mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2025-04-30 14:24:37 +00:00
refactor: sync code from uoj.ac
This commit is contained in:
parent
26809917a1
commit
844c93da84
16
.github/workflows/test.yml
vendored
16
.github/workflows/test.yml
vendored
@ -1,16 +0,0 @@
|
||||
name: Lint & Test
|
||||
|
||||
on:
|
||||
- push
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
php-cs-fixer:
|
||||
name: PHP-CS-Fixer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: PHP-CS-Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
with:
|
||||
args: --config=./web/.php-cs-fixer.php --diff --dry-run
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
uoj_data/
|
||||
uoj_data_1/
|
||||
uoj_data_2/
|
||||
.php-cs-fixer.cache
|
||||
docker-compose.local.yml
|
||||
|
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "linux-gcc-x64"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"intelephense.format.braces": "k&r",
|
||||
"intelephense.completion.triggerParameterHints": false
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
FROM mysql:5.7
|
||||
FROM mysql:8.0
|
||||
|
||||
ADD . /opt/uoj_db
|
||||
WORKDIR /opt/uoj_db
|
||||
|
@ -1,2 +1,2 @@
|
||||
USE `app_uoj233`;
|
||||
insert into judger_info (judger_name, password, ip) values ('compose_judger', '_judger_password_', 'uoj-judger');
|
||||
insert into judger_info (judger_name, password, ip, display_name, description) values ('compose_judger', '_judger_password_', 'uoj-judger', '内建 Judger', '');
|
||||
|
@ -30,18 +30,18 @@ USE `app_uoj233`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `best_ac_submissions` (
|
||||
`problem_id` int(11) NOT NULL,
|
||||
`problem_id` int NOT NULL,
|
||||
`submitter` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`submission_id` int(11) NOT NULL,
|
||||
`used_time` int(11) NOT NULL,
|
||||
`used_memory` int(11) NOT NULL,
|
||||
`tot_size` int(11) NOT NULL,
|
||||
`shortest_id` int(11) NOT NULL,
|
||||
`shortest_used_time` int(11) NOT NULL,
|
||||
`shortest_used_memory` int(11) NOT NULL,
|
||||
`shortest_tot_size` int(11) NOT NULL,
|
||||
`submission_id` int NOT NULL,
|
||||
`used_time` int NOT NULL,
|
||||
`used_memory` int NOT NULL,
|
||||
`tot_size` int NOT NULL,
|
||||
`shortest_id` int NOT NULL,
|
||||
`shortest_used_time` int NOT NULL,
|
||||
`shortest_used_memory` int NOT NULL,
|
||||
`shortest_tot_size` int NOT NULL,
|
||||
PRIMARY KEY (`problem_id`,`submitter`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci TABLESPACE `innodb_system`;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -60,16 +60,20 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `blogs` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`post_time` datetime NOT NULL,
|
||||
`active_time` datetime NOT NULL,
|
||||
`poster` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content_md` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`zan` int(11) NOT NULL,
|
||||
`content_md` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`zan` int NOT NULL DEFAULT '0',
|
||||
`is_hidden` tinyint(1) NOT NULL,
|
||||
`type` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'B',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `post_time` (`post_time`),
|
||||
KEY `active_time` (`active_time`),
|
||||
KEY `poster` (`poster`,`is_hidden`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -89,14 +93,19 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `blogs_comments` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`blog_id` int(11) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`blog_id` int NOT NULL,
|
||||
`content` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`post_time` datetime NOT NULL,
|
||||
`poster` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`zan` int(11) NOT NULL,
|
||||
`reply_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
`zan` int NOT NULL,
|
||||
`reply_id` int NOT NULL,
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`reason_to_hide` varchar(10000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `reply_id` (`reply_id`,`id`),
|
||||
KEY `blog_id` (`blog_id`,`post_time`),
|
||||
KEY `blog_id_2` (`blog_id`,`reply_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -116,8 +125,8 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `blogs_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`blog_id` int(11) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`blog_id` int NOT NULL,
|
||||
`tag` varchar(30) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `blog_id` (`blog_id`),
|
||||
@ -143,8 +152,8 @@ UNLOCK TABLES;
|
||||
CREATE TABLE `click_zans` (
|
||||
`type` char(2) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`target_id` int(11) NOT NULL,
|
||||
`val` tinyint(4) NOT NULL DEFAULT '1',
|
||||
`target_id` int NOT NULL,
|
||||
`val` tinyint NOT NULL DEFAULT '1',
|
||||
PRIMARY KEY (`type`,`target_id`,`username`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@ -165,15 +174,17 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`start_time` datetime NOT NULL,
|
||||
`last_min` int(11) NOT NULL,
|
||||
`player_num` int(11) NOT NULL,
|
||||
`status` varchar(50) NOT NULL,
|
||||
`extra_config` varchar(200) NOT NULL,
|
||||
`zan` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
`end_time` datetime GENERATED ALWAYS AS ((`start_time` + interval `last_min` minute)) VIRTUAL NOT NULL,
|
||||
`last_min` int NOT NULL,
|
||||
`player_num` int NOT NULL DEFAULT '0',
|
||||
`status` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`extra_config` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '{}',
|
||||
`zan` int NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `status` (`status`,`id`) USING BTREE
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -193,15 +204,17 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_asks` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`contest_id` int NOT NULL,
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`question` text NOT NULL,
|
||||
`answer` text NOT NULL,
|
||||
`post_time` datetime NOT NULL,
|
||||
`reply_time` datetime NOT NULL,
|
||||
`is_hidden` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `contest_id` (`contest_id`,`is_hidden`,`username`) USING BTREE,
|
||||
KEY `username` (`username`,`contest_id`) USING BTREE
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -221,7 +234,7 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_notice` (
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`contest_id` int NOT NULL,
|
||||
`title` varchar(30) NOT NULL,
|
||||
`content` varchar(500) NOT NULL,
|
||||
`time` datetime NOT NULL,
|
||||
@ -246,7 +259,7 @@ UNLOCK TABLES;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_permissions` (
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`contest_id` int NOT NULL,
|
||||
PRIMARY KEY (`username`,`contest_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@ -267,10 +280,11 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_problems` (
|
||||
`problem_id` int(11) NOT NULL,
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`dfn` int(11) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`problem_id`,`contest_id`)
|
||||
`problem_id` int NOT NULL,
|
||||
`contest_id` int NOT NULL,
|
||||
`level` int NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`problem_id`,`contest_id`),
|
||||
KEY `contest_id` (`contest_id`,`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -291,9 +305,9 @@ UNLOCK TABLES;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_registrants` (
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`contest_id` int NOT NULL,
|
||||
`has_participated` tinyint(1) NOT NULL,
|
||||
`rank` int(11) NOT NULL,
|
||||
`final_rank` int NOT NULL,
|
||||
PRIMARY KEY (`contest_id`,`username`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@ -314,12 +328,14 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_submissions` (
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`contest_id` int NOT NULL,
|
||||
`submitter` varchar(20) NOT NULL,
|
||||
`problem_id` int(11) NOT NULL,
|
||||
`submission_id` int(11) NOT NULL,
|
||||
`score` int(11) NOT NULL,
|
||||
`penalty` int(11) NOT NULL,
|
||||
`problem_id` int NOT NULL,
|
||||
`submission_id` int NOT NULL,
|
||||
`score` int NOT NULL,
|
||||
`penalty` int NOT NULL,
|
||||
`cnt` int DEFAULT NULL,
|
||||
`n_failures` int DEFAULT NULL,
|
||||
PRIMARY KEY (`contest_id`,`submitter`,`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@ -340,11 +356,13 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `contests_reviews` (
|
||||
`contest_id` int(11) NOT NULL,
|
||||
`problem_id` int(11) NOT NULL DEFAULT 0,
|
||||
`contest_id` int NOT NULL,
|
||||
`problem_id` int NOT NULL DEFAULT 0,
|
||||
`poster` varchar(20) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
PRIMARY KEY (`contest_id`,`problem_id`,`poster`)
|
||||
PRIMARY KEY (`contest_id`,`problem_id`,`poster`),
|
||||
KEY `contest_id` (`contest_id`,`problem_id`),
|
||||
KEY `poster` (`poster`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -364,7 +382,7 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `countdowns` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` text NOT NULL,
|
||||
`end_time` datetime NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
@ -387,8 +405,8 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `custom_test_submissions` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int(10) unsigned NOT NULL,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int UNSIGNED NOT NULL,
|
||||
`submit_time` datetime NOT NULL,
|
||||
`submitter` varchar(20) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
@ -396,8 +414,10 @@ CREATE TABLE `custom_test_submissions` (
|
||||
`result` blob NOT NULL,
|
||||
`status` varchar(20) NOT NULL,
|
||||
`status_details` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `submitter` (`submitter`,`problem_id`,`id`),
|
||||
KEY `judge_time` (`judge_time`,`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -416,10 +436,10 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `friend_links` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(40) NOT NULL,
|
||||
`url` varchar(100) NOT NULL,
|
||||
`level` int(10) NOT NULL DEFAULT 10,
|
||||
`level` int NOT NULL DEFAULT 10,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@ -440,7 +460,7 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` text NOT NULL,
|
||||
`announcement` text NOT NULL DEFAULT '',
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT 0,
|
||||
@ -455,10 +475,11 @@ CREATE TABLE `groups` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `groups_assignments` (
|
||||
`group_id` int(11) NOT NULL,
|
||||
`list_id` int(11) NOT NULL,
|
||||
`group_id` int NOT NULL,
|
||||
`list_id` int NOT NULL,
|
||||
`end_time` datetime NOT NULL,
|
||||
PRIMARY KEY (`group_id`, `list_id`)
|
||||
PRIMARY KEY (`group_id`, `list_id`),
|
||||
KEY `list_id` (`list_id`,`group_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -469,9 +490,11 @@ CREATE TABLE `groups_assignments` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `groups_users` (
|
||||
`group_id` int(11) NOT NULL,
|
||||
`group_id` int NOT NULL,
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`group_id`, `username`)
|
||||
PRIMARY KEY (`group_id`, `username`),
|
||||
KEY `group_id` (`group_id`, `username`),
|
||||
KEY `username` (`username`, `group_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -482,23 +505,26 @@ CREATE TABLE `groups_users` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `hacks` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int(10) unsigned NOT NULL,
|
||||
`contest_id` int(10) unsigned DEFAULT NULL,
|
||||
`submission_id` int(10) unsigned NOT NULL,
|
||||
`hacker` varchar(20) NOT NULL,
|
||||
`owner` varchar(20) NOT NULL,
|
||||
`input` varchar(150) NOT NULL,
|
||||
`input_type` char(20) NOT NULL,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int UNSIGNED NOT NULL,
|
||||
`contest_id` int UNSIGNED DEFAULT NULL,
|
||||
`submission_id` int UNSIGNED NOT NULL,
|
||||
`hacker` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`owner` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`input` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`input_type` char(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`submit_time` datetime NOT NULL,
|
||||
`judge_time` datetime DEFAULT NULL,
|
||||
`success` tinyint(1) DEFAULT NULL,
|
||||
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`details` blob NOT NULL,
|
||||
`is_hidden` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `submission_id` (`submission_id`),
|
||||
KEY `is_hidden` (`is_hidden`,`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
KEY `is_hidden` (`is_hidden`,`problem_id`),
|
||||
KEY `status` (`status`),
|
||||
KEY `judge_time` (`judge_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -539,11 +565,14 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `judger_info` (
|
||||
`judger_name` varchar(50) NOT NULL,
|
||||
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
|
||||
`ip` char(20) NOT NULL,
|
||||
`judger_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`password` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`ip` char(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`enabled` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`display_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`description` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`judger_name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -555,6 +584,26 @@ LOCK TABLES `judger_info` WRITE;
|
||||
/*!40000 ALTER TABLE `judger_info` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `meta`
|
||||
--
|
||||
|
||||
CREATE TABLE `meta` (
|
||||
`name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`value` json NOT NULL,
|
||||
`updated_at` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `meta`
|
||||
--
|
||||
|
||||
LOCK TABLES `meta` WRITE;
|
||||
/*!40000 ALTER TABLE `meta` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `meta` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `problems`
|
||||
--
|
||||
@ -562,18 +611,20 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `problems` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` text NOT NULL,
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT,
|
||||
`title` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`uploader` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`submission_requirement` text,
|
||||
`submission_requirement` mediumtext COLLATE utf8mb4_unicode_ci,
|
||||
`hackable` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`extra_config` varchar(500) NOT NULL DEFAULT '{"view_content_type":"ALL","view_details_type":"ALL"}',
|
||||
`extra_config` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '{"view_content_type":"ALL","view_details_type":"ALL"}',
|
||||
`zan` int(11) NOT NULL DEFAULT '0',
|
||||
`ac_num` int(11) NOT NULL DEFAULT '0',
|
||||
`submit_num` int(11) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
`assigned_to_judger` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'any',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `assigned_to_judger` (`assigned_to_judger`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci TABLESPACE `innodb_system`;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -592,11 +643,11 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `problems_contents` (
|
||||
`id` int(11) NOT NULL,
|
||||
`statement` mediumtext NOT NULL,
|
||||
`statement_md` mediumtext NOT NULL,
|
||||
`id` int NOT NULL,
|
||||
`statement` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`statement_md` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -616,9 +667,10 @@ UNLOCK TABLES;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `problems_permissions` (
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`problem_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`username`,`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
`problem_id` int NOT NULL,
|
||||
PRIMARY KEY (`username`,`problem_id`),
|
||||
KEY `problem_id` (`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -637,9 +689,10 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `problems_solutions` (
|
||||
`problem_id` int(11) NOT NULL,
|
||||
`blog_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`problem_id`, `blog_id`)
|
||||
`problem_id` int NOT NULL,
|
||||
`blog_id` int NOT NULL,
|
||||
PRIMARY KEY (`problem_id`, `blog_id`),
|
||||
KEY `problem_id` (`problem_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -659,8 +712,8 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `problems_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int(11) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int NOT NULL,
|
||||
`tag` varchar(30) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `problem_id` (`problem_id`),
|
||||
@ -684,7 +737,7 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `lists` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` text NOT NULL,
|
||||
`description` text NOT NULL DEFAULT '',
|
||||
`is_hidden` tinyint(1) NOT NULL DEFAULT '0',
|
||||
@ -699,9 +752,10 @@ CREATE TABLE `lists` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `lists_problems` (
|
||||
`list_id` int(11) NOT NULL,
|
||||
`problem_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`list_id`, `problem_id`)
|
||||
`list_id` int NOT NULL,
|
||||
`problem_id` int NOT NULL,
|
||||
PRIMARY KEY (`list_id`, `problem_id`),
|
||||
KEY `list_id` (`list_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -712,8 +766,8 @@ CREATE TABLE `lists_problems` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `lists_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`list_id` int(11) NOT NULL,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`list_id` int NOT NULL,
|
||||
`tag` varchar(30) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `list_id` (`list_id`),
|
||||
@ -728,14 +782,14 @@ CREATE TABLE `lists_tags` (
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `search_requests` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`created_at` datetime NOT NULL,
|
||||
`remote_addr` varchar(50) NOT NULL,
|
||||
`type` enum('search','autocomplete') NOT NULL,
|
||||
`cache_id` int(11) NOT NULL,
|
||||
`q` varchar(100) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`result` mediumtext NOT NULL,
|
||||
`remote_addr` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`type` enum('search','autocomplete') COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`cache_id` int NOT NULL,
|
||||
`q` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`result` json NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `remote_addr` (`remote_addr`,`created_at`),
|
||||
KEY `created_at` (`created_at`)
|
||||
@ -758,27 +812,42 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `submissions` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int(10) unsigned NOT NULL,
|
||||
`contest_id` int(10) unsigned DEFAULT NULL,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`problem_id` int UNSIGNED NOT NULL,
|
||||
`contest_id` int UNSIGNED DEFAULT NULL,
|
||||
`submit_time` datetime NOT NULL,
|
||||
`submitter` varchar(20) NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`language` varchar(15) NOT NULL,
|
||||
`tot_size` int(11) NOT NULL,
|
||||
`submitter` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`language` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`tot_size` int NOT NULL,
|
||||
`judge_reason` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`judge_time` datetime DEFAULT NULL,
|
||||
`result` blob NOT NULL,
|
||||
`status` varchar(20) NOT NULL,
|
||||
`result_error` varchar(20) DEFAULT NULL,
|
||||
`score` int(11) DEFAULT NULL,
|
||||
`used_time` int(11) NOT NULL DEFAULT '0',
|
||||
`used_memory` int(11) NOT NULL DEFAULT '0',
|
||||
`judger` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`result` mediumblob NOT NULL,
|
||||
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`result_error` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`score` int DEFAULT NULL,
|
||||
`hide_score_to_others` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`hidden_score` int DEFAULT NULL,
|
||||
`used_time` int NOT NULL DEFAULT '0',
|
||||
`used_memory` int NOT NULL DEFAULT '0',
|
||||
`is_hidden` tinyint(1) NOT NULL,
|
||||
`status_details` varchar(100) NOT NULL,
|
||||
`status_details` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `is_hidden` (`is_hidden`,`problem_id`),
|
||||
KEY `score` (`problem_id`, `submitter`, `score`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
KEY `status` (`status`,`id`),
|
||||
KEY `result_error` (`result_error`),
|
||||
KEY `problem_id` (`problem_id`,`id`),
|
||||
KEY `language` (`language`,`id`),
|
||||
KEY `language2` (`is_hidden`,`language`,`id`),
|
||||
KEY `user_score` (`problem_id`,`submitter`,`score`,`id`),
|
||||
KEY `problem_id2` (`is_hidden`,`problem_id`,`id`),
|
||||
KEY `id2` (`is_hidden`,`id`),
|
||||
KEY `problem_score2` (`is_hidden`,`problem_id`,`score`,`id`),
|
||||
KEY `contest_submission_status` (`contest_id`,`status`),
|
||||
KEY `submitter2` (`is_hidden`,`submitter`,`id`),
|
||||
KEY `submitter` (`submitter`,`id`) USING BTREE,
|
||||
KEY `contest_id` (`contest_id`,`is_hidden`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -790,6 +859,83 @@ LOCK TABLES `submissions` WRITE;
|
||||
/*!40000 ALTER TABLE `submissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `submissions_history`
|
||||
--
|
||||
|
||||
CREATE TABLE `submissions_history` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`submission_id` int UNSIGNED NOT NULL,
|
||||
`judge_reason` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`judge_time` datetime DEFAULT NULL,
|
||||
`judger` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`result` mediumblob NOT NULL,
|
||||
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`status_details` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`result_error` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`score` int DEFAULT NULL,
|
||||
`used_time` int NOT NULL DEFAULT '0',
|
||||
`used_memory` int NOT NULL DEFAULT '0',
|
||||
`major` tinyint(1) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `submission_judge_time` (`submission_id`,`judge_time`,`id`),
|
||||
KEY `submission` (`submission_id`,`id`),
|
||||
KEY `status_major` (`status`,`major`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `submissions_history`
|
||||
--
|
||||
|
||||
LOCK TABLES `submissions_history` WRITE;
|
||||
/*!40000 ALTER TABLE `submissions_history` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `submissions_history` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `system_updates`
|
||||
--
|
||||
|
||||
CREATE TABLE `system_updates` (
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`time` datetime NOT NULL,
|
||||
`type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`target_id` int UNSIGNED NOT NULL,
|
||||
`message` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `type_id_time` (`type`,`target_id`,`time`),
|
||||
KEY `type_time` (`type`,`time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `system_updates`
|
||||
--
|
||||
|
||||
LOCK TABLES `system_updates` WRITE;
|
||||
/*!40000 ALTER TABLE `system_updates` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `system_updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `upgrades`
|
||||
--
|
||||
|
||||
CREATE TABLE `upgrades` (
|
||||
`name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`status` enum('up','down') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime NOT NULL,
|
||||
PRIMARY KEY (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data for table `upgrades`
|
||||
--
|
||||
|
||||
LOCK TABLES `upgrades` WRITE;
|
||||
/*!40000 ALTER TABLE `upgrades` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `upgrades` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `user_info`
|
||||
--
|
||||
@ -797,32 +943,29 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `user_info` (
|
||||
`usergroup` char(1) NOT NULL DEFAULT 'U',
|
||||
`usergroup` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'U',
|
||||
`username` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`usertype` varchar(250) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'student',
|
||||
`realname` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`school` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`usertype` varchar(250) NOT NULL DEFAULT 'student',
|
||||
`email` varchar(50) NOT NULL,
|
||||
`password` char(32) NOT NULL,
|
||||
`svn_password` char(10) NOT NULL,
|
||||
`qq` bigint(20) NOT NULL,
|
||||
`sex` char(1) NOT NULL DEFAULT 'U',
|
||||
`ac_num` int(11) NOT NULL,
|
||||
`email` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`password` char(32) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`svn_password` char(10) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`qq` bigint NOT NULL DEFAULT '0',
|
||||
`sex` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'U',
|
||||
`ac_num` int NOT NULL DEFAULT 0,
|
||||
`register_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`remote_addr` varchar(50) NOT NULL,
|
||||
`http_x_forwarded_for` varchar(50) NOT NULL,
|
||||
`remember_token` char(60) NOT NULL,
|
||||
`motto` varchar(200) NOT NULL,
|
||||
`last_login` timestamp NOT NULL DEFAULT 0,
|
||||
`last_visited` timestamp NOT NULL DEFAULT 0,
|
||||
`images_size_limit` int(11) UNSIGNED NOT NULL DEFAULT 104857600, /* 100 MiB */
|
||||
`codeforces_handle` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`github` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`website` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`avatar_source` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'gravatar',
|
||||
`last_login_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_visit_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
`expiration_time` datetime DEFAULT NULL,
|
||||
`remote_addr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`http_x_forwarded_for` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`remember_token` char(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`motto` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
|
||||
`extra` json NOT NULL,
|
||||
PRIMARY KEY (`username`),
|
||||
KEY `ac_num` (`ac_num`,`username`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
@ -841,13 +984,13 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `users_images` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`path` varchar(100) NOT NULL,
|
||||
`uploader` varchar(20) NOT NULL,
|
||||
`width` int(11) NOT NULL,
|
||||
`height` int(11) NOT NULL,
|
||||
`width` int NOT NULL,
|
||||
`height` int NOT NULL,
|
||||
`upload_time` datetime NOT NULL,
|
||||
`size` int(11) NOT NULL,
|
||||
`size` int NOT NULL,
|
||||
`hash` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uploader` (`uploader`),
|
||||
@ -874,13 +1017,16 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `user_msg` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`sender` varchar(20) NOT NULL,
|
||||
`receiver` varchar(20) NOT NULL,
|
||||
`message` varchar(5000) NOT NULL,
|
||||
`send_time` datetime NOT NULL,
|
||||
`read_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `sender` (`sender`),
|
||||
KEY `receiver` (`receiver`),
|
||||
KEY `read_time` (`receiver`,`read_time`) USING BTREE
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@ -900,13 +1046,14 @@ UNLOCK TABLES;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `user_system_msg` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`id` int NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`content` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`receiver` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`send_time` datetime NOT NULL,
|
||||
`read_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `receiver` (`receiver`,`read_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
|
@ -24,6 +24,8 @@ services:
|
||||
build:
|
||||
context: ./judger/
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- USE_MIRROR=1
|
||||
container_name: uoj-judger
|
||||
restart: always
|
||||
stdin_open: true
|
||||
@ -44,6 +46,8 @@ services:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: web/Dockerfile
|
||||
args:
|
||||
- USE_MIRROR=1
|
||||
container_name: uoj-web
|
||||
restart: always
|
||||
stdin_open: true
|
||||
|
@ -1,15 +1,24 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG CLONE_ADDFLAG
|
||||
ARG USE_MIRROR
|
||||
ENV USE_MIRROR $USE_MIRROR
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get update && apt-get install -y vim ntp zip unzip curl wget build-essential fp-compiler python2.7 python3.10 python3-requests libseccomp-dev openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk
|
||||
ENV PKGS="vim ntp zip unzip curl wget build-essential fp-compiler python2.7 python3.10 python3-requests libseccomp-dev openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk"
|
||||
RUN if [[ "$USE_MIRROR" == "1" ]]; then\
|
||||
sed -i "s@http://.*archive.ubuntu.com@http://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list &&\
|
||||
sed -i "s@http://.*security.ubuntu.com@http://mirrors.tuna.tsinghua.edu.cn@g" /etc/apt/sources.list ;\
|
||||
fi &&\
|
||||
apt-get update &&\
|
||||
(apt-get install -y --allow-unauthenticated --no-install-recommends -o Dpkg::Options::="--force-overwrite" -o APT::Acquire::Retries="30" --fix-missing $PKGS || apt --fix-broken install -y || apt-get install -y --allow-unauthenticated --no-install-recommends -o Dpkg::Options::="--force-overwrite" -o APT::Acquire::Retries="30" --fix-missing $PKGS)
|
||||
|
||||
ADD . /opt/uoj_judger
|
||||
WORKDIR /opt/uoj_judger
|
||||
|
||||
# Install environment and set startup script
|
||||
RUN sh install.sh -p && echo "\
|
||||
RUN sh install.sh -p && echo -e "\
|
||||
#!/bin/sh\n\
|
||||
if [ ! -f \"/opt/uoj_judger/.conf.json\" ]; then\n\
|
||||
cd /opt/uoj_judger && sh install.sh -i\n\
|
||||
|
@ -35,12 +35,15 @@ const std::vector<std::pair<const char *, const char *>> suffix_search_list = {
|
||||
{".code" , "" },
|
||||
{"20.cpp" , "C++20" },
|
||||
{"17.cpp" , "C++17" },
|
||||
{"14.cpp" , "C++14" },
|
||||
{"14.cpp" , "C++" },
|
||||
{"11.cpp" , "C++11" },
|
||||
{".cpp" , "C++" },
|
||||
{"03.cpp" , "C++03" },
|
||||
{"98.cpp" , "C++98" },
|
||||
{".cpp" , "C++" },
|
||||
{".c" , "C" },
|
||||
{".pas" , "Pascal" },
|
||||
{"2.7.py" , "Python2.7"},
|
||||
{"2.py" , "Python2.7"},
|
||||
{".py" , "Python3" },
|
||||
{"7.java" , "Java7" },
|
||||
{"8.java" , "Java8" },
|
||||
|
@ -1,18 +1,30 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG CLONE_ADDFLAG
|
||||
ARG USE_MIRROR
|
||||
ENV USE_MIRROR $USE_MIRROR
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN dpkg -s gnupg 2>/dev/null || (apt-get update && apt-get install -y gnupg) &&\
|
||||
echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" | tee /etc/apt/sources.list.d/ondrej-php.list && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4F4EA0AAE5267A6C &&\
|
||||
apt-get update --allow-unauthenticated &&\
|
||||
apt-get install -y --allow-unauthenticated -o Dpkg::Options::="--force-overwrite" php7.4 php7.4-yaml php7.4-xml php7.4-dev php7.4-zip php7.4-mysql php7.4-mbstring php7.4-gd php7.4-imagick libseccomp-dev git vim ntp zip unzip curl wget libapache2-mod-xsendfile mysql-server php-pear cmake fp-compiler re2c libyaml-dev python2.7 python3.10 python3-requests openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk
|
||||
ENV PKGS="php7.4 php7.4-yaml php7.4-xml php7.4-dev php7.4-zip php7.4-mysql php7.4-mbstring php7.4-gd php7.4-imagick libseccomp-dev git vim ntp zip unzip curl wget apache2 libapache2-mod-xsendfile php-pear mysql-client build-essential fp-compiler re2c libseccomp-dev libyaml-dev python2.7 python3.10 python3-requests openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk"
|
||||
RUN if [[ "$USE_MIRROR" == "1" ]]; then\
|
||||
sed -i "s@http://.*archive.ubuntu.com@https://mirrors.aliyun.com@g" /etc/apt/sources.list &&\
|
||||
sed -i "s@http://.*security.ubuntu.com@https://mirrors.aliyun.com@g" /etc/apt/sources.list ;\
|
||||
fi &&\
|
||||
apt-get -o "Acquire::https::Verify-Peer=false" update && apt-get -o "Acquire::https::Verify-Peer=false" install -y --no-install-recommends gnupg ca-certificates &&\
|
||||
echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu jammy main" | tee /etc/apt/sources.list.d/ondrej-php.list && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4F4EA0AAE5267A6C &&\
|
||||
if [[ "$USE_MIRROR" == "1" ]]; then\
|
||||
find /etc/apt/sources.list.d/ -type f -name "*.list" -exec sed -i.bak -r 's#deb(-src)?\s*http(s)?://ppa.launchpad.net#deb\1 https://launchpad.proxy.ustclug.org#ig' {} \; &&\
|
||||
find /etc/apt/sources.list.d/ -type f -name "*.list" -exec sed -i.bak -r 's#deb(-src)?\s*http(s)?://ppa.launchpadcontent.net#deb\1 https://launchpad.proxy.ustclug.org#ig' {} \; ;\
|
||||
fi &&\
|
||||
apt-get update --allow-unauthenticated &&\
|
||||
(apt-get install -y --allow-unauthenticated --no-install-recommends -o Dpkg::Options::="--force-overwrite" -o APT::Acquire::Retries="30" --fix-missing $PKGS || apt-get install --fix-broken -y -o APT::Acquire::Retries="30")
|
||||
|
||||
ADD . /opt/uoj
|
||||
WORKDIR /opt/uoj
|
||||
|
||||
# Install environment and set startup script
|
||||
RUN sh web/install.sh -p && echo "\
|
||||
RUN sh web/install.sh -p && echo -e "\
|
||||
#!/bin/sh\n\
|
||||
if [ ! -f \"/var/uoj_data/.UOJSetupDone\" ]; then\n\
|
||||
cd /opt/uoj/web && sh install.sh -i\n\
|
||||
|
@ -21,12 +21,12 @@ return [
|
||||
'main' => [
|
||||
'protocol' => 'http',
|
||||
'host' => '_httpHost_',
|
||||
'port' => 80
|
||||
'port' => '80/443'
|
||||
],
|
||||
'blog' => [
|
||||
'protocol' => 'http',
|
||||
'host' => '_httpHost_',
|
||||
'port' => 80
|
||||
'port' => '80/443'
|
||||
]
|
||||
],
|
||||
'security' => [
|
||||
@ -54,7 +54,6 @@ return [
|
||||
],
|
||||
'switch' => [
|
||||
'blog-domain-mode' => 3,
|
||||
'force-login' => true,
|
||||
'open-register' => false
|
||||
]
|
||||
];
|
||||
|
@ -1,101 +1,103 @@
|
||||
<?php
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!isNormalUser($myUser)) {
|
||||
become403Page();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
isSuperUser(Auth::user()) || UOJResponse::page403();
|
||||
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!isSuperUser($myUser)) {
|
||||
become403Page();
|
||||
}
|
||||
$time_form = new UOJForm('time');
|
||||
$time_form->addVInput(
|
||||
'name', 'text', '比赛标题', 'New Contest',
|
||||
function($name, &$vdata) {
|
||||
if ($name == '') {
|
||||
return '标题不能为空';
|
||||
}
|
||||
|
||||
if (strlen($name) > 100) {
|
||||
return '标题过长';
|
||||
}
|
||||
$time_form = new UOJBs4Form('time');
|
||||
$time_form->addVInput(
|
||||
'name',
|
||||
'text',
|
||||
'比赛标题',
|
||||
'New Contest',
|
||||
function ($name, &$vdata) {
|
||||
if ($name == '') {
|
||||
return '标题不能为空';
|
||||
}
|
||||
|
||||
$name = HTML::escape($name);
|
||||
if (strlen($name) > 100) {
|
||||
return '标题过长';
|
||||
}
|
||||
|
||||
if ($name === '') {
|
||||
return '无效编码';
|
||||
}
|
||||
$name = HTML::escape($name);
|
||||
|
||||
$vdata['name'] = $name;
|
||||
if ($name === '') {
|
||||
return '无效编码';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addVInput(
|
||||
'start_time', 'text', '开始时间', date("Y-m-d H:i:s"),
|
||||
function($str, &$vdata) {
|
||||
try {
|
||||
$vdata['start_time'] = new DateTime($str);
|
||||
} catch (Exception $e) {
|
||||
return '无效时间格式';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addVInput(
|
||||
'last_min', 'text', '时长(单位:分钟)', 180,
|
||||
function($str, &$vdata) {
|
||||
if (!validateUInt($str)) {
|
||||
return '必须为一个整数';
|
||||
}
|
||||
$vdata['name'] = $name;
|
||||
|
||||
$vdata['last_min'] = $str;
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addVInput(
|
||||
'start_time',
|
||||
'text',
|
||||
'开始时间',
|
||||
date("Y-m-d H:i:s"),
|
||||
function ($str, &$vdata) {
|
||||
try {
|
||||
$vdata['start_time'] = new DateTime($str);
|
||||
} catch (Exception $e) {
|
||||
return '无效时间格式';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->addVInput(
|
||||
'last_min',
|
||||
'text',
|
||||
'时长(单位:分钟)',
|
||||
180,
|
||||
function ($str, &$vdata) {
|
||||
if (!validateUInt($str)) {
|
||||
return '必须为一个整数';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->handle = function(&$vdata) {
|
||||
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
|
||||
$esc_name = DB::escape($vdata['name']);
|
||||
$esc_last_min = DB::escape($vdata['last_min']);
|
||||
|
||||
DB::query("insert into contests (name, start_time, last_min, status) values ('$esc_name', '$start_time_str', $esc_last_min, 'unfinished')");
|
||||
};
|
||||
$time_form->succ_href = "/contests";
|
||||
$time_form->runAtServer();
|
||||
?>
|
||||
$vdata['last_min'] = $str;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$time_form->handle = function (&$vdata) {
|
||||
$start_time_str = $vdata['start_time']->format('Y-m-d H:i:s');
|
||||
|
||||
DB::insert([
|
||||
"insert into contests",
|
||||
"(name, start_time, last_min, status)", "values",
|
||||
DB::tuple([$vdata['name'], $start_time_str, $vdata['last_min'], 'unfinished'])
|
||||
]);
|
||||
};
|
||||
$time_form->succ_href = "/contests";
|
||||
$time_form->runAtServer();
|
||||
?>
|
||||
<?php echoUOJPageHeader('添加比赛') ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
<h1 class="card-title">添加比赛</h1>
|
||||
|
||||
<h1 class="h2 card-title">添加比赛</h1>
|
||||
<div class="w-full" style="max-width: 400px">
|
||||
<?php $time_form->printHTML(); ?>
|
||||
</div>
|
||||
|
||||
<div class="w-full" style="max-width: 400px">
|
||||
<?php $time_form->printHTML(); ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar', array()) ?>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end left col -->
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,73 +1,57 @@
|
||||
<?php
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('announcements')) ?>
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<h1>
|
||||
<?= UOJLocale::get('announcements') ?>
|
||||
</h1>
|
||||
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
function echoBlogCell($blog) {
|
||||
$level = $blog['level'];
|
||||
|
||||
switch ($level) {
|
||||
case 0:
|
||||
$level_str = '';
|
||||
break;
|
||||
case 1:
|
||||
$level_str = '<span style="color:red">[三级置顶]</span> ';
|
||||
break;
|
||||
case 2:
|
||||
$level_str = '<span style="color:red">[二级置顶]</span> ';
|
||||
break;
|
||||
case 3:
|
||||
$level_str = '<span style="color:red">[一级置顶]</span> ';
|
||||
break;
|
||||
}
|
||||
|
||||
echo '<tr>';
|
||||
echo '<td>' . $level_str . getBlogLink($blog['id']) . '</td>';
|
||||
echo '<td>' . getUserLink($blog['poster']) . '</td>';
|
||||
echo '<td>' . $blog['post_time'] . '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
$header = <<<EOD
|
||||
<?php
|
||||
echoLongTable(
|
||||
['blogs.id', 'poster', 'title', 'post_time', 'zan', 'level'],
|
||||
'important_blogs, blogs',
|
||||
[
|
||||
'is_hidden' => 0,
|
||||
'important_blogs.blog_id' => DB::raw('blogs.id')
|
||||
],
|
||||
'order by level desc, important_blogs.blog_id desc',
|
||||
<<<EOD
|
||||
<tr>
|
||||
<th width="60%">标题</th>
|
||||
<th width="20%">发表者</th>
|
||||
<th width="20%">发表日期</th>
|
||||
</tr>
|
||||
EOD;
|
||||
$config = [
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'my-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
];
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('announcements')) ?>
|
||||
EOD,
|
||||
function ($info) {
|
||||
$blog = new UOJBlog($info);
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
echo '<tr>';
|
||||
echo '<td>' . $blog->getLink(['show_level' => true, 'show_new_tag' => true]) . '</td>';
|
||||
echo '<td>' . getUserLink($blog->info['poster']) . '</td>';
|
||||
echo '<td>' . $blog->info['post_time'] . '</td>';
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'my-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
|
||||
<h1 class="h2">
|
||||
<?= UOJLocale::get('announcements') ?>
|
||||
</h1>
|
||||
|
||||
<?php echoLongTable(array('blogs.id', 'poster', 'title', 'post_time', 'zan', 'level'), 'important_blogs, blogs', 'is_hidden = 0 and important_blogs.blog_id = blogs.id', 'order by level desc, important_blogs.blog_id desc', $header, 'echoBlogCell', $config); ?>
|
||||
|
||||
</div>
|
||||
<!-- end left col -->
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar', array()) ?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
</div>
|
||||
<!-- end left col -->
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,15 +1,6 @@
|
||||
<?php
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJBlog::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($blog = queryBlog($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
redirectTo(HTML::blog_url($blog['poster'], '/post/'.$_GET['id'] . ($_GET['sub'] ?: '')));
|
||||
?>
|
||||
redirectTo(HTML::blog_url(UOJBlog::info('poster'), '/post/' . UOJBlog::info('id'), ['escape' => false]));
|
||||
|
@ -1,83 +1,80 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
?>
|
||||
Auth::check() || redirectToLogin();
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('blogs')) ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<!-- title container -->
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center">
|
||||
<h1>
|
||||
<?= UOJLocale::get("blogs overview") ?>
|
||||
</h1>
|
||||
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<?php if (Auth::check()) : ?>
|
||||
<div class="text-end">
|
||||
<div class="btn-group">
|
||||
<a href="<?= HTML::blog_url(Auth::id(), '/') ?>" class="btn btn-secondary btn-sm">
|
||||
我的博客首页
|
||||
</a>
|
||||
<a href="<?= HTML::blog_url(Auth::id(), '/post/new/write') ?>" class="btn btn-primary btn-sm">
|
||||
<i class="bi bi-pencil"></i>
|
||||
写新博客
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<!-- end title container -->
|
||||
|
||||
<!-- title container -->
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center">
|
||||
|
||||
<h1 class="h2">
|
||||
<?= UOJLocale::get("blogs overview") ?>
|
||||
</h1>
|
||||
|
||||
<div class="text-end">
|
||||
<div class="btn-group">
|
||||
<a href="<?= HTML::blog_url(Auth::id(), '/') ?>" class="btn btn-secondary btn-sm">
|
||||
我的博客首页
|
||||
</a>
|
||||
<a href="<?= HTML::blog_url(Auth::id(), '/post/new/write')?>" class="btn btn-primary btn-sm">
|
||||
<i class="bi bi-pencil"></i>
|
||||
写新博客
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end title container -->
|
||||
|
||||
<?php
|
||||
echoLongTable(
|
||||
['id', 'poster', 'title', 'post_time', 'zan', 'is_hidden'],
|
||||
'blogs',
|
||||
isSuperUser($myUser) ? "1" : "is_hidden = 0 or poster = '{$myUser['username']}'",
|
||||
'order by post_time desc',
|
||||
<<<EOD
|
||||
<?php
|
||||
echoLongTable(
|
||||
['id', 'poster', 'title', 'post_time', 'zan', 'is_hidden'],
|
||||
'blogs',
|
||||
isSuperUser($myUser) ? "1" : "is_hidden = 0 or poster = '{$myUser['username']}'",
|
||||
'order by post_time desc',
|
||||
<<<EOD
|
||||
<tr>
|
||||
<th width="60%">标题</th>
|
||||
<th width="20%">发表者</th>
|
||||
<th width="20%">发表日期</th>
|
||||
<th>标题</th>
|
||||
<th style="width:200px">发表者</th>
|
||||
<th style="width:200px">发表日期</th>
|
||||
<th style="width:50px" class="text-center">评价</th>
|
||||
</tr>
|
||||
EOD,
|
||||
function($blog) {
|
||||
echo '<tr>';
|
||||
echo '<td>';
|
||||
echo getBlogLink($blog['id']);
|
||||
if ($blog['is_hidden']) {
|
||||
echo ' <span class="badge text-bg-danger"><i class="bi bi-eye-slash-fill"></i> ', UOJLocale::get('hidden'), '</span> ';
|
||||
}
|
||||
echo '</td>';
|
||||
echo '<td>' . getUserLink($blog['poster']) . '</td>';
|
||||
echo '<td>' . $blog['post_time'] . '</td>';
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 10,
|
||||
'div_classes' => ['card', 'my-3', 'table-responsive'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
function ($info) {
|
||||
$blog = new UOJBlog($info);
|
||||
|
||||
</div>
|
||||
echo '<tr>';
|
||||
echo '<td>';
|
||||
echo $blog->getLink();
|
||||
if ($blog->info['is_hidden']) {
|
||||
echo ' <span class="badge text-bg-danger"><i class="bi bi-eye-slash-fill"></i> ', UOJLocale::get('hidden'), '</span> ';
|
||||
}
|
||||
echo '</td>';
|
||||
echo '<td>' . getUserLink($blog->info['poster']) . '</td>';
|
||||
echo '<td>' . $blog->info['post_time'] . '</td>';
|
||||
echo '<td class="text-center">' . ClickZans::getCntBlock($blog->info['zan']) . '</td>';
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 10,
|
||||
'div_classes' => ['card', 'my-3', 'table-responsive'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
</div>
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -9,5 +9,3 @@ $_SESSION['phrase'] = $builder->getPhrase();
|
||||
|
||||
header('Content-Type: image/jpeg');
|
||||
$builder->build()->output();
|
||||
|
||||
?>
|
||||
|
3
web/app/controllers/check_notice.php
Normal file
3
web/app/controllers/check_notice.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
die(json_encode(UOJNotice::fetch(UOJTime::str2time(UOJRequest::post('last_time')))));
|
@ -1,69 +1,24 @@
|
||||
<?php
|
||||
function validateZan() {
|
||||
if (!validateUInt($_POST['id'])) {
|
||||
return false;
|
||||
}
|
||||
if (!validateInt($_POST['delta'])) {
|
||||
return false;
|
||||
}
|
||||
if ($_POST['delta'] != 1 && $_POST['delta'] != -1) {
|
||||
return false;
|
||||
}
|
||||
if ($_POST['type'] != 'B' && $_POST['type'] != 'BC' && $_POST['type'] != 'P' && $_POST['type'] != 'C') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!validateZan()) {
|
||||
die('<div class="text-danger">failed</div>');
|
||||
}
|
||||
if ($myUser == null) {
|
||||
die('<div class="text-danger">please <a href="'.HTML::url('/login').'">log in</a></div>');
|
||||
}
|
||||
|
||||
$id = $_POST['id'];
|
||||
$delta = $_POST['delta'];
|
||||
$type = $_POST['type'];
|
||||
$show_text = isset($_POST['show-text']) && $_POST['show-text'] != 'false';
|
||||
|
||||
switch ($type) {
|
||||
case 'B':
|
||||
$table_name = 'blogs';
|
||||
break;
|
||||
case 'BC':
|
||||
$table_name = 'blogs_comments';
|
||||
break;
|
||||
case 'P':
|
||||
$table_name = 'problems';
|
||||
break;
|
||||
case 'C':
|
||||
$table_name = 'contests';
|
||||
break;
|
||||
}
|
||||
|
||||
$cur = queryZanVal($id, $type, $myUser);
|
||||
|
||||
if ($cur != $delta) {
|
||||
$row = DB::selectFirst("select zan from $table_name where id = $id");
|
||||
if ($row == null) {
|
||||
die('<div class="text-danger">failed</div>');
|
||||
}
|
||||
$cur += $delta;
|
||||
if ($cur == 0) {
|
||||
DB::query("delete from click_zans where username = '{$myUser['username']}' and type = '$type' and target_id = $id");
|
||||
} elseif ($cur != $delta) {
|
||||
DB::query("update click_zans set val = '$cur' where username = '{$myUser['username']}' and type = '$type' and target_id = $id");
|
||||
} else {
|
||||
DB::query("insert into click_zans (username, type, target_id, val) values ('{$myUser['username']}', '$type', $id, $cur)");
|
||||
}
|
||||
$cnt = $row['zan'] + $delta;
|
||||
DB::query("update $table_name set zan = $cnt where id = $id");
|
||||
} else {
|
||||
$row = DB::selectFirst("select zan from $table_name where id = $id");
|
||||
if ($row == null) {
|
||||
die('<div class="text-danger">failed</div>');
|
||||
}
|
||||
$cnt = $row['zan'];
|
||||
}
|
||||
?>
|
||||
<?= getClickZanBlock($type, $id, $cnt, $cur, $show_text) ?>
|
||||
|
||||
function validateZan() {
|
||||
if (!validateUInt($_POST['id']))
|
||||
return false;
|
||||
if (!validateInt($_POST['delta']))
|
||||
return false;
|
||||
if ($_POST['delta'] != 1 && $_POST['delta'] != -1)
|
||||
return false;
|
||||
if (!ClickZans::getTable($_POST['type']))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (!validateZan()) {
|
||||
die('<div class="text-danger">failed</div>');
|
||||
}
|
||||
if (!Auth::check()) {
|
||||
die('<div class="text-danger">please <a href="' . HTML::url('/login') . '">log in</a></div>');
|
||||
}
|
||||
if (!ClickZans::canClickZan($_POST['id'], $_POST['type'], Auth::user())) {
|
||||
die('<div class="text-danger">no permission</div>');
|
||||
}
|
||||
|
||||
die(ClickZans::click($_POST['id'], $_POST['type'], Auth::user(), $_POST['delta'], $_POST['show-text']));
|
||||
|
@ -1,77 +1,65 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJContest::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
UOJContest::cur()->userCanParticipateNow(Auth::user()) || UOJResponse::page403();
|
||||
UOJContest::cur()->userHasMarkedParticipated(Auth::user()) && redirectTo(UOJContest::cur()->getUri());
|
||||
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
} elseif (!hasRegistered($myUser, $contest)) {
|
||||
redirectTo("/contest/{$contest['id']}/register");
|
||||
} elseif ($contest['cur_progress'] < CONTEST_IN_PROGRESS) {
|
||||
redirectTo('/contests');
|
||||
} elseif (hasParticipated($myUser, $contest) || $contest['cur_progress'] > CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
$confirm_form = new UOJBs4Form('confirm');
|
||||
$confirm_form->submit_button_config['class_str'] = 'btn btn-primary mt-3';
|
||||
$confirm_form->submit_button_config['text'] = '我已核对信息,确认参加比赛';
|
||||
$confirm_form->handle = function () {
|
||||
UOJContest::cur()->markUserAsParticipated(Auth::user());
|
||||
};
|
||||
$confirm_form->succ_href = '/contest/' . UOJContest::info('id');
|
||||
$confirm_form->runAtServer();
|
||||
?>
|
||||
|
||||
$confirm_form = new UOJForm('confirm');
|
||||
$confirm_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$confirm_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$confirm_form->submit_button_config['text'] = '我已核对信息,确认参加比赛';
|
||||
$confirm_form->handle = function() use ($myUser, $contest) {
|
||||
DB::update("update contests_registrants set has_participated = 1 where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
|
||||
};
|
||||
$confirm_form->succ_href = "/contest/{$contest['id']}";
|
||||
$confirm_form->runAtServer();
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader('确认参赛 - ' . HTML::stripTags($contest['name'])) ?>
|
||||
<?php echoUOJPageHeader('确认参赛 - ' . UOJContest::info('name')) ?>
|
||||
|
||||
<div class="card mw-100 mx-auto" style="width:800px">
|
||||
<div class="card-body">
|
||||
<h1 class="h2 card-title text-center mb-3">确认参赛</h1>
|
||||
<div class="card-body">
|
||||
<h1 class="card-title text-center mb-3">确认参赛</h1>
|
||||
|
||||
<p class="card-text text-center">您即将参加比赛 “<b><?= $contest['name'] ?></b>”,请在正式参赛前仔细核对以下比赛信息:</p>
|
||||
<p class="card-text text-center">您即将参加比赛 “<b><?= UOJContest::info('name') ?></b>”,请在正式参赛前仔细核对以下比赛信息:</p>
|
||||
|
||||
<div class="table-responsive mx-auto" style="width:500px">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40%"></th>
|
||||
<th style="width:60%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">比赛名称</td>
|
||||
<td><?= $contest['name'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">参赛选手</td>
|
||||
<td><?= getUserLink($myUser['username']) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">开始时间</td>
|
||||
<td><?= $contest['start_time_str'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">结束时间</td>
|
||||
<td><?= $contest['end_time_str'] ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">比赛赛制</td>
|
||||
<td><?= $contest['extra_config']['contest_type'] ?: 'OI' ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive mx-auto" style="width:500px">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40%"></th>
|
||||
<th style="width:60%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="text-center">比赛名称</td>
|
||||
<td><?= UOJContest::info('name') ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">参赛选手</td>
|
||||
<td><?= getUserLink(Auth::id()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">开始时间</td>
|
||||
<td><?= UOJContest::info('start_time_str') ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">结束时间</td>
|
||||
<td><?= UOJContest::info('end_time_str') ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-center">比赛赛制</td>
|
||||
<td><?= UOJContest::cur()->basicRule() ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php $confirm_form->printHTML() ?>
|
||||
</div>
|
||||
|
||||
<?php $confirm_form->printHTML() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,186 +1,167 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJContest::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
$contest = UOJContest::info();
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
$is_manager = UOJContest::cur()->userCanManage(Auth::user());
|
||||
$show_ip = isSuperUser(Auth::user());
|
||||
|
||||
genMoreContestInfo($contest);
|
||||
if ($is_manager) {
|
||||
$add_new_contestant_form = new UOJBs4Form('add_new_contestant_form');
|
||||
$add_new_contestant_form->addInput(
|
||||
'new_username',
|
||||
'text',
|
||||
'用户名',
|
||||
'',
|
||||
function ($username, &$vdata) {
|
||||
$user = UOJUser::query($username);
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$add_new_contestant_form = new UOJForm('add_new_contestant_form');
|
||||
$add_new_contestant_form->addInput('new_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
|
||||
if (!validateUsername($x)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
$user = queryUser($x);
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
if (hasRegistered($user, $contest)) {
|
||||
return '该用户已经报名';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_contestant_form->submit_button_config['align'] = 'compressed';
|
||||
$add_new_contestant_form->submit_button_config['text'] = '注册该用户';
|
||||
$add_new_contestant_form->handle = function() {
|
||||
global $contest;
|
||||
|
||||
$username = $_POST['new_username'];
|
||||
|
||||
DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$username}', {$contest['id']}, 0)");
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$add_new_contestant_form->runAtServer();
|
||||
|
||||
$add_group_to_contest_form = new UOJForm('add_group_to_contest');
|
||||
$add_group_to_contest_form->addInput('group_id', 'text', '小组 ID', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
|
||||
if (!validateUInt($x)) {
|
||||
return '小组 ID 不合法';
|
||||
}
|
||||
$group = queryGroup($x);
|
||||
if (!$group) {
|
||||
return '小组不存在';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_group_to_contest_form->submit_button_config['align'] = 'compressed';
|
||||
$add_group_to_contest_form->submit_button_config['text'] = '注册该小组中的用户';
|
||||
$add_group_to_contest_form->handle = function() {
|
||||
global $contest;
|
||||
$group_id = $_POST['group_id'];
|
||||
|
||||
$users = DB::selectAll("select b.username as username from groups_users a inner join user_info b on a.username = b.username where a.group_id = $group_id");
|
||||
|
||||
foreach ($users as $user) {
|
||||
DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$user['username']}', {$contest['id']}, 0)");
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$add_group_to_contest_form->runAtServer();
|
||||
if (UOJContest::cur()->userHasRegistered($user)) {
|
||||
return '该用户已经报名';
|
||||
}
|
||||
|
||||
$remove_user_from_contest_form = new UOJForm('remove_user_from_contest');
|
||||
$remove_user_from_contest_form->addInput('remove_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
if (!validateUsername($x)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
$vdata['user'] = $user;
|
||||
|
||||
$user = queryUser($x);
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_contestant_form->submit_button_config['align'] = 'compressed';
|
||||
$add_new_contestant_form->submit_button_config['text'] = '注册该用户';
|
||||
$add_new_contestant_form->handle = function (&$vdata) {
|
||||
UOJContest::cur()->userRegister($vdata['user']);
|
||||
};
|
||||
$add_new_contestant_form->runAtServer();
|
||||
|
||||
if (!hasRegistered($user, $contest)) {
|
||||
return '该用户未报名';
|
||||
}
|
||||
$add_group_to_contest_form = new UOJBs4Form('add_group_to_contest');
|
||||
$add_group_to_contest_form->addInput(
|
||||
'group_id',
|
||||
'text',
|
||||
'小组 ID',
|
||||
'',
|
||||
function ($group_id, &$vdata) {
|
||||
if (!validateUInt($group_id)) {
|
||||
return '小组 ID 不合法';
|
||||
}
|
||||
$group = queryGroup($group_id);
|
||||
if (!$group) {
|
||||
return '小组不存在';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$remove_user_from_contest_form->submit_button_config['align'] = 'compressed';
|
||||
$remove_user_from_contest_form->submit_button_config['text'] = '移除该用户';
|
||||
$remove_user_from_contest_form->submit_button_config['class_str'] = 'mt-2 btn btn-danger';
|
||||
$remove_user_from_contest_form->handle = function() {
|
||||
global $contest;
|
||||
$username = $_POST['remove_username'];
|
||||
$vdata['group_id'] = $group_id;
|
||||
|
||||
DB::query("delete from contests_registrants where username = '{$username}' and contest_id = {$contest['id']}");
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$remove_user_from_contest_form->runAtServer();
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_group_to_contest_form->submit_button_config['align'] = 'compressed';
|
||||
$add_group_to_contest_form->submit_button_config['text'] = '注册该小组中的用户';
|
||||
$add_group_to_contest_form->handle = function (&$vdata) {
|
||||
$users = queryGroupUsers($vdata['group_id']);
|
||||
|
||||
$force_set_user_participated_form = new UOJForm('force_set_user_participated');
|
||||
$force_set_user_participated_form->addInput('force_set_username', 'text', '用户名', '',
|
||||
function ($x) {
|
||||
global $contest;
|
||||
foreach ($users as $user) {
|
||||
UOJContest::cur()->userRegister($user);
|
||||
}
|
||||
};
|
||||
$add_group_to_contest_form->runAtServer();
|
||||
|
||||
if (!validateUsername($x)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
$remove_user_from_contest_form = new UOJBs4Form('remove_user_from_contest');
|
||||
$remove_user_from_contest_form->addInput(
|
||||
'remove_username',
|
||||
'text',
|
||||
'用户名',
|
||||
'',
|
||||
function ($username, &$vdata) {
|
||||
$user = UOJUser::query($username);
|
||||
|
||||
$user = queryUser($x);
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
if (!hasRegistered($user, $contest)) {
|
||||
return '该用户未报名';
|
||||
}
|
||||
if (!UOJContest::cur()->userHasRegistered($user)) {
|
||||
return '该用户未报名';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$force_set_user_participated_form->submit_button_config['align'] = 'compressed';
|
||||
$force_set_user_participated_form->submit_button_config['text'] = '强制参赛';
|
||||
$force_set_user_participated_form->submit_button_config['class_str'] = 'mt-2 btn btn-warning';
|
||||
$force_set_user_participated_form->handle = function() {
|
||||
global $contest;
|
||||
$username = $_POST['force_set_username'];
|
||||
$vdata['user'] = $user;
|
||||
|
||||
DB::query("update contests_registrants set has_participated = 1 where username = '{$username}' and contest_id = {$contest['id']}");
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$force_set_user_participated_form->runAtServer();
|
||||
}
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$remove_user_from_contest_form->submit_button_config['align'] = 'compressed';
|
||||
$remove_user_from_contest_form->submit_button_config['text'] = '移除该用户';
|
||||
$remove_user_from_contest_form->submit_button_config['class_str'] = 'mt-2 btn btn-danger';
|
||||
$remove_user_from_contest_form->handle = function (&$vdata) {
|
||||
UOJContest::cur()->userUnregister($vdata['user']);
|
||||
};
|
||||
$remove_user_from_contest_form->runAtServer();
|
||||
|
||||
$has_contest_permission = hasContestPermission($myUser, $contest);
|
||||
$show_ip = $has_contest_permission;
|
||||
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
$iHasRegistered = $myUser != null && hasRegistered($myUser, $contest);
|
||||
|
||||
if ($iHasRegistered) {
|
||||
$unregister_form = new UOJForm('unregister');
|
||||
$unregister_form->handle = function() {
|
||||
global $myUser, $contest;
|
||||
DB::query("delete from contests_registrants where username = '{$myUser['username']}' and contest_id = {$contest['id']}");
|
||||
updateContestPlayerNum($contest);
|
||||
$force_set_user_participated_form = new UOJBs4Form('force_set_user_participated');
|
||||
$force_set_user_participated_form->addInput(
|
||||
'force_set_username',
|
||||
'text',
|
||||
'用户名',
|
||||
'',
|
||||
function ($username, &$vdata) {
|
||||
$user = UOJUser::query($username);
|
||||
|
||||
if (!$user) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
if (!UOJContest::cur()->userHasRegistered($user)) {
|
||||
return '该用户未报名';
|
||||
}
|
||||
|
||||
$vdata['user'] = $user;
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$force_set_user_participated_form->submit_button_config['align'] = 'compressed';
|
||||
$force_set_user_participated_form->submit_button_config['text'] = '强制参赛';
|
||||
$force_set_user_participated_form->submit_button_config['class_str'] = 'mt-2 btn btn-warning';
|
||||
$force_set_user_participated_form->handle = function (&$vdata) {
|
||||
UOJContest::cur()->markUserAsParticipated($vdata['user']);
|
||||
};
|
||||
$force_set_user_participated_form->runAtServer();
|
||||
}
|
||||
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
$iHasRegistered = UOJContest::cur()->userHasRegistered(Auth::user());
|
||||
|
||||
if ($iHasRegistered) {
|
||||
if ($iHasRegistered && UOJContest::cur()->freeRegistration()) {
|
||||
$unregister_form = new UOJBs4Form('unregister');
|
||||
$unregister_form->handle = function () {
|
||||
UOJContest::cur()->userUnregister(Auth::user());
|
||||
};
|
||||
$unregister_form->submit_button_config['align'] = 'right';
|
||||
$unregister_form->submit_button_config['class_str'] = 'btn btn-danger btn-xs';
|
||||
$unregister_form->submit_button_config['text'] = '取消报名';
|
||||
$unregister_form->succ_href = "/contests";
|
||||
|
||||
|
||||
$unregister_form->runAtServer();
|
||||
}
|
||||
}
|
||||
?>
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader(HTML::stripTags($contest['name']) . ' - ' . UOJLocale::get('contests::contest registrants')) ?>
|
||||
|
||||
<h1 class="h2 text-center">
|
||||
<h1 class="text-center">
|
||||
<?= $contest['name'] ?>
|
||||
</h1>
|
||||
|
||||
<?php if ($contest['cur_progress'] == CONTEST_NOT_STARTED): ?>
|
||||
<?php if ($iHasRegistered): ?>
|
||||
<?php if ($contest['cur_progress'] == CONTEST_NOT_STARTED) : ?>
|
||||
<?php if ($iHasRegistered) : ?>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<a class="text-decoration-none text-success">已报名</a>
|
||||
@ -189,64 +170,64 @@
|
||||
<?php $unregister_form->printHTML(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php else : ?>
|
||||
<div>当前尚未报名,您可以 <a class="text-decoration-none text-danger" href="/contest/<?= $contest['id'] ?>/register">报名</a>。</div>
|
||||
<?php endif ?>
|
||||
<div class="mt-2"></div>
|
||||
<div class="mt-2"></div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php
|
||||
$header_row = '<tr><th>#</th><th>'.UOJLocale::get('username').'</th>';
|
||||
if ($show_ip) {
|
||||
$header_row .= '<th>remote_addr</th><th>http_x_forwarded_for</th>';
|
||||
}
|
||||
if ($has_contest_permission) {
|
||||
$header_row .= '<th>是否参赛</th>';
|
||||
}
|
||||
$header_row .= '</tr>';
|
||||
$header_row = '<tr><th>#</th><th>' . UOJLocale::get('username') . '</th>';
|
||||
if ($show_ip) {
|
||||
$header_row .= '<th>remote_addr</th><th>http_x_forwarded_for</th>';
|
||||
}
|
||||
if ($is_manager) {
|
||||
$header_row .= '<th>是否参赛</th>';
|
||||
}
|
||||
$header_row .= '</tr>';
|
||||
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests_registrants',
|
||||
"contest_id = {$contest['id']}",
|
||||
'order by username desc',
|
||||
$header_row,
|
||||
function($contestant, $num) use ($myUser, $has_contest_permission, $show_ip, $has_participated) {
|
||||
$user = queryUser($contestant['username']);
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests_registrants',
|
||||
['contest_id' => $contest['id']],
|
||||
'order by username desc',
|
||||
$header_row,
|
||||
function ($contestant, $num) use ($is_manager, $show_ip) {
|
||||
$user = UOJUser::query($contestant['username']);
|
||||
|
||||
echo '<tr>';
|
||||
echo '<td>'.$num.'</td>';
|
||||
echo '<td>'.getUserLink($contestant['username']).'</td>';
|
||||
if ($show_ip) {
|
||||
echo '<td>'.$user['remote_addr'].'</td>';
|
||||
echo '<td>'.$user['http_x_forwarded_for'].'</td>';
|
||||
}
|
||||
if ($has_contest_permission) {
|
||||
echo '<td>'.($contestant['has_participated'] ? 'Yes' : 'No').'</td>';
|
||||
}
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 50,
|
||||
'get_row_index' => '',
|
||||
'div_classes' => ['table-responsive', 'card', 'mb-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0', 'text-center'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
echo '<tr>';
|
||||
echo '<td>' . $num . '</td>';
|
||||
echo '<td>' . getUserLink($user['username']) . '</td>';
|
||||
if ($show_ip) {
|
||||
echo '<td>' . $user['remote_addr'] . '</td>';
|
||||
echo '<td>' . $user['http_x_forwarded_for'] . '</td>';
|
||||
}
|
||||
if ($is_manager) {
|
||||
echo '<td>' . ($contestant['has_participated'] ? 'Yes' : 'No') . '</td>';
|
||||
}
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 50,
|
||||
'get_row_index' => '',
|
||||
'div_classes' => ['table-responsive', 'card', 'mb-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0', 'text-center'],
|
||||
]
|
||||
);
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (isset($add_new_contestant_form)) {
|
||||
$add_new_contestant_form->printHTML();
|
||||
}
|
||||
if (isset($add_group_to_contest_form)) {
|
||||
$add_group_to_contest_form->printHTML();
|
||||
}
|
||||
if (isset($remove_user_from_contest_form)) {
|
||||
$remove_user_from_contest_form->printHTML();
|
||||
}
|
||||
if (isset($force_set_user_participated_form)) {
|
||||
$force_set_user_participated_form->printHTML();
|
||||
}
|
||||
?>
|
||||
if (isset($add_new_contestant_form)) {
|
||||
$add_new_contestant_form->printHTML();
|
||||
}
|
||||
if (isset($add_group_to_contest_form)) {
|
||||
$add_group_to_contest_form->printHTML();
|
||||
}
|
||||
if (isset($remove_user_from_contest_form)) {
|
||||
$remove_user_from_contest_form->printHTML();
|
||||
}
|
||||
if (isset($force_set_user_participated_form)) {
|
||||
$force_set_user_participated_form->printHTML();
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,73 +1,57 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($contest = queryContest($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
genMoreContestInfo($contest);
|
||||
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
} elseif (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
} elseif (hasRegistered($myUser, $contest)) {
|
||||
if ($contest['cur_progress'] < CONTEST_IN_PROGRESS) {
|
||||
redirectTo('/contests');
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
} elseif ($contest['cur_progress'] > CONTEST_IN_PROGRESS) {
|
||||
redirectTo("/contest/{$contest['id']}");
|
||||
}
|
||||
|
||||
$register_form = new UOJForm('register');
|
||||
$register_form->handle = function() use ($myUser, $contest) {
|
||||
DB::query("replace into contests_registrants (username, contest_id, has_participated) values ('{$myUser['username']}', {$contest['id']}, 0)");
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJContest::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
UOJContest::cur()->userCanRegister(Auth::user(), ['ensure' => true]);
|
||||
|
||||
updateContestPlayerNum($contest);
|
||||
};
|
||||
$register_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$register_form->submit_button_config['text'] = '我已阅读规则,确认报名比赛';
|
||||
|
||||
if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
$register_form->succ_href = "/contest/{$contest['id']}/confirm";
|
||||
} else {
|
||||
$register_form->succ_href = "/contests";
|
||||
}
|
||||
|
||||
$register_form->runAtServer();
|
||||
?>
|
||||
<?php echoUOJPageHeader('报名 - ' . HTML::stripTags($contest['name'])) ?>
|
||||
$register_form = new UOJBs4Form('register');
|
||||
$register_form->handle = function () {
|
||||
UOJContest::cur()->userRegister(Auth::user());
|
||||
};
|
||||
$register_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$register_form->submit_button_config['text'] = '我已阅读规则,确认报名比赛';
|
||||
|
||||
if (UOJContest::cur()->progress() == CONTEST_IN_PROGRESS) {
|
||||
$register_form->succ_href = '/contest/' . UOJContest::info('id') . '/confirm';
|
||||
} else {
|
||||
$register_form->succ_href = '/contests';
|
||||
}
|
||||
|
||||
$register_form->runAtServer();
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader('报名 - ' . UOJContest::info('name')) ?>
|
||||
|
||||
<div class="card mw-100 mx-auto" style="width:800px">
|
||||
<div class="card-body">
|
||||
<h1 class="h2 card-title text-center mb-3">比赛规则</h1>
|
||||
<div class="card-body">
|
||||
<h1 class="card-title text-center mb-3">比赛规则</h1>
|
||||
|
||||
<p class="card-text">您即将报名比赛 “<b><?= $contest['name'] ?></b>”,请在报名前仔细阅读以下比赛规则:</p>
|
||||
<p class="card-text">您即将报名比赛 “<b><?= UOJContest::info('name') ?></b>”,请在报名前仔细阅读以下比赛规则:</p>
|
||||
|
||||
<ul>
|
||||
<?php if ($contest['cur_progress'] == CONTEST_IN_PROGRESS): ?>
|
||||
<li class="text-danger">本场比赛正在进行中,将于 <b><?= $contest['end_time_str'] ?></b> 结束。</li>
|
||||
<?php else: ?>
|
||||
<li>本场比赛将于 <b><?= $contest['start_time_str'] ?></b> 开始,并于 <b><?= $contest['end_time_str'] ?></b> 结束。</li>
|
||||
<?php endif ?>
|
||||
<li>比赛开始后点击 “<b>确认参赛</b>” 按钮才会被视为正式参赛,未正式参赛的选手不会显示在排行榜上。</li>
|
||||
<?php if (!isset($contest['extra_config']['contest_type']) || $contest['extra_config']['contest_type'] == 'OI'): ?>
|
||||
<li>本场比赛为 OI 赛制。比赛中途可以提交代码,但 <b>只显示测样例的结果</b>。</li>
|
||||
<?php elseif ($contest['extra_config']['contest_type'] == 'IOI'): ?>
|
||||
<li>本场比赛为 IOI 赛制。比赛时的提交会测试题目的全部数据,但无法查看数据点详情。</li>
|
||||
<?php endif ?>
|
||||
<li>若选手在比赛中多次提交了同一题,则最后按照 <b>最后一次不是 Compile Error 的提交</b> 计算排行。</li>
|
||||
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>
|
||||
<li>比赛排名按分数为第一关键字,完成题目的总时间为第二关键字。完成题目的总时间等于完成每道题所花时间之和(无视掉爆零的题目)。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以 0 分处理或者封禁。</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<?php if (UOJContest::cur()->progress() == CONTEST_IN_PROGRESS) : ?>
|
||||
<li class="text-danger">本场比赛正在进行中,将于 <b><?= UOJContest::info('end_time_str') ?></b> 结束。</li>
|
||||
<?php else : ?>
|
||||
<li>本场比赛将于 <b><?= UOJContest::info('start_time_str') ?></b> 开始,并于 <b><?= UOJContest::info('end_time_str') ?></b> 结束。</li>
|
||||
<?php endif ?>
|
||||
<li>比赛开始后点击 “<b>确认参赛</b>” 按钮才会被视为正式参赛,未正式参赛的选手不会显示在排行榜上。</li>
|
||||
<?php if (UOJContest::cur()->basicRule() == 'OI') : ?>
|
||||
<li>本场比赛为 OI 赛制。比赛中途可以提交代码,但 <b>只显示测样例的结果</b>。</li>
|
||||
<?php elseif (UOJContest::cur()->basicRule() == 'IOI') : ?>
|
||||
<li>本场比赛为 IOI 赛制。比赛时的提交会测试题目的全部数据,但无法查看数据点详情。</li>
|
||||
<?php elseif (UOJContest::cur()->basicRule() == 'ACM') : ?>
|
||||
<li>本场比赛为 ACM 赛制。</li>
|
||||
<?php endif ?>
|
||||
<li>若选手在比赛中多次提交了同一题,则最后按照 <b>最后一次不是 Compile Error 的提交</b> 计算排行。</li>
|
||||
<li>比赛结束后会进行最终测试,最终测试后的排名为最终排名。</li>
|
||||
<li>比赛排名按分数为第一关键字,完成题目的总时间为第二关键字。完成题目的总时间等于完成每道题所花时间之和(无视掉爆零的题目)。</li>
|
||||
<li>请遵守比赛规则,一位选手在一场比赛内不得报名多个账号,选手之间不能交流或者抄袭代码,如果被检测到将以 0 分处理或者封禁。</li>
|
||||
</ul>
|
||||
|
||||
<?php $register_form->printHTML() ?>
|
||||
</div>
|
||||
<?php $register_form->printHTML() ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,108 +1,110 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
|
||||
$upcoming_contest_name = null;
|
||||
$upcoming_contest_href = null;
|
||||
$rest_second = 1000000;
|
||||
function echoContest($contest) {
|
||||
global $myUser, $upcoming_contest_name, $upcoming_contest_href, $rest_second;
|
||||
$upcoming_contest_name = null;
|
||||
$upcoming_contest_href = null;
|
||||
$rest_second = 1000000;
|
||||
function echoContest($info) {
|
||||
global $upcoming_contest_name, $upcoming_contest_href, $rest_second;
|
||||
|
||||
$contest_name_link = <<<EOD
|
||||
<a class="text-decoration-none" href="/contest/{$contest['id']}">{$contest['name']}</a>
|
||||
EOD;
|
||||
genMoreContestInfo($contest);
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
$cur_rest_second = $contest['start_time']->getTimestamp() - UOJTime::$time_now->getTimestamp();
|
||||
if ($cur_rest_second < $rest_second) {
|
||||
$upcoming_contest_name = $contest['name'];
|
||||
$upcoming_contest_href = "/contest/{$contest['id']}";
|
||||
$rest_second = $cur_rest_second;
|
||||
}
|
||||
if ($myUser != null && hasRegistered($myUser, $contest)) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:green">'.UOJLocale::get('contests::registered').'</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:red" href="/contest/'.$contest['id'].'/register">'.UOJLocale::get('contests::register').'</a></sup>';
|
||||
}
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if (hasRegistered($myUser, $contest)) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::in progress').'</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'/register">'.UOJLocale::get('contests::in progress').'</a></sup>';
|
||||
}
|
||||
} elseif ($contest['cur_progress'] == CONTEST_PENDING_FINAL_TEST) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::pending final test').'</a></sup>';
|
||||
} elseif ($contest['cur_progress'] == CONTEST_TESTING) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/'.$contest['id'].'">'.UOJLocale::get('contests::final testing').'</a></sup>';
|
||||
} elseif ($contest['cur_progress'] == CONTEST_FINISHED) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:grey" href="/contest/'.$contest['id'].'/standings">'.UOJLocale::get('contests::ended').'</a></sup>';
|
||||
$contest = new UOJContest($info);
|
||||
|
||||
$contest_name_link = '<a class="text-decoration-none" href="/contest/' . $contest->info['id'] . '">' . $contest->info['name'] . '</a>';
|
||||
|
||||
if ($contest->progress() == CONTEST_NOT_STARTED) {
|
||||
$cur_rest_second = $contest->info['start_time']->getTimestamp() - UOJTime::$time_now->getTimestamp();
|
||||
if ($cur_rest_second < $rest_second) {
|
||||
$upcoming_contest_name = $contest->info['name'];
|
||||
$upcoming_contest_href = '/contest/' . $contest->info['id'];
|
||||
$rest_second = $cur_rest_second;
|
||||
}
|
||||
if ($contest->userHasRegistered(Auth::user())) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:green">' . UOJLocale::get('contests::registered') . '</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:red" href="/contest/' . $contest->info['id'] . '/register">' . UOJLocale::get('contests::register') . '</a></sup>';
|
||||
}
|
||||
} elseif ($contest->progress() == CONTEST_IN_PROGRESS) {
|
||||
if ($contest->allowExtraRegistration() && !$contest->userHasRegistered(Auth::user())) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:red" href="/contest/' . $contest->info['id'] . '/register">' . UOJLocale::get('contests::register') . ' (' . UOJLocale::get('contests::in progress') . ')' . '</a></sup>';
|
||||
} else {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:blue" href="/contest/' . $contest->info['id'] . '">' . UOJLocale::get('contests::in progress') . '</a></sup>';
|
||||
}
|
||||
} elseif ($contest->progress() == CONTEST_FINISHED) {
|
||||
$contest_name_link .= '<sup><a class="text-decoration-none" style="color:grey" href="/contest/' . $contest->info['id'] . '/standings">' . UOJLocale::get('contests::ended') . '</a></sup>';
|
||||
} else {
|
||||
if ($contest->basicRule() == 'OI') {
|
||||
if ($contest->progress() == CONTEST_PENDING_FINAL_TEST) {
|
||||
$contest_name_link .= '<sup><a style="color:blue" href="/contest/' . $contest->info['id'] . '">' . UOJLocale::get('contests::pending final test') . '</a></sup>';
|
||||
} elseif ($contest->progress() == CONTEST_TESTING) {
|
||||
$contest_name_link .= '<sup><a style="color:blue" href="/contest/' . $contest->info['id'] . '">' . UOJLocale::get('contests::final testing') . '</a></sup>';
|
||||
}
|
||||
} elseif ($contest->basicRule() == 'ACM' || $contest->basicRule() == 'IOI') {
|
||||
$contest_name_link .= '<sup><a style="color:blue" href="/contest/' . $contest->info['id'] . '">' . UOJLocale::get('contests::official results to be announced') . '</a></sup>';
|
||||
}
|
||||
|
||||
$last_hour = round($contest['last_min'] / 60, 2);
|
||||
|
||||
$click_zan_block = getClickZanBlock('C', $contest['id'], $contest['zan']);
|
||||
echo '<tr>';
|
||||
echo '<td>', $contest_name_link, '</td>';
|
||||
echo '<td>', '<a class="text-decoration-none" href="'.HTML::timeanddate_url($contest['start_time'], array('duration' => $contest['last_min'])).'">'.$contest['start_time_str'].'</a>', '</td>';
|
||||
echo '<td>', UOJLocale::get('hours', $last_hour), '</td>';
|
||||
echo '<td>', '<a class="text-decoration-none" href="/contest/'.$contest['id'].'/registrants">', '<i class="bi bi-person-fill"></i>', ' ×'.$contest['player_num'].'</a>', '</td>';
|
||||
echo '<td>', '<div class="text-left">'.$click_zan_block.'</div>', '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
?>
|
||||
|
||||
$last_hour = round($contest->info['last_min'] / 60, 2);
|
||||
echo '<tr>';
|
||||
echo '<td>', $contest_name_link, '</td>';
|
||||
echo '<td>', '<a class="text-decoration-none" href="' . HTML::timeanddate_url($contest->info['start_time'], ['duration' => $contest->info['last_min']]) . '">' . $contest->info['start_time_str'] . '</a>', '</td>';
|
||||
echo '<td>', UOJLocale::get('hours', $last_hour), '</td>';
|
||||
echo '<td>', '<a class="text-decoration-none" href="/contest/' . $contest->info['id'] . '/registrants">', '<i class="bi bi-person-fill"></i>', ' ×' . $contest->info['player_num'] . '</a>', '</td>';
|
||||
echo '<td>', '<div class="text-left">' . ClickZans::getBlock('C', $contest->info['id'], $contest->info['zan']) . '</div>', '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('contests')) ?>
|
||||
|
||||
<!-- title container -->
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1 class="h2">
|
||||
<?= UOJLocale::get('contests') ?>
|
||||
</h1>
|
||||
<h1>
|
||||
<?= UOJLocale::get('contests') ?>
|
||||
</h1>
|
||||
|
||||
<?php if (isSuperUser($myUser)): ?>
|
||||
<div class="text-end">
|
||||
<a href="/contest/new" class="btn btn-primary"><?= UOJLocale::get('contests::add new contest') ?></a>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php if (isSuperUser($myUser)) : ?>
|
||||
<div class="text-end">
|
||||
<a href="/contest/new" class="btn btn-primary"><?= UOJLocale::get('contests::add new contest') ?></a>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
<!-- end title container -->
|
||||
|
||||
<h2 class="h4">
|
||||
<h2>
|
||||
<?= UOJLocale::get('contests::current or upcoming contests') ?>
|
||||
</h2>
|
||||
<?php
|
||||
$table_header = '';
|
||||
$table_header .= '<tr>';
|
||||
$table_header .= '<th>'.UOJLocale::get('contests::contest name').'</th>';
|
||||
$table_header .= '<th style="width:15em;">'.UOJLocale::get('contests::start time').'</th>';
|
||||
$table_header .= '<th style="width:100px;">'.UOJLocale::get('contests::duration').'</th>';
|
||||
$table_header .= '<th style="width:100px;">'.UOJLocale::get('contests::the number of registrants').'</th>';
|
||||
$table_header .= '<th style="width:180px;">'.UOJLocale::get('appraisal').'</th>';
|
||||
$table_header .= '</tr>';
|
||||
$table_header = '';
|
||||
$table_header .= '<tr>';
|
||||
$table_header .= '<th>' . UOJLocale::get('contests::contest name') . '</th>';
|
||||
$table_header .= '<th style="width:15em;">' . UOJLocale::get('contests::start time') . '</th>';
|
||||
$table_header .= '<th style="width:100px;">' . UOJLocale::get('contests::duration') . '</th>';
|
||||
$table_header .= '<th style="width:100px;">' . UOJLocale::get('contests::the number of registrants') . '</th>';
|
||||
$table_header .= '<th style="width:180px;">' . UOJLocale::get('appraisal') . '</th>';
|
||||
$table_header .= '</tr>';
|
||||
|
||||
$table_config = [
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'mb-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0', 'text-center'],
|
||||
];
|
||||
$table_config = [
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'mb-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0', 'text-center'],
|
||||
];
|
||||
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests',
|
||||
"status != 'finished'",
|
||||
'order by start_time asc, id asc',
|
||||
$table_header,
|
||||
echoContest,
|
||||
$table_config
|
||||
);
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests',
|
||||
[["status", "!=", 'finished']],
|
||||
'order by start_time asc, id asc',
|
||||
$table_header,
|
||||
'echoContest',
|
||||
$table_config
|
||||
);
|
||||
|
||||
if ($rest_second <= 86400) {
|
||||
$notification = json_encode($upcoming_contest_name . " 已经开始了。是否要跳转到比赛页面?");
|
||||
echo <<<EOD
|
||||
if ($rest_second <= 86400) {
|
||||
$notification = json_encode($upcoming_contest_name . " 已经开始了。是否要跳转到比赛页面?");
|
||||
echo <<<EOD
|
||||
<div class="text-center bot-buffer-lg">
|
||||
<div class="text-secondary">$upcoming_contest_name 倒计时</div>
|
||||
<div id="contest-countdown"></div>
|
||||
@ -115,21 +117,23 @@ $('#contest-countdown').countdown($rest_second, function() {
|
||||
</script>
|
||||
</div>
|
||||
EOD;
|
||||
}
|
||||
?>
|
||||
}
|
||||
?>
|
||||
|
||||
<h2 class="h4">
|
||||
<h2>
|
||||
<?= UOJLocale::get('contests::ended contests') ?>
|
||||
</h2>
|
||||
|
||||
<?php
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests',
|
||||
"status = 'finished'",
|
||||
'order by start_time desc, id desc',
|
||||
$table_header,
|
||||
echoContest,
|
||||
$table_config
|
||||
);
|
||||
?>
|
||||
echoLongTable(
|
||||
['*'],
|
||||
'contests',
|
||||
['status' => 'finished'],
|
||||
'order by start_time desc, id desc',
|
||||
$table_header,
|
||||
'echoContest',
|
||||
$table_config
|
||||
);
|
||||
?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,140 +1,61 @@
|
||||
<?php
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('judger');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
$auth = false;
|
||||
if (UOJRequest::get('auth') === 'judger') {
|
||||
authenticateJudger() || UOJResponse::page403();
|
||||
$auth = true;
|
||||
} else {
|
||||
Auth::check() || redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login'] && $_GET['type'] != 'attachment') {
|
||||
become403Page();
|
||||
}
|
||||
switch (UOJRequest::get('type')) {
|
||||
case 'attachment':
|
||||
UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
if (!$auth) {
|
||||
UOJProblem::cur()->userCanDownloadAttachments(Auth::user()) || UOJResponse::page404();
|
||||
}
|
||||
|
||||
switch ($_GET['type']) {
|
||||
case 'attachment':
|
||||
if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
$visible = isProblemVisibleToUser($problem, $myUser);
|
||||
if (!$visible && $myUser != null) {
|
||||
$result = DB::query("select contest_id from contests_problems where problem_id = {$_GET['id']}");
|
||||
while (list($contest_id) = DB::fetch($result, MYSQLI_NUM)) {
|
||||
$contest = queryContest($contest_id);
|
||||
genMoreContestInfo($contest);
|
||||
if ($contest['cur_progress'] != CONTEST_NOT_STARTED && hasRegistered($myUser, $contest) && queryContestProblemRank($contest, $problem)) {
|
||||
$visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$visible) {
|
||||
become404Page();
|
||||
}
|
||||
$file_name = UOJProblem::cur()->getDataFolderPath() . '/download.zip';
|
||||
$download_name = 'problem_' . UOJProblem::info('id') . '_attachment.zip';
|
||||
|
||||
$id = $_GET['id'];
|
||||
|
||||
$file_name = "/var/uoj_data/$id/download.zip";
|
||||
$download_name = "problem_{$id}_attachment.zip";
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'problem':
|
||||
if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
case 'problem':
|
||||
UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
|
||||
if (!isProblemVisibleToUser($problem, $myUser)) {
|
||||
become404Page();
|
||||
}
|
||||
if (!$auth) {
|
||||
UOJProblem::cur()->userCanDownloadTestData(Auth::user()) || UOJResponse::page404();
|
||||
}
|
||||
|
||||
$id = $_GET['id'];
|
||||
$file_name = "/var/uoj_data/$id.zip";
|
||||
$download_name = "problem_$id.zip";
|
||||
$file_name = UOJProblem::cur()->getDataZipPath();
|
||||
$download_name = 'problem_' . UOJProblem::info('id') . '.zip';
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'testcase':
|
||||
if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
case 'submission':
|
||||
if (!$auth) {
|
||||
isSuperUser(Auth::user()) || UOJResponse::page404();
|
||||
}
|
||||
$file_name = UOJContext::storagePath() . "/submission/{$_GET['id']}/{$_GET['rand_str_id']}";
|
||||
$download_name = "submission.zip";
|
||||
break;
|
||||
|
||||
if (!isProblemVisibleToUser($problem, $myUser)) {
|
||||
become404Page();
|
||||
}
|
||||
case 'tmp':
|
||||
if (!$auth) {
|
||||
isSuperUser(Auth::user()) || UOJResponse::page404();
|
||||
}
|
||||
$file_name = UOJContext::storagePath() . "/tmp/{$_GET['rand_str_id']}";
|
||||
$download_name = "tmp";
|
||||
break;
|
||||
|
||||
$id = $_GET['id'];
|
||||
$problem_conf = getUOJConf("/var/uoj_data/$id/problem.conf");
|
||||
case 'testlib.h':
|
||||
$file_name = UOJLocalRun::$judger_include_path . '/testlib.h';
|
||||
$download_name = 'testlib.h';
|
||||
break;
|
||||
|
||||
if ($problem_conf == -1 || $problem_conf == -2) {
|
||||
become404Page();
|
||||
}
|
||||
default:
|
||||
UOJResponse::page404();
|
||||
}
|
||||
|
||||
if (!validateUInt($_GET['testcase_id'])) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
$testcase_id = $_GET['testcase_id'];
|
||||
$testcase_group = isset($_GET['testcase_group']) && $_GET['testcase_group'] == 'extra' ? 'extra' : 'normal';
|
||||
|
||||
if ($testcase_group == 'extra') {
|
||||
$n_ex_tests = getUOJConfVal($problem_conf, 'n_ex_tests', 0);
|
||||
|
||||
if ($testcase_id < 1 || $testcase_id > $n_ex_tests) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
switch ($_GET['testcase_type']) {
|
||||
case 'input':
|
||||
$file_name = "/var/uoj_data/$id/" . getUOJProblemExtraInputFileName($problem_conf, $testcase_id);
|
||||
$download_name = getUOJProblemExtraInputFileName($problem_conf, $testcase_id);
|
||||
break;
|
||||
|
||||
case 'output':
|
||||
$file_name = "/var/uoj_data/$id/" . getUOJProblemExtraOutputFileName($problem_conf, $testcase_id);
|
||||
$download_name = getUOJProblemExtraOutputFileName($problem_conf, $testcase_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
become404Page();
|
||||
}
|
||||
} else {
|
||||
$n_tests = getUOJConfVal($problem_conf, 'n_tests', 10);
|
||||
|
||||
if ($testcase_id < 1 || $testcase_id > $n_tests) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
switch ($_GET['testcase_type']) {
|
||||
case 'input':
|
||||
$file_name = "/var/uoj_data/$id/" . getUOJProblemInputFileName($problem_conf, $testcase_id);
|
||||
$download_name = getUOJProblemInputFileName($problem_conf, $testcase_id);
|
||||
break;
|
||||
case 'output':
|
||||
$file_name = "/var/uoj_data/$id/" . getUOJProblemOutputFileName($problem_conf, $testcase_id);
|
||||
$download_name = getUOJProblemOutputFileName($problem_conf, $testcase_id);
|
||||
break;
|
||||
default:
|
||||
become404Page();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'testlib.h':
|
||||
$file_name = "/opt/uoj/judger/uoj_judger/include/testlib.h";
|
||||
$download_name = "testlib.h";
|
||||
break;
|
||||
|
||||
default:
|
||||
become404Page();
|
||||
}
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfo, $file_name);
|
||||
if ($mimetype === false) {
|
||||
become404Page();
|
||||
}
|
||||
finfo_close($finfo);
|
||||
|
||||
header("X-Sendfile: $file_name");
|
||||
header("Content-type: $mimetype");
|
||||
header("Content-Disposition: attachment; filename=$download_name");
|
||||
?>
|
||||
UOJResponse::xsendfile($file_name, ['attachment' => $download_name]);
|
||||
|
@ -1,122 +1,120 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
requireLib('mathjax');
|
||||
?>
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
requireLib('mathjax');
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('help')) ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<div class="card card-default">
|
||||
<article class="card-body">
|
||||
<h1 class="h2 card-title mb-3">常见问题及其解答 (FAQ)</h1>
|
||||
|
||||
<div class="card card-default">
|
||||
<article class="card-body">
|
||||
<h1 class="h3 card-title mb-3">常见问题及其解答 (FAQ)</h1>
|
||||
<h5 class="mt-4"><?= UOJConfig::$data['profile']['oj-name-short'] ?> 是什么</h5>
|
||||
<p class="card-text">
|
||||
见 <a href="https://sjzezoj.com/blogs/1">https://sjzezoj.com/blogs/1</a>。
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4"><?= UOJConfig::$data['profile']['oj-name-short'] ?> 是什么</h5>
|
||||
<p class="card-text">
|
||||
见 <a href="https://sjzezoj.com/blogs/1">https://sjzezoj.com/blogs/1</a>。
|
||||
</p>
|
||||
<h5 class="mt-4">测评环境</h5>
|
||||
<p class="card-text">评测机的系统版本是 Ubuntu Server 22.04 LTS。</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered text-center align-middle">
|
||||
<thead>
|
||||
<th>语言</th>
|
||||
<th>版本</th>
|
||||
<th>编译命令</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>gcc 11.2.0</td>
|
||||
<td><code>gcc -o code code.c -lm -O2 -DONLINE_JUDGE</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C++</td>
|
||||
<td>g++ 11.2.0</td>
|
||||
<td><code>g++ -o code code.cpp -lm -O2 -DONLINE_JUDGE</code>(语言版本默认为 C++14,如选择其他版本还会添加 <code>-std=</code> 参数)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pascal</td>
|
||||
<td>fpc 3.2.2</td>
|
||||
<td><code>fpc code.pas -O2</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python 2</td>
|
||||
<td>Python 2.7.18</td>
|
||||
<td rowspan="2">预先编译为优化过的字节码 <code>.pyo</code> 文件</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python 3</td>
|
||||
<td>Python 3.10.6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 8</td>
|
||||
<td>OpenJDK 1.8.0_342</td>
|
||||
<td rowspan="3"><code>javac code.java</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 11</td>
|
||||
<td>OpenJDK 11.0.16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 17</td>
|
||||
<td>OpenJDK 17.0.4</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="card-text">以上信息仅供参考,实际评测环境可能会有变动。</p>
|
||||
|
||||
<h5 class="mt-4">测评环境</h5>
|
||||
<p class="card-text">评测机的系统版本是 Ubuntu Server 22.04 LTS。</p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered text-center align-middle">
|
||||
<thead>
|
||||
<th>语言</th>
|
||||
<th>版本</th>
|
||||
<th>编译命令</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>C</td>
|
||||
<td>gcc 11.2.0</td>
|
||||
<td><code>gcc -o code code.c -lm -O2 -DONLINE_JUDGE</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>C++</td>
|
||||
<td>g++ 11.2.0</td>
|
||||
<td><code>g++ -o code code.cpp -lm -O2 -DONLINE_JUDGE</code>(语言版本默认为 C++14,如选择其他版本还会添加 <code>-std=</code> 参数)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pascal</td>
|
||||
<td>fpc 3.2.2</td>
|
||||
<td><code>fpc code.pas -O2</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python 2</td>
|
||||
<td>Python 2.7.18</td>
|
||||
<td rowspan="2">预先编译为优化过的字节码 <code>.pyo</code> 文件</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Python 3</td>
|
||||
<td>Python 3.10.6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 8</td>
|
||||
<td>OpenJDK 1.8.0_342</td>
|
||||
<td rowspan="3"><code>javac code.java</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 11</td>
|
||||
<td>OpenJDK 11.0.16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Java 17</td>
|
||||
<td>OpenJDK 17.0.4</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h5 class="mt-4">如何上传头像</h5>
|
||||
<p class="card-text">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> 不提供头像存储服务。每到一个网站都要上传一个头像挺烦的对不对?我们支持 Gravatar,请使用 Gravatar 吧!Gravatar 是一个全球的头像存储服务,你的头像将会与你的电子邮箱绑定。在各大网站比如各种 Wordpress 还有各种 OJ 比如 Vijos、Contest Hunter 上,只要你电子邮箱填对了,那么你的头像也就立即能显示了!
|
||||
</p>
|
||||
<p class="card-text">
|
||||
快使用 Gravatar 吧!Gravatar 地址:<a href="https://cn.gravatar.com" target="_blank">https://cn.gravatar.com</a>。进去后注册个帐号然后与邮箱绑定并上传头像,就 OK 啦!
|
||||
</p>
|
||||
<p class="card-text">
|
||||
上不去 Gravatar?没关系,我们现在也支持 QQ 头像了!你只需要前往 “更改个人信息” 页面填写自己的 QQ 号,并将 “头像来源” 选为 “QQ” 就可以让你的 QQ 头像显示在 S2OJ 上啦!
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">递归 10<sup>7</sup> 层怎么没爆栈啊</h5>
|
||||
<p class="card-text">
|
||||
没错就是这样!除非是特殊情况,<?= UOJConfig::$data['profile']['oj-name-short'] ?> 测评程序时的栈大小与该题的空间限制是相等的!
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">联系方式</h5>
|
||||
<p class="card-text">
|
||||
题目相关问题请联系各校区的竞赛教练以及题目管理员。
|
||||
</p>
|
||||
<p class="card-text">
|
||||
系统相关问题请邮件联系 <a href="https://sjzezoj.com/user/baoshuo" class="uoj-username">baoshuo</a>(<a href="mailto:i@baoshuo.ren">i@baoshuo.ren</a>)
|
||||
和 <a href="https://sjzezoj.com/user/nekko" class="uoj-username">nekko</a>(<a href="mailto:1139855151@qq.com">1139855151@qq.com</a>)。
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">开源项目</h5>
|
||||
<p class="card-text">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> 的源代码存放于
|
||||
<a href="https://github.com/renbaoshuo/S2OJ" target="_blank">https://github.com/renbaoshuo/S2OJ</a>。
|
||||
如果你网不太好,打不开 GitHub 的话,也可以点击 <a href="https://git.m.ac/baoshuo/S2OJ" target="_blank">https://git.m.ac/baoshuo/S2OJ</a> 查看哦!这两个仓库的内容是一模一样的。
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">用户手册</h5>
|
||||
<p class="card-text">
|
||||
请移步 <a href="https://s2oj.github.io/">S2OJ 使用文档</a>。
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<!-- end left col -->
|
||||
</div>
|
||||
<p class="card-text">以上信息仅供参考,实际评测环境可能会有变动。</p>
|
||||
|
||||
<h5 class="mt-4">如何上传头像</h5>
|
||||
<p class="card-text">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> 不提供头像存储服务。每到一个网站都要上传一个头像挺烦的对不对?我们支持 Gravatar,请使用 Gravatar 吧!Gravatar 是一个全球的头像存储服务,你的头像将会与你的电子邮箱绑定。在各大网站比如各种 Wordpress 还有各种 OJ 比如 Vijos、Contest Hunter 上,只要你电子邮箱填对了,那么你的头像也就立即能显示了!
|
||||
</p>
|
||||
<p class="card-text">
|
||||
快使用 Gravatar 吧!Gravatar 地址:<a href="https://cn.gravatar.com" target="_blank">https://cn.gravatar.com</a>。进去后注册个帐号然后与邮箱绑定并上传头像,就 OK 啦!
|
||||
</p>
|
||||
<p class="card-text">
|
||||
上不去 Gravatar?没关系,我们现在也支持 QQ 头像了!你只需要前往 “更改个人信息” 页面填写自己的 QQ 号,并将 “头像来源” 选为 “QQ” 就可以让你的 QQ 头像显示在 S2OJ 上啦!
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">递归 10<sup>7</sup> 层怎么没爆栈啊</h5>
|
||||
<p class="card-text">
|
||||
没错就是这样!除非是特殊情况,<?= UOJConfig::$data['profile']['oj-name-short'] ?> 测评程序时的栈大小与该题的空间限制是相等的!
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">联系方式</h5>
|
||||
<p class="card-text">
|
||||
题目相关问题请联系各校区的竞赛教练以及题目管理员。
|
||||
</p>
|
||||
<p class="card-text">
|
||||
系统相关问题请邮件联系 <a href="https://sjzezoj.com/user/baoshuo" class="uoj-username">baoshuo</a>(<a href="mailto:i@baoshuo.ren">i@baoshuo.ren</a>)
|
||||
和 <a href="https://sjzezoj.com/user/nekko" class="uoj-username">nekko</a>(<a href="mailto:1139855151@qq.com">1139855151@qq.com</a>)。
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">开源项目</h5>
|
||||
<p class="card-text">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> 的源代码存放于
|
||||
<a href="https://github.com/renbaoshuo/S2OJ" target="_blank">https://github.com/renbaoshuo/S2OJ</a>。
|
||||
如果你网不太好,打不开 GitHub 的话,也可以点击 <a href="https://git.m.ac/baoshuo/S2OJ" target="_blank">https://git.m.ac/baoshuo/S2OJ</a> 查看哦!这两个仓库的内容是一模一样的。
|
||||
</p>
|
||||
|
||||
<h5 class="mt-4">用户手册</h5>
|
||||
<p class="card-text">
|
||||
请移步 <a href="https://s2oj.github.io/">S2OJ 使用文档</a>。
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<!-- end left col -->
|
||||
</div>
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar', array()) ?>
|
||||
</aside>
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
requirePHPLib('form');
|
||||
|
||||
$forgot_form = new UOJForm('forgot');
|
||||
$forgot_form = new UOJBs4Form('forgot');
|
||||
$forgot_form->addInput('username', 'text', '用户名', '',
|
||||
function($username, &$vdata) {
|
||||
if (!validateUsername($username)) {
|
||||
|
@ -4,14 +4,10 @@
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
$group_id = $_GET['id'];
|
||||
if (!validateUInt($group_id) || !($group = queryGroup($group_id))) {
|
||||
become404Page();
|
||||
@ -30,7 +26,7 @@
|
||||
|
||||
<!-- title -->
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?php if ($group['is_hidden']): ?>
|
||||
<span class="fs-5 text-danger">[隐藏]</span>
|
||||
<?php endif ?>
|
||||
@ -51,7 +47,7 @@
|
||||
<!-- main content -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h2 class="h4">
|
||||
<h2 class="h3">
|
||||
<?= UOJLocale::get('group announcement') ?>
|
||||
</h2>
|
||||
<?php if ($group['announcement']): ?>
|
||||
@ -68,7 +64,7 @@
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title h4">
|
||||
<h2 class="card-title h3">
|
||||
<?= UOJLocale::get('news') ?>
|
||||
</h5>
|
||||
<ul class="mb-0">
|
||||
@ -92,7 +88,7 @@
|
||||
|
||||
<div class="card card-default mb-3">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title h4">
|
||||
<h2 class="card-title h3">
|
||||
<?= UOJLocale::get('assignments') ?>
|
||||
</h5>
|
||||
<?php
|
||||
@ -139,7 +135,7 @@ EOD,
|
||||
|
||||
<div class="card card-default mb-3">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title h4">
|
||||
<h2 class="card-title h3">
|
||||
<?= UOJLocale::get('top solver') ?>
|
||||
</h5>
|
||||
<?php echoRanklist([
|
||||
|
@ -1,12 +1,8 @@
|
||||
<?php
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
|
||||
@ -40,7 +36,7 @@
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<small class="fs-4">作业:</small><?= $list['title'] ?>
|
||||
</h1>
|
||||
<ul class="mt-3">
|
||||
|
@ -43,7 +43,7 @@
|
||||
}
|
||||
|
||||
if ($cur_tab == 'profile') {
|
||||
$update_profile_form = new UOJForm('update_profile');
|
||||
$update_profile_form = new UOJBs4Form('update_profile');
|
||||
$update_profile_form->addVInput('name', 'text', '名称', $group['title'],
|
||||
function($title, &$vdata) {
|
||||
if ($title == '') {
|
||||
@ -107,7 +107,7 @@ function(res) {
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$update_profile_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$update_profile_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$update_profile_form->submit_button_config['text'] = '更新';
|
||||
$update_profile_form->runAtServer();
|
||||
} elseif ($cur_tab == 'assignments') {
|
||||
@ -127,7 +127,7 @@ EOD);
|
||||
dieWithAlert('移除成功!');
|
||||
}
|
||||
|
||||
$add_new_assignment_form = new UOJForm('add_new_assignment');
|
||||
$add_new_assignment_form = new UOJBs4Form('add_new_assignment');
|
||||
$add_new_assignment_form->addVInput('new_assignment_list_id', 'text', '题单 ID', '',
|
||||
function ($list_id, &$vdata) use ($group) {
|
||||
if (!validateUInt($list_id)) {
|
||||
@ -177,7 +177,7 @@ EOD);
|
||||
'message' => '题单 #' . $vdata['list_id'] . ' 已经被添加到作业列表中,结束时间为 ' . $vdata['end_time']->format('Y-m-d H:i:s') . '。'
|
||||
]);
|
||||
};
|
||||
$add_new_assignment_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_new_assignment_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$add_new_assignment_form->submit_button_config['text'] = '添加';
|
||||
$add_new_assignment_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
@ -223,7 +223,7 @@ EOD);
|
||||
dieWithAlert('移除成功!');
|
||||
}
|
||||
|
||||
$add_new_user_form = new UOJForm('add_new_user');
|
||||
$add_new_user_form = new UOJBs4Form('add_new_user');
|
||||
$add_new_user_form->addVInput('new_username', 'text', '用户名', '',
|
||||
function ($username, &$vdata) {
|
||||
global $group_id;
|
||||
@ -246,7 +246,7 @@ EOD);
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_user_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_new_user_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$add_new_user_form->submit_button_config['text'] = '添加';
|
||||
$add_new_user_form->handle = function(&$vdata) use ($group) {
|
||||
DB::insert("insert into groups_users (group_id, username) values ({$group['id']}, '{$vdata['username']}')");
|
||||
@ -277,7 +277,7 @@ EOD);
|
||||
?>
|
||||
<?php echoUOJPageHeader('管理 - ' . $group['title']); ?>
|
||||
|
||||
<h1 class="h2 d-block d-md-inline-block">
|
||||
<h1 class="d-block d-md-inline-block">
|
||||
<?= $group['title'] ?>
|
||||
<small class="fs-5">(ID: #<?= $group['id'] ?>)</small>
|
||||
管理
|
||||
|
@ -1,57 +1,50 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$new_group_form = new UOJForm('new_group');
|
||||
$new_group_form->handle = function() {
|
||||
DB::query("insert into `groups` (title, is_hidden) values ('新小组', 1)");
|
||||
};
|
||||
$new_group_form->submit_button_config['align'] = 'right';
|
||||
$new_group_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$new_group_form->submit_button_config['text'] = UOJLocale::get('add new group');
|
||||
$new_group_form->submit_button_config['smart_confirm'] = '';
|
||||
$new_group_form->runAtServer();
|
||||
}
|
||||
?>
|
||||
if (isSuperUser($myUser)) {
|
||||
$new_group_form = new UOJBs4Form('new_group');
|
||||
$new_group_form->handle = function () {
|
||||
DB::query("insert into `groups` (title, is_hidden) values ('新小组', 1)");
|
||||
};
|
||||
$new_group_form->submit_button_config['align'] = 'right';
|
||||
$new_group_form->submit_button_config['class_str'] = 'btn btn-primary';
|
||||
$new_group_form->submit_button_config['text'] = UOJLocale::get('add new group');
|
||||
$new_group_form->submit_button_config['smart_confirm'] = '';
|
||||
$new_group_form->runAtServer();
|
||||
}
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('groups')) ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<!-- title container -->
|
||||
<div class="d-flex justify-content-between">
|
||||
<h1>
|
||||
<?= UOJLocale::get('groups') ?>
|
||||
</h1>
|
||||
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<?php if (isset($new_group_form)) : ?>
|
||||
<div class="text-end mb-2">
|
||||
<?php $new_group_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<!-- title container -->
|
||||
<div class="d-flex justify-content-between">
|
||||
</div>
|
||||
<!-- end title container -->
|
||||
|
||||
<h1 class="h2">
|
||||
<?= UOJLocale::get('groups') ?>
|
||||
</h1>
|
||||
|
||||
<?php if (isset($new_group_form)): ?>
|
||||
<div class="text-end mb-2">
|
||||
<?php $new_group_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
</div>
|
||||
<!-- end title container -->
|
||||
|
||||
<?php
|
||||
$groups_caption = UOJLocale::get('groups');
|
||||
$users_caption = UOJLocale::get('users count');
|
||||
$header = <<<EOD
|
||||
<?php
|
||||
$groups_caption = UOJLocale::get('groups');
|
||||
$users_caption = UOJLocale::get('users count');
|
||||
$header = <<<EOD
|
||||
<tr>
|
||||
<th class="text-center" style="width:5em;">ID</th>
|
||||
<th>{$groups_caption}</th>
|
||||
@ -59,52 +52,58 @@
|
||||
</tr>
|
||||
EOD;
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$cond = "1";
|
||||
} else {
|
||||
$cond = 'is_hidden = 0';
|
||||
}
|
||||
if (isSuperUser(Auth::user())) {
|
||||
$cond = "1";
|
||||
} else {
|
||||
$cond = ["is_hidden" => false];
|
||||
}
|
||||
|
||||
echoLongTable(
|
||||
['a.id as group_id', 'a.title as title', 'a.is_hidden as is_hidden', 'count(b.username) as user_count'],
|
||||
"`groups` a left join groups_users b on a.id = b.group_id",
|
||||
$cond,
|
||||
'group by a.id order by a.id asc',
|
||||
$header,
|
||||
function ($group) use ($myUser) {
|
||||
echo '<tr class="text-center">';
|
||||
echo '<td>';
|
||||
echo '#', $group['group_id'], '</td>';
|
||||
|
||||
echo '<td class="text-start">';
|
||||
echo '<a class="text-decoration-none" href="/group/', $group['group_id'], '">', $group['title'], '</a>';
|
||||
if ($group['is_hidden']) {
|
||||
echo ' <span class="badge text-bg-danger"><i class="bi bi-eye-slash-fill"></i> ', UOJLocale::get('hidden'), '</span> ';
|
||||
}
|
||||
echo '</td>';
|
||||
|
||||
echo "<td>{$group['user_count']}</td>";
|
||||
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'my-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
'head_pagination' => true,
|
||||
'pagination_table' => "`groups`",
|
||||
]
|
||||
);
|
||||
?>
|
||||
echoLongTable(
|
||||
['id', 'title', 'is_hidden'],
|
||||
"`groups`",
|
||||
$cond,
|
||||
'order by id asc',
|
||||
$header,
|
||||
function ($group) {
|
||||
$users_count = DB::selectCount([
|
||||
"select count(*)",
|
||||
"from", "groups_users",
|
||||
"where", [
|
||||
"group_id" => $group['id'],
|
||||
],
|
||||
]);
|
||||
|
||||
<!-- end left col -->
|
||||
</div>
|
||||
echo '<tr class="text-center">';
|
||||
echo '<td>';
|
||||
echo '#', $group['id'], '</td>';
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar', array()); ?>
|
||||
</aside>
|
||||
echo '<td class="text-start">';
|
||||
echo '<a class="text-decoration-none" href="/group/', $group['id'], '">', $group['title'], '</a>';
|
||||
if ($group['is_hidden']) {
|
||||
echo ' <span class="badge text-bg-danger"><i class="bi bi-eye-slash-fill"></i> ', UOJLocale::get('hidden'), '</span> ';
|
||||
}
|
||||
echo '</td>';
|
||||
|
||||
echo "<td>{$users_count}</td>";
|
||||
|
||||
echo '</tr>';
|
||||
},
|
||||
[
|
||||
'page_len' => 40,
|
||||
'div_classes' => ['card', 'my-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
'head_pagination' => true,
|
||||
]
|
||||
);
|
||||
?>
|
||||
<!-- end left col -->
|
||||
</div>
|
||||
|
||||
<!-- right col -->
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<?php uojIncludeView('sidebar') ?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
</div>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,101 +1,117 @@
|
||||
<?php
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJHack::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
UOJHack::cur()->setProblem() || UOJResponse::page404();
|
||||
UOJHack::cur()->userCanView(Auth::user(), ['ensure' => true]);
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
if (UOJHack::cur()->setSubmission()) {
|
||||
UOJHack::cur()->submission->setAsCur();
|
||||
UOJSubmission::cur()->setProblem(['problem' => UOJHack::cur()->problem]) || UOJResponse::page404();
|
||||
UOJSubmission::cur()->userCanView(Auth::user(), ['ensure' => true]);
|
||||
}
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($hack = queryHack($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
if (UOJHack::cur()->userCanDelete(Auth::user())) {
|
||||
$delete_form = new UOJBs4Form('delete');
|
||||
$delete_form->handle = function () {
|
||||
DB::delete([
|
||||
"delete from hacks",
|
||||
"where", ["id" => UOJHack::info('id')]
|
||||
]);
|
||||
};
|
||||
$delete_form->submit_button_config['class_str'] = 'btn btn-danger';
|
||||
$delete_form->submit_button_config['text'] = '删除此 Hack';
|
||||
$delete_form->submit_button_config['align'] = 'end';
|
||||
$delete_form->submit_button_config['smart_confirm'] = '';
|
||||
$delete_form->succ_href = "/hacks";
|
||||
$delete_form->runAtServer();
|
||||
}
|
||||
|
||||
$submission = querySubmission($hack['submission_id']);
|
||||
$problem = queryProblemBrief($submission['problem_id']);
|
||||
$problem_extra_config = getProblemExtraConfig($problem);
|
||||
if (UOJHack::cur()->userCanReview(Auth::user())) {
|
||||
$addex_form = new UOJBs4Form('addex');
|
||||
$addex_form->handle = function () {
|
||||
$input = UOJContext::storagePath() . UOJHack::info('input');
|
||||
$new_in = "{$input}_in";
|
||||
$new_out = "{$input}_out";
|
||||
$reason = null;
|
||||
$err = dataAddHackPoint(UOJHack::cur()->problem->info, $new_in, $new_out, $reason, Auth::user());
|
||||
$err === '' || UOJResponse::message($err);
|
||||
unlink($new_in);
|
||||
unlink($new_out);
|
||||
DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
'status' => 'Judged',
|
||||
], "where", ['id' => UOJHack::info('id')]
|
||||
]);
|
||||
};
|
||||
$addex_form->submit_button_config['class_str'] = 'btn btn-danger mt-3';
|
||||
$addex_form->submit_button_config['text'] = '确认无误,添加到测试数据';
|
||||
$addex_form->submit_button_config['align'] = 'end';
|
||||
$addex_form->submit_button_config['smart_confirm'] = '';
|
||||
$addex_form->succ_href = "/hacks";
|
||||
$addex_form->runAtServer();
|
||||
}
|
||||
|
||||
if ($submission['contest_id']) {
|
||||
$contest = queryContest($submission['contest_id']);
|
||||
genMoreContestInfo($contest);
|
||||
} else {
|
||||
$contest = null;
|
||||
}
|
||||
$perm = UOJHack::cur()->viewerCanSeeComponents(Auth::user());
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('problems::hack') . ' #' . UOJHack::info('id')) ?>
|
||||
|
||||
if (!isHackVisibleToUser($hack, $problem, $myUser)) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$delete_form = new UOJForm('delete');
|
||||
$delete_form->handle = function() {
|
||||
global $hack;
|
||||
DB::query("delete from hacks where id = {$hack['id']}");
|
||||
};
|
||||
$delete_form->submit_button_config['class_str'] = 'btn btn-danger';
|
||||
$delete_form->submit_button_config['text'] = '删除此Hack';
|
||||
$delete_form->submit_button_config['align'] = 'right';
|
||||
$delete_form->submit_button_config['smart_confirm'] = '';
|
||||
$delete_form->succ_href = "/hacks";
|
||||
$delete_form->runAtServer();
|
||||
}
|
||||
|
||||
$should_show_content = hasViewPermission($problem_extra_config['view_content_type'], $myUser, $problem, $submission);
|
||||
$should_show_all_details = hasViewPermission($problem_extra_config['view_all_details_type'], $myUser, $problem, $submission);
|
||||
$should_show_details = hasViewPermission($problem_extra_config['view_details_type'], $myUser, $problem, $submission);
|
||||
$should_show_details_to_me = isSuperUser($myUser);
|
||||
if ($hack['success'] === null) {
|
||||
$should_show_all_details = false;
|
||||
}
|
||||
if (!isSubmissionFullVisibleToUser($submission, $contest, $problem, $myUser)
|
||||
|| !isHackFullVisibleToUser($hack, $contest, $problem, $myUser)) {
|
||||
$should_show_content = $should_show_all_details = false;
|
||||
}
|
||||
|
||||
if ($should_show_all_details) {
|
||||
$styler = new HackDetailsStyler();
|
||||
if (!$should_show_details) {
|
||||
$styler->fade_all_details = true;
|
||||
$styler->show_small_tip = false;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('problems::hack').' #'.$hack['id']) ?>
|
||||
|
||||
<h1 class="h3">
|
||||
<?= UOJLocale::get('problems::hack').' #'.$hack['id'] ?>
|
||||
<h1>
|
||||
<?= UOJLocale::get('problems::hack') . ' #' . UOJHack::info('id') ?>
|
||||
</h1>
|
||||
|
||||
<?php echoHackListOnlyOne($hack, array('id_hidden' => ''), $myUser) ?>
|
||||
<?php if ($should_show_all_details): ?>
|
||||
<div class="card border-info mb-3">
|
||||
<div class="card-header bg-info">
|
||||
<h4 class="card-title"><?= UOJLocale::get('details') ?></h4>
|
||||
<?php echoHackListOnlyOne(UOJHack::info(), [], Auth::user()) ?>
|
||||
|
||||
<?php if (UOJHack::cur()->hasJudged()) : ?>
|
||||
<?php if ($perm['high_level_details']) : ?>
|
||||
<div class="card mb-3">
|
||||
<div class="card-header fw-bold">
|
||||
<?= UOJLocale::get('details') ?>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<?php
|
||||
$styler = new HackDetailsStyler();
|
||||
if (!$perm['low_level_details']) {
|
||||
$styler->fade_all_details = true;
|
||||
$styler->show_small_tip = false;
|
||||
}
|
||||
echoJudgmentDetails(UOJHack::info('details'), $styler, 'details');
|
||||
?>
|
||||
<?php if ($perm['manager_view'] && !$perm['low_level_details']) : ?>
|
||||
<hr />
|
||||
<h4 class="text-info">全部详细信息(仅管理员可见)</h4>
|
||||
<?php echoHackDetails(UOJHack::info('details'), 'all_details') ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php echoJudgementDetails($hack['details'], $styler, 'details') ?>
|
||||
<?php if ($should_show_details_to_me): ?>
|
||||
<?php if ($styler->fade_all_details): ?>
|
||||
<hr />
|
||||
<?php echoHackDetails($hack['details'], 'final_details') ?>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
|
||||
<h2 class="h3">
|
||||
<?= UOJLocale::get('problems::submission').' #'.$submission['id'] ?>
|
||||
<h2 class="mt-3">
|
||||
<?= UOJLocale::get('problems::submission') . ' #' . UOJSubmission::info('id') ?>
|
||||
</h2>
|
||||
|
||||
<?php echoSubmissionsListOnlyOne($submission, array(), $myUser) ?>
|
||||
<?php if ($should_show_content): ?>
|
||||
<?php echoSubmissionContent($submission, getProblemSubmissionRequirement($problem)) ?>
|
||||
<?php if (UOJSubmission::cur()) : ?>
|
||||
<?php UOJSubmission::cur()->echoStatusTable(['show_actual_score' => $perm['score']], Auth::user()) ?>
|
||||
<?php if ($perm['content'] || $perm['manager_view']) : ?>
|
||||
<?php UOJSubmission::cur()->echoContent() ?>
|
||||
<?php endif ?>
|
||||
<?php else : ?>
|
||||
<h3 class="text-danger">提交记录信息损坏</h3>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (isset($delete_form)): ?>
|
||||
<?php if (isset($delete_form)) : ?>
|
||||
<?php $delete_form->printHTML() ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if (isset($addex_form)) : ?>
|
||||
<?php $addex_form->printHTML() ?>
|
||||
<?php endif ?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,60 +1,54 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requireLib('bootstrap5');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
$q_problem_id = isset($_GET['problem_id']) && validateUInt($_GET['problem_id']) ? $_GET['problem_id'] : null;
|
||||
$q_submission_id = isset($_GET['submission_id']) && validateUInt($_GET['submission_id']) ? $_GET['submission_id'] : null;
|
||||
$q_hacker = isset($_GET['hacker']) && validateUsername($_GET['hacker']) ? $_GET['hacker'] : null;
|
||||
$q_owner = isset($_GET['owner']) && validateUsername($_GET['owner']) ? $_GET['owner'] : null;
|
||||
|
||||
$conds = array();
|
||||
$conds = [];
|
||||
if ($q_problem_id != null) {
|
||||
$conds[] = ["problem_id" => $q_problem_id];
|
||||
}
|
||||
if ($q_submission_id != null) {
|
||||
$conds[] = ["submission_id" => $q_submission_id];
|
||||
}
|
||||
if ($q_hacker != null) {
|
||||
$conds[] = ["hacker" => $q_hacker];
|
||||
}
|
||||
if ($q_owner != null) {
|
||||
$conds[] = ["owner" => $q_owner];
|
||||
}
|
||||
|
||||
$q_problem_id = isset($_GET['problem_id']) && validateUInt($_GET['problem_id']) ? $_GET['problem_id'] : null;
|
||||
$q_submission_id = isset($_GET['submission_id']) && validateUInt($_GET['submission_id']) ? $_GET['submission_id'] : null;
|
||||
$q_hacker = isset($_GET['hacker']) && validateUsername($_GET['hacker']) ? $_GET['hacker'] : null;
|
||||
$q_owner = isset($_GET['owner']) && validateUsername($_GET['owner']) ? $_GET['owner'] : null;
|
||||
if ($q_problem_id != null) {
|
||||
$conds[] = "problem_id = $q_problem_id";
|
||||
$selected_all = ' selected="selected"';
|
||||
$selected_succ = '';
|
||||
$selected_fail = '';
|
||||
if (isset($_GET['status']) && validateUInt($_GET['status'])) {
|
||||
if ($_GET['status'] == 1) {
|
||||
$selected_all = '';
|
||||
$selected_succ = ' selected="selected"';
|
||||
$conds[] = 'success = 1';
|
||||
}
|
||||
if ($q_submission_id != null) {
|
||||
$conds[] = "submission_id = $q_submission_id";
|
||||
if ($_GET['status'] == 2) {
|
||||
$selected_all = '';
|
||||
$selected_fail = ' selected="selected"';
|
||||
$conds[] = 'success = 0';
|
||||
}
|
||||
if ($q_hacker != null) {
|
||||
$conds[] = "hacker = '$q_hacker'";
|
||||
}
|
||||
if ($q_owner != null) {
|
||||
$conds[] = "owner = '$q_owner'";
|
||||
}
|
||||
|
||||
$selected_all = ' selected="selected"';
|
||||
$selected_succ ='';
|
||||
$selected_fail ='';
|
||||
if (isset($_GET['status']) && validateUInt($_GET['status'])) {
|
||||
if ($_GET['status'] == 1) {
|
||||
$selected_all = '';
|
||||
$selected_succ =' selected="selected"';
|
||||
$conds[] = 'success = 1';
|
||||
}
|
||||
if ($_GET['status'] == 2) {
|
||||
$selected_all = '';
|
||||
$selected_fail = ' selected="selected"';
|
||||
$conds[] = 'success = 0';
|
||||
}
|
||||
}
|
||||
|
||||
if ($conds) {
|
||||
$cond = join($conds, ' and ');
|
||||
} else {
|
||||
$cond = '1';
|
||||
}
|
||||
|
||||
?>
|
||||
}
|
||||
|
||||
if ($conds) {
|
||||
$cond = $conds;
|
||||
} else {
|
||||
$cond = '1';
|
||||
}
|
||||
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('hacks')) ?>
|
||||
|
||||
<h1 class="h2">
|
||||
<?= UOJLocale::get('hacks') ?>
|
||||
<h1>
|
||||
<?= UOJLocale::get('hacks') ?>
|
||||
</h1>
|
||||
|
||||
<div class="d-none d-sm-block mb-3">
|
||||
@ -77,10 +71,10 @@
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control form-control-sm" name="hacker" id="input-hacker" value="<?= $q_hacker ?>" maxlength="20" style="width:10em" />
|
||||
<?php if (Auth::check()): ?>
|
||||
<a id="my-hacks" href="/hacks?hacker=<?= Auth::id() ?>" class="btn btn-outline-secondary btn-sm">
|
||||
我的
|
||||
</a>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<a id="my-hacks" href="/hacks?hacker=<?= Auth::id() ?>" class="btn btn-outline-secondary btn-sm">
|
||||
我的
|
||||
</a>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<script>
|
||||
@ -97,10 +91,10 @@
|
||||
</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control form-control-sm" name="owner" id="input-owner" value="<?= $q_owner ?>" maxlength="20" style="width:10em" />
|
||||
<?php if (Auth::check()): ?>
|
||||
<a id="my-owners" href="/hacks?owner=<?= Auth::id() ?>" class="btn btn-outline-secondary btn-sm">
|
||||
我的
|
||||
</a>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<a id="my-owners" href="/hacks?owner=<?= Auth::id() ?>" class="btn btn-outline-secondary btn-sm">
|
||||
我的
|
||||
</a>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<script>
|
||||
@ -116,9 +110,9 @@
|
||||
<?= UOJLocale::get('problems::result') ?>:
|
||||
</label>
|
||||
<select class="form-select form-select-sm" id="input-status" name="status">
|
||||
<option value=""<?= $selected_all?>>All</option>
|
||||
<option value="1"<?= $selected_succ ?>>Success!</option>
|
||||
<option value="2"<?= $selected_fail ?>>Failed.</option>
|
||||
<option value="" <?= $selected_all ?>>All</option>
|
||||
<option value="1" <?= $selected_succ ?>>Success!</option>
|
||||
<option value="2" <?= $selected_fail ?>>Failed.</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
@ -129,7 +123,9 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php echoHacksList($cond,
|
||||
<?php
|
||||
echoHacksList(
|
||||
$cond,
|
||||
'order by id desc',
|
||||
[
|
||||
'judge_time_hidden' => '',
|
||||
@ -138,7 +134,8 @@
|
||||
'table_classes' => ['table', 'mb-0', 'uoj-table', 'text-center'],
|
||||
],
|
||||
],
|
||||
$myUser);
|
||||
?>
|
||||
Auth::user()
|
||||
);
|
||||
?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,19 +1,18 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
?>
|
||||
<?php requireLib('bootstrap5') ?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('html to markdown')) ?>
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?= UOJLocale::get('html to markdown') ?>
|
||||
</h1>
|
||||
|
||||
<style>
|
||||
#html, #markdown {
|
||||
font-family: Cascadia Mono, Ubuntu Mono, Roboto Mono, Jetbrains Mono, Fira Code, Consolas, '思源黑体 Regular', '思源宋体 Light', '宋体', 'Courier New', monospace;
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
#html,
|
||||
#markdown {
|
||||
font-family: Cascadia Mono, Ubuntu Mono, Roboto Mono, Jetbrains Mono, Fira Code, Consolas, '思源黑体 Regular', '思源宋体 Light', '宋体', 'Courier New', monospace;
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="card">
|
||||
@ -35,11 +34,13 @@
|
||||
<?= HTML::js_src('/js/h2m.js') ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#html').on('input', function() {
|
||||
$('#markdown').val(h2m($('#html').val(), { converter: 'Gfm' }));
|
||||
$(document).ready(function() {
|
||||
$('#html').on('input', function() {
|
||||
$('#markdown').val(h2m($('#html').val(), {
|
||||
converter: 'Gfm'
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,24 +1,23 @@
|
||||
<?php
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page(UOJLocale::get('need login'));
|
||||
}
|
||||
if (!Auth::check()) {
|
||||
become403Page(UOJLocale::get('need login'));
|
||||
}
|
||||
|
||||
$name = $_GET['image_name'];
|
||||
if (!validateString($name)) {
|
||||
become404Page();
|
||||
}
|
||||
$name = $_GET['image_name'];
|
||||
if (!validateString($name)) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
$file_name = UOJContext::storagePath()."/image_hosting/$name.png";
|
||||
$file_name = UOJContext::storagePath() . "/image_hosting/$name.png";
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfo, $file_name);
|
||||
if ($mimetype === false) {
|
||||
become404Page();
|
||||
}
|
||||
finfo_close($finfo);
|
||||
|
||||
header("X-Sendfile: $file_name");
|
||||
header("Content-type: $mimetype");
|
||||
header("Cache-Control: max-age=604800", true);
|
||||
$finfo = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfo, $file_name);
|
||||
if ($mimetype === false) {
|
||||
become404Page();
|
||||
}
|
||||
finfo_close($finfo);
|
||||
|
||||
header("X-Sendfile: $file_name");
|
||||
header("Content-type: $mimetype");
|
||||
header("Cache-Control: max-age=604800", true);
|
||||
|
@ -1,235 +1,241 @@
|
||||
<?php
|
||||
use Gregwar\Captcha\PhraseBuilder;
|
||||
use Gregwar\Captcha\CaptchaBuilder;
|
||||
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
use Gregwar\Captcha\PhraseBuilder;
|
||||
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
|
||||
Auth::check() || redirectToLogin();
|
||||
|
||||
$extra = UOJUser::getExtra($user);
|
||||
$limit = $extra['image_hosting']['total_size_limit'];
|
||||
$used = DB::selectSingle([
|
||||
"select sum(size)",
|
||||
"from users_images",
|
||||
"where", [
|
||||
"uploader" => Auth::id(),
|
||||
],
|
||||
]);
|
||||
$count = DB::selectCount([
|
||||
"select count(*)",
|
||||
"from users_images",
|
||||
"where", [
|
||||
"uploader" => Auth::id(),
|
||||
],
|
||||
]);
|
||||
|
||||
function throwError($msg) {
|
||||
dieWithJsonData(['status' => 'error', 'message' => $msg]);
|
||||
}
|
||||
|
||||
$allowedTypes = [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_WEBP];
|
||||
if ($_POST['image_upload_file_submit'] == 'submit') {
|
||||
if (!crsf_check()) {
|
||||
throwError('expired');
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser)) {
|
||||
become403Page();
|
||||
if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $_POST['captcha'])) {
|
||||
throwError("bad_captcha");
|
||||
}
|
||||
|
||||
$limit = $myUser['images_size_limit'];
|
||||
$_result = DB::selectFirst("SELECT SUM(size), count(*) FROM `users_images` WHERE uploader = '{$myUser['username']}'");
|
||||
$used = $_result["SUM(size)"];
|
||||
$count = $_result["count(*)"];
|
||||
|
||||
function throwError($msg) {
|
||||
dieWithJsonData(['status' => 'error', 'message' => $msg]);
|
||||
if ($_FILES["image_upload_file"]["error"] > 0) {
|
||||
throwError($_FILES["image_upload_file"]["error"]);
|
||||
}
|
||||
|
||||
$allowedTypes = [IMAGETYPE_PNG, IMAGETYPE_JPEG];
|
||||
if ($_POST['image_upload_file_submit'] == 'submit') {
|
||||
if (!crsf_check()) {
|
||||
throwError('expired');
|
||||
}
|
||||
if ($_FILES["image_upload_file"]["size"] > 5242880) { // 5 MB
|
||||
throwError('too_large');
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $_POST['captcha'])) {
|
||||
throwError("bad_captcha");
|
||||
}
|
||||
if ($used + $_FILES["image_upload_file"]["size"] > $limit) {
|
||||
throwError('storage_limit_exceeded');
|
||||
}
|
||||
|
||||
if ($_FILES["image_upload_file"]["error"] > 0) {
|
||||
throwError($_FILES["image_upload_file"]["error"]);
|
||||
}
|
||||
$size = getimagesize($_FILES['image_upload_file']['tmp_name']);
|
||||
|
||||
if ($_FILES["image_upload_file"]["size"] > 5242880) { // 5 MB
|
||||
throwError('too_large');
|
||||
}
|
||||
if (!$size || !in_array($size[2], $allowedTypes)) {
|
||||
throwError('not_a_image');
|
||||
}
|
||||
|
||||
if ($used + $_FILES["image_upload_file"]["size"] > $limit) {
|
||||
throwError('storage_limit_exceeded');
|
||||
}
|
||||
list($width, $height, $type) = $size;
|
||||
$hash = hash_file("sha256", $_FILES['image_upload_file']['tmp_name']);
|
||||
$scale = ceil($height / 600.0);
|
||||
|
||||
$size = getimagesize($_FILES['image_upload_file']['tmp_name']);
|
||||
$watermark_text = UOJConfig::$data['profile']['oj-name-short'];
|
||||
if (isSuperUser($myUser) && $_POST['watermark'] == 'no_watermark') {
|
||||
$watermark_text = "";
|
||||
$hash .= "__no_watermark";
|
||||
} elseif ($_POST['watermark'] == 'site_shortname_and_username') {
|
||||
$watermark_text .= ' @' . Auth::id();
|
||||
$hash .= "__id_" . Auth::id();
|
||||
}
|
||||
|
||||
if (!$size || !in_array($size[2], $allowedTypes)) {
|
||||
throwError('not_a_image');
|
||||
}
|
||||
$existing_image = DB::selectFirst("SELECT * FROM users_images WHERE `hash` = '$hash'");
|
||||
|
||||
list($width, $height, $type) = $size;
|
||||
$hash = hash_file("sha256", $_FILES['image_upload_file']['tmp_name']);
|
||||
$scale = ceil($height / 600.0);
|
||||
if ($existing_image) {
|
||||
dieWithJsonData(['status' => 'success', 'path' => $existing_image['path']]);
|
||||
}
|
||||
|
||||
$watermark_text = UOJConfig::$data['profile']['oj-name-short'];
|
||||
if (isSuperUser($myUser) && $_POST['watermark'] == 'no_watermark') {
|
||||
$watermark_text = "";
|
||||
$hash .= "__no_watermark";
|
||||
} elseif ($_POST['watermark'] == 'site_shortname_and_username') {
|
||||
$watermark_text .= ' @'.Auth::id();
|
||||
$hash .= "__id_".Auth::id();
|
||||
}
|
||||
$image = new Imagick($_FILES["image_upload_file"]["tmp_name"]);
|
||||
$draw = new ImagickDraw();
|
||||
$draw->setFont(UOJContext::documentRoot() . '/fonts/roboto-mono/RobotoMono-Bold.ttf');
|
||||
$draw->setFontSize($scale * 14);
|
||||
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);
|
||||
$draw->setFillColor("rgba(100,100,100,0.5)");
|
||||
$image->annotateImage($draw, 15, 10, 0, $watermark_text);
|
||||
$draw->setFillColor("rgba(255,255,255,0.65)");
|
||||
$image->annotateImage($draw, 15 + $scale, 10 + $scale, 0, $watermark_text);
|
||||
$image->setImageFormat('png');
|
||||
$image->writeImage();
|
||||
|
||||
$existing_image = DB::selectFirst("SELECT * FROM users_images WHERE `hash` = '$hash'");
|
||||
if (($size = filesize($_FILES["image_upload_file"]["tmp_name"])) > 5242880) { // 5 MB
|
||||
throwError('too_large');
|
||||
}
|
||||
|
||||
if ($existing_image) {
|
||||
dieWithJsonData(['status' => 'success', 'path' => $existing_image['path']]);
|
||||
}
|
||||
$filename = uojRandAvaiableFileName('/image_hosting/', 10, '.png');
|
||||
if (!move_uploaded_file($_FILES["image_upload_file"]["tmp_name"], UOJContext::storagePath() . $filename)) {
|
||||
throwError('unknown error');
|
||||
}
|
||||
|
||||
$image = new Imagick($_FILES["image_upload_file"]["tmp_name"]);
|
||||
$draw = new ImagickDraw();
|
||||
$draw->setFont(UOJContext::documentRoot().'/fonts/roboto-mono/RobotoMono-Bold.ttf');
|
||||
$draw->setFontSize($scale * 14);
|
||||
$draw->setGravity(Imagick::GRAVITY_SOUTHEAST);
|
||||
$draw->setFillColor("rgba(100,100,100,0.5)");
|
||||
$image->annotateImage($draw, 15, 10, 0, $watermark_text);
|
||||
$draw->setFillColor("rgba(255,255,255,0.65)");
|
||||
$image->annotateImage($draw, 15 + $scale, 10 + $scale, 0, $watermark_text);
|
||||
$image->setImageFormat('png');
|
||||
$image->writeImage();
|
||||
DB::insert("INSERT INTO users_images (`path`, uploader, width, height, upload_time, size, `hash`) VALUES ('$filename', '{$myUser['username']}', $width, $height, now(), {$_FILES["image_upload_file"]["size"]}, '$hash')");
|
||||
|
||||
if (($size = filesize($_FILES["image_upload_file"]["tmp_name"])) > 5242880) { // 5 MB
|
||||
throwError('too_large');
|
||||
}
|
||||
dieWithJsonData(['status' => 'success', 'path' => $filename]);
|
||||
} elseif ($_POST['image_delete_submit'] == 'submit') {
|
||||
crsf_defend();
|
||||
|
||||
$filename = uojRandAvaiableFileName('/image_hosting/', 10, '.png');
|
||||
if (!move_uploaded_file($_FILES["image_upload_file"]["tmp_name"], UOJContext::storagePath().$filename)) {
|
||||
throwError('unknown error');
|
||||
}
|
||||
|
||||
DB::insert("INSERT INTO users_images (`path`, uploader, width, height, upload_time, size, `hash`) VALUES ('$filename', '{$myUser['username']}', $width, $height, now(), {$_FILES["image_upload_file"]["size"]}, '$hash')");
|
||||
|
||||
dieWithJsonData(['status' => 'success', 'path' => $filename]);
|
||||
} elseif ($_POST['image_delete_submit'] == 'submit') {
|
||||
crsf_defend();
|
||||
|
||||
$id = $_POST['image_delete_id'];
|
||||
if (!validateUInt($id)) {
|
||||
becomeMsgPage('ID 不合法。<a href="'.UOJContext::requestURI().'">返回</a>');
|
||||
$id = $_POST['image_delete_id'];
|
||||
if (!validateUInt($id)) {
|
||||
becomeMsgPage('ID 不合法。<a href="' . UOJContext::requestURI() . '">返回</a>');
|
||||
} else {
|
||||
$result = DB::selectFirst("SELECT * from users_images WHERE id = $id");
|
||||
if (!$result) {
|
||||
becomeMsgPage('图片不存在。<a href="' . UOJContext::requestURI() . '">返回</a>');
|
||||
} else {
|
||||
$result = DB::selectFirst("SELECT * from users_images WHERE id = $id");
|
||||
if (!$result) {
|
||||
becomeMsgPage('图片不存在。<a href="'.UOJContext::requestURI().'">返回</a>');
|
||||
} else {
|
||||
unlink(UOJContext::storagePath().$result['path']);
|
||||
DB::delete("DELETE FROM users_images WHERE id = $id");
|
||||
unlink(UOJContext::storagePath() . $result['path']);
|
||||
DB::delete("DELETE FROM users_images WHERE id = $id");
|
||||
|
||||
header("Location: ". UOJContext::requestURI());
|
||||
die();
|
||||
}
|
||||
header("Location: " . UOJContext::requestURI());
|
||||
die();
|
||||
}
|
||||
}
|
||||
?>
|
||||
}
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(UOJLocale::get('image hosting')) ?>
|
||||
|
||||
<style>
|
||||
.drop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
flex-grow: 0 !important;
|
||||
width: 9em;
|
||||
height: 8.75em;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
margin-left: 0;
|
||||
background: #fafafa;
|
||||
border: 1px solid #e8e8e8;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.drop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-self: center;
|
||||
flex-grow: 0 !important;
|
||||
width: 9em;
|
||||
height: 8.75em;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
margin-left: 0;
|
||||
background: #fafafa;
|
||||
border: 1px solid #e8e8e8;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.drop:hover {
|
||||
border-color: #89d1f5;
|
||||
}
|
||||
.drop:hover {
|
||||
border-color: #89d1f5;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?= UOJLocale::get('image hosting') ?>
|
||||
</h1>
|
||||
|
||||
<div class="card card-default">
|
||||
<div class="card-body">
|
||||
<form class="row m-0" id="image-upload-form" method="post" enctype="multipart/form-data">
|
||||
<div class="col-12 col-md-3 col-lg-3 order-1 drop mx-auto mx-md-0" id="image-upload-form-drop">
|
||||
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="56" class="mb-2">
|
||||
<g>
|
||||
<path fill="#3498db" d="M424.49 120.48a12 12 0 0 0-17 0L272 256l-39.51-39.52a12 12 0 0 0-17 0L160 272v48h352V208zM64 336V128H48a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48v-16H144a80.09 80.09 0 0 1-80-80z"></path>
|
||||
<path fill="#89d1f5" d="M528 32H144a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48zM208 80a48 48 0 1 1-48 48 48 48 0 0 1 48-48zm304 240H160v-48l55.52-55.52a12 12 0 0 1 17 0L272 256l135.52-135.52a12 12 0 0 1 17 0L512 208z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
<span id="select-image-text" class="small">点击此处选择图片</span>
|
||||
</div>
|
||||
<input id="image_upload_file" name="image_upload_file" type="file" accept="image/*" style="display: none;" />
|
||||
<div class="modal fade" id="image-upload-modal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">上传图片</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
您确定要上传图片吗?
|
||||
<div class="card-body">
|
||||
<form class="row m-0" id="image-upload-form" method="post" enctype="multipart/form-data">
|
||||
<div class="col-12 col-md-3 col-lg-3 order-1 drop mx-auto mx-md-0" id="image-upload-form-drop">
|
||||
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="56" class="mb-2">
|
||||
<g>
|
||||
<path fill="#3498db" d="M424.49 120.48a12 12 0 0 0-17 0L272 256l-39.51-39.52a12 12 0 0 0-17 0L160 272v48h352V208zM64 336V128H48a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48v-16H144a80.09 80.09 0 0 1-80-80z"></path>
|
||||
<path fill="#89d1f5" d="M528 32H144a48 48 0 0 0-48 48v256a48 48 0 0 0 48 48h384a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48zM208 80a48 48 0 1 1-48 48 48 48 0 0 1 48-48zm304 240H160v-48l55.52-55.52a12 12 0 0 1 17 0L272 256l135.52-135.52a12 12 0 0 1 17 0L512 208z"></path>
|
||||
</g>
|
||||
</svg>
|
||||
<span id="select-image-text" class="small">点击此处选择图片</span>
|
||||
</div>
|
||||
<input id="image_upload_file" name="image_upload_file" type="file" accept="image/*" style="display: none;" />
|
||||
<div class="modal fade" id="image-upload-modal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">上传图片</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="mb-3" id="modal-file-info"></div>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="input-captcha" name="captcha" placeholder="<?= UOJLocale::get('enter verification code') ?>" maxlength="20" />
|
||||
<span class="input-group-text p-0 overflow-hidden rounded-0" style="border-bottom-right-radius: var(--bs-border-radius) !important">
|
||||
<img id="captcha" class="col w-100 h-100" src="/captcha">
|
||||
</span>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
您确定要上传图片吗?
|
||||
</div>
|
||||
<div class="mb-3" id="modal-file-info"></div>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" id="input-captcha" name="captcha" placeholder="<?= UOJLocale::get('enter verification code') ?>" maxlength="20" />
|
||||
<span class="input-group-text p-0 overflow-hidden rounded-0" style="border-bottom-right-radius: var(--bs-border-radius) !important">
|
||||
<img id="captcha" class="col w-100 h-100" src="/captcha">
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-3" id="modal-help-message" style="display: none"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="cancel-upload">取消</button>
|
||||
<button type="submit" class="btn btn-primary">确定</button>
|
||||
</div>
|
||||
<div class="mt-3" id="modal-help-message" style="display: none"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" id="cancel-upload">取消</button>
|
||||
<button type="submit" class="btn btn-primary">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 col-lg-2 order-2 mt-3 mt-md-0 ms-md-2">
|
||||
<h2 class="h4">水印</h2>
|
||||
<?php if (isSuperUser($myUser)): ?>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-no_watermark" data-value="no_watermark">
|
||||
<label class="form-check-label" for="watermark-no_watermark">
|
||||
无水印
|
||||
</label>
|
||||
<div class="col-12 col-md-4 col-lg-2 order-2 mt-3 mt-md-0 ms-md-2">
|
||||
<h2 class="h3">水印</h2>
|
||||
<?php if (isSuperUser($myUser)) : ?>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-no_watermark" data-value="no_watermark">
|
||||
<label class="form-check-label" for="watermark-no_watermark">
|
||||
无水印
|
||||
</label>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname" data-value="site_shortname" checked>
|
||||
<label class="form-check-label" for="watermark-site_shortname">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname_and_username" data-value="site_shortname_and_username">
|
||||
<label class="form-check-label" for="watermark-site_shortname_and_username">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname" data-value="site_shortname" checked>
|
||||
<label class="form-check-label" for="watermark-site_shortname">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?>
|
||||
</label>
|
||||
<div class="col order-3 order-md-4 order-lg-3 mt-3 mt-lg-0 ms-lg-2">
|
||||
<h2 class="h3">上传须知</h2>
|
||||
<ul>
|
||||
<li>上传的图片必须符合法律与社会道德;</li>
|
||||
<li>图床仅供 S2OJ 站内使用,校外用户无法查看;</li>
|
||||
<li>图片上传后会被自动转码为 PNG 格式;</li>
|
||||
<li>在合适的地方插入图片即可引用。</li>
|
||||
</ul>
|
||||
<p class="small">更多信息可以查看 <a href="https://s2oj.github.io/#/user/apps/image_hosting" target="_blank">使用文档</a>。</p>
|
||||
</div>
|
||||
<div class="form-check d-inline-block d-md-block me-2">
|
||||
<input class="form-check-input" type="radio" name="watermark" id="watermark-site_shortname_and_username" data-value="site_shortname_and_username">
|
||||
<label class="form-check-label" for="watermark-site_shortname_and_username">
|
||||
<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>
|
||||
</label>
|
||||
<div class="col-12 col-md-5 col-lg-3 order-4 order-md-3 order-lg-4 mt-3 mt-md-0 ms-md-2">
|
||||
<h2 class="h3">使用统计</h2>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="small">已用空间</span>
|
||||
<span><?= round($used * 1.0 / 1024 / 1024, 2) ?> MB / <?= round($limit * 1.0 / 1024 / 1024, 2) ?> MB</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="small">上传总数</span>
|
||||
<span><?= $count ?> 张</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col order-3 order-md-4 order-lg-3 mt-3 mt-lg-0 ms-lg-2">
|
||||
<h2 class="h4">上传须知</h2>
|
||||
<ul>
|
||||
<li>上传的图片必须符合法律与社会道德;</li>
|
||||
<li>图床仅供 S2OJ 站内使用,校外用户无法查看;</li>
|
||||
<li>图片上传后会被自动转码为 PNG 格式;</li>
|
||||
<li>在合适的地方插入图片即可引用。</li>
|
||||
</ul>
|
||||
<p class="small">更多信息可以查看 <a href="https://s2oj.github.io/#/user/apps/image_hosting" target="_blank">使用文档</a>。</p>
|
||||
</div>
|
||||
<div class="col-12 col-md-5 col-lg-3 order-4 order-md-3 order-lg-4 mt-3 mt-md-0 ms-md-2">
|
||||
<h2 class="h4">使用统计</h2>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="small">已用空间</span>
|
||||
<span><?= round($used * 1.0 / 1024 / 1024, 2) ?> MB / <?= round($limit * 1.0 / 1024 / 1024, 2) ?> MB</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="small">上传总数</span>
|
||||
<span><?= $count ?> 张</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toast-container position-fixed bottom-0 start-0 ms-3 mb-4" style="z-index: 999999">
|
||||
<div id="image-upload-toast" class="toast text-bg-danger align-items-center border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
@ -242,130 +248,132 @@
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var image_upload_modal = new bootstrap.Modal('#image-upload-modal');
|
||||
var image_upload_toast = new bootstrap.Toast('#image-upload-toast', { delay: 2000 });
|
||||
var droppedFiles = false;
|
||||
var image_upload_modal = new bootstrap.Modal('#image-upload-modal');
|
||||
var image_upload_toast = new bootstrap.Toast('#image-upload-toast', {
|
||||
delay: 2000
|
||||
});
|
||||
var droppedFiles = false;
|
||||
|
||||
function refreshCaptcha() {
|
||||
var timestamp = new Date().getTime();
|
||||
$("#captcha").attr("src", "/captcha" + '?' + timestamp);
|
||||
}
|
||||
|
||||
$("#captcha").click(function(e) {
|
||||
refreshCaptcha();
|
||||
});
|
||||
|
||||
$('#image-upload-form').submit(function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var data = new FormData();
|
||||
data.append('_token', "<?= crsf_token() ?>");
|
||||
data.append('image_upload_file_submit', 'submit');
|
||||
data.append('image_upload_file', $('#image_upload_file').prop('files')[0]);
|
||||
data.append('watermark', $('input[name=watermark]:checked', this).data('value'));
|
||||
data.append('captcha', $('#input-captcha').val());
|
||||
|
||||
if ($('#image_upload_file').prop('files')[0].size > 5242880) {
|
||||
$('#modal-help-message').html('图片大小不能超过 5 MB。').show();
|
||||
|
||||
return false;
|
||||
function refreshCaptcha() {
|
||||
var timestamp = new Date().getTime();
|
||||
$("#captcha").attr("src", "/captcha" + '?' + timestamp);
|
||||
}
|
||||
|
||||
$('#modal-help-message').html('上传中...').show();
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: data,
|
||||
success: function(data) {
|
||||
if (data.status === 'success') {
|
||||
image_upload_modal.hide();
|
||||
location.reload();
|
||||
} else {
|
||||
if (data.message === 'bad_captcha') {
|
||||
refreshCaptcha();
|
||||
$('#modal-help-message').html('验证码错误。').show();
|
||||
} else if (data.message === 'expired') {
|
||||
$('#modal-help-message').html('页面过期,请刷新重试。').show();
|
||||
} else if (data.message === 'storage_limit_exceeded') {
|
||||
$('#modal-help-message').html('存储超限,请联系管理员提升限制。').show();
|
||||
} else if (data.message === 'not_a_image') {
|
||||
$('#modal-help-message').html('文件格式不受支持。').show();
|
||||
} else if (data.message === 'too_large') {
|
||||
$('#modal-help-message').html('图片大小不能超过 5 MB。').show();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#modal-help-message').html('上传失败,请刷新页面重试。').addClass('text-danger').show();
|
||||
}
|
||||
$("#captcha").click(function(e) {
|
||||
refreshCaptcha();
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
$('#image-upload-form-drop').click(function() {
|
||||
$('#image_upload_file').click();
|
||||
});
|
||||
$('#image-upload-form-drop').on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}).on('dragover dragenter', function() {
|
||||
$('#select-image-text').html('松开以上传');
|
||||
}).on('dragleave dragend drop', function() {
|
||||
$('#select-image-text').html('点击此处选择图片');
|
||||
}).on('drop', function(e) {
|
||||
$('#image_upload_file').prop('files', e.originalEvent.dataTransfer.files);
|
||||
$('#image_upload_file').trigger('change');
|
||||
});
|
||||
$(document).on('paste', function(e) {
|
||||
if (e.originalEvent.clipboardData) {
|
||||
$('#image_upload_file').prop('files', e.originalEvent.clipboardData.files);
|
||||
}
|
||||
$('#image-upload-form').submit(function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
$('#image_upload_file').trigger('change');
|
||||
});
|
||||
$('#image-upload-modal').on('hide.bs.modal', function() {
|
||||
$('#image-upload-form').trigger('reset');
|
||||
});
|
||||
$('#image_upload_file').change(function() {
|
||||
var items = $(this).prop('files');
|
||||
var file = null;
|
||||
var data = new FormData();
|
||||
data.append('_token', "<?= crsf_token() ?>");
|
||||
data.append('image_upload_file_submit', 'submit');
|
||||
data.append('image_upload_file', $('#image_upload_file').prop('files')[0]);
|
||||
data.append('watermark', $('input[name=watermark]:checked', this).data('value'));
|
||||
data.append('captcha', $('#input-captcha').val());
|
||||
|
||||
if (items && items.length) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if (items[i].type.indexOf('image') !== -1) {
|
||||
file = items[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($('#image_upload_file').prop('files')[0].size > 5242880) {
|
||||
$('#modal-help-message').html('图片大小不能超过 5 MB。').show();
|
||||
|
||||
if (file) {
|
||||
refreshCaptcha();
|
||||
var watermark_type = $('input[name=watermark]:checked', '#image-upload-form').data('value');
|
||||
var html = '';
|
||||
|
||||
html += '<p><img src="'+ URL.createObjectURL(file) +'" height="150" style="object-fit: contain"></p>';
|
||||
html += '<p class="small">大小:<b>'+(file.size / 1024).toFixed(2)+'</b> KB。';
|
||||
|
||||
if (watermark_type === 'no_watermark') {
|
||||
html += '不添加水印。';
|
||||
} else if (watermark_type === 'site_shortname_and_username') {
|
||||
html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>。';
|
||||
} else {
|
||||
html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?>。';
|
||||
return false;
|
||||
}
|
||||
|
||||
html += '</p>';
|
||||
$('#modal-help-message').html('上传中...').show();
|
||||
|
||||
$('#modal-file-info').html(html);
|
||||
$('#modal-help-message').html('').hide();
|
||||
image_upload_modal.show();
|
||||
} else {
|
||||
image_upload_toast.show();
|
||||
}
|
||||
});
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: data,
|
||||
success: function(data) {
|
||||
if (data.status === 'success') {
|
||||
image_upload_modal.hide();
|
||||
location.reload();
|
||||
} else {
|
||||
if (data.message === 'bad_captcha') {
|
||||
refreshCaptcha();
|
||||
$('#modal-help-message').html('验证码错误。').show();
|
||||
} else if (data.message === 'expired') {
|
||||
$('#modal-help-message').html('页面过期,请刷新重试。').show();
|
||||
} else if (data.message === 'storage_limit_exceeded') {
|
||||
$('#modal-help-message').html('存储超限,请联系管理员提升限制。').show();
|
||||
} else if (data.message === 'not_a_image') {
|
||||
$('#modal-help-message').html('文件格式不受支持。').show();
|
||||
} else if (data.message === 'too_large') {
|
||||
$('#modal-help-message').html('图片大小不能超过 5 MB。').show();
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
$('#modal-help-message').html('上传失败,请刷新页面重试。').addClass('text-danger').show();
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
$('#image-upload-form-drop').click(function() {
|
||||
$('#image_upload_file').click();
|
||||
});
|
||||
$('#image-upload-form-drop').on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}).on('dragover dragenter', function() {
|
||||
$('#select-image-text').html('松开以上传');
|
||||
}).on('dragleave dragend drop', function() {
|
||||
$('#select-image-text').html('点击此处选择图片');
|
||||
}).on('drop', function(e) {
|
||||
$('#image_upload_file').prop('files', e.originalEvent.dataTransfer.files);
|
||||
$('#image_upload_file').trigger('change');
|
||||
});
|
||||
$(document).on('paste', function(e) {
|
||||
if (e.originalEvent.clipboardData) {
|
||||
$('#image_upload_file').prop('files', e.originalEvent.clipboardData.files);
|
||||
}
|
||||
|
||||
$('#image_upload_file').trigger('change');
|
||||
});
|
||||
$('#image-upload-modal').on('hide.bs.modal', function() {
|
||||
$('#image-upload-form').trigger('reset');
|
||||
});
|
||||
$('#image_upload_file').change(function() {
|
||||
var items = $(this).prop('files');
|
||||
var file = null;
|
||||
|
||||
if (items && items.length) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
if (items[i].type.indexOf('image') !== -1) {
|
||||
file = items[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file) {
|
||||
refreshCaptcha();
|
||||
var watermark_type = $('input[name=watermark]:checked', '#image-upload-form').data('value');
|
||||
var html = '';
|
||||
|
||||
html += '<p><img src="' + URL.createObjectURL(file) + '" height="150" style="object-fit: contain"></p>';
|
||||
html += '<p class="small">大小:<b>' + (file.size / 1024).toFixed(2) + '</b> KB。';
|
||||
|
||||
if (watermark_type === 'no_watermark') {
|
||||
html += '不添加水印。';
|
||||
} else if (watermark_type === 'site_shortname_and_username') {
|
||||
html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?> @<?= Auth::id() ?>。';
|
||||
} else {
|
||||
html += '使用水印:<?= UOJConfig::$data['profile']['oj-name-short'] ?>。';
|
||||
}
|
||||
|
||||
html += '</p>';
|
||||
|
||||
$('#modal-file-info').html(html);
|
||||
$('#modal-help-message').html('').hide();
|
||||
image_upload_modal.show();
|
||||
} else {
|
||||
image_upload_toast.show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
@ -376,15 +384,15 @@ $pag_config = [
|
||||
'cond' => "uploader = '{$myUser['username']}'",
|
||||
'tail' => 'order by upload_time desc',
|
||||
];
|
||||
$pag = new Paginator($pag_config);
|
||||
?>
|
||||
$pag = new Paginator($pag_config);
|
||||
?>
|
||||
|
||||
<h2 class="h3 mt-4 mb-3">
|
||||
<h2 class="mt-4 mb-3">
|
||||
我的图片
|
||||
</h2>
|
||||
|
||||
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4">
|
||||
<?php foreach ($pag->get() as $idx => $row): ?>
|
||||
<?php foreach ($pag->get() as $idx => $row) : ?>
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<img src="<?= $row['path'] ?>" class="card-img-top" height="200" style="object-fit: contain">
|
||||
@ -392,9 +400,9 @@ $pag_config = [
|
||||
<div class="d-flex flex-wrap justify-content-between">
|
||||
<time><?= $row['upload_time'] ?></time>
|
||||
<span>
|
||||
<?php if ($row['size'] < 1024 * 512): ?>
|
||||
<?php if ($row['size'] < 1024 * 512) : ?>
|
||||
<?= round($row['size'] * 1.0 / 1024, 1) ?> KB
|
||||
<?php else: ?>
|
||||
<?php else : ?>
|
||||
<?= round($row['size'] * 1.0 / 1024 / 1024, 1) ?> MB
|
||||
<?php endif ?>
|
||||
</span>
|
||||
@ -423,7 +431,7 @@ $pag_config = [
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
<?php if ($pag->isEmpty()): ?>
|
||||
<?php if ($pag->isEmpty()) : ?>
|
||||
<div class="mt-4 text-muted">
|
||||
<?= UOJLocale::get('none') ?>
|
||||
</div>
|
||||
@ -445,23 +453,25 @@ $pag_config = [
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||
});
|
||||
$(document).ready(function() {
|
||||
[...document.querySelectorAll('[data-bs-toggle="tooltip"]')].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||
});
|
||||
|
||||
var copy_url_toast = new bootstrap.Toast('#copy-url-toast', { delay: 2000 });
|
||||
var copy_url_toast = new bootstrap.Toast('#copy-url-toast', {
|
||||
delay: 2000
|
||||
});
|
||||
|
||||
$('.image-copy-url-button').click(function() {
|
||||
var url = new URL($(this).data('image-path'), location.origin);
|
||||
navigator.clipboard.writeText(url);
|
||||
copy_url_toast.show();
|
||||
});
|
||||
$('.image-copy-url-button').click(function() {
|
||||
var url = new URL($(this).data('image-path'), location.origin);
|
||||
navigator.clipboard.writeText(url);
|
||||
copy_url_toast.show();
|
||||
});
|
||||
|
||||
$('.image-copy-md-button').click(function() {
|
||||
var url = new URL($(this).data('image-path'), location.origin);
|
||||
navigator.clipboard.writeText('');
|
||||
copy_url_toast.show();
|
||||
});
|
||||
$('.image-copy-md-button').click(function() {
|
||||
var url = new URL($(this).data('image-path'), location.origin);
|
||||
navigator.clipboard.writeText('');
|
||||
copy_url_toast.show();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,10 +1,21 @@
|
||||
<?php requireLib('bootstrap5'); ?>
|
||||
<?php
|
||||
$blogs = DB::selectAll("select blogs.id, title, poster, post_time from important_blogs, blogs where is_hidden = 0 and important_blogs.blog_id = blogs.id order by level desc, important_blogs.blog_id desc limit 5");
|
||||
$countdowns = DB::selectAll("select * from countdowns order by end_time asc");
|
||||
$friend_links = DB::selectAll("select * from friend_links order by level desc, id asc");
|
||||
|
||||
requireLib('bootstrap5');
|
||||
?>
|
||||
$blogs = DB::selectAll([
|
||||
"select blogs.id, title, poster, post_time from important_blogs inner join blogs on important_blogs.blog_id = blogs.id",
|
||||
"where", [
|
||||
"is_hidden" => 0,
|
||||
], "order by level desc, important_blogs.blog_id desc",
|
||||
DB::limit(5)
|
||||
]);
|
||||
$countdowns = DB::selectAll([
|
||||
"select title, end_time from countdowns",
|
||||
"order by end_time asc",
|
||||
]);
|
||||
$friend_links = DB::selectAll([
|
||||
"select title, url from friend_links",
|
||||
"order by level desc, id asc",
|
||||
]);
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJConfig::$data['profile']['oj-name-short']) ?>
|
||||
<div class="row">
|
||||
<div class="col-lg-9">
|
||||
@ -21,27 +32,23 @@
|
||||
<th style="width:20%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tbody>
|
||||
<?php $now_cnt = 0; ?>
|
||||
<?php foreach ($blogs as $blog): ?>
|
||||
<?php foreach ($blogs as $blog_info) : ?>
|
||||
<?php
|
||||
$now_cnt++;
|
||||
$new_tag = '';
|
||||
if ((time() - strtotime($blog['post_time'])) / 3600 / 24 <= 7) {
|
||||
$new_tag = '<sup style="color:red"> new</sup>';
|
||||
}
|
||||
$blog = new UOJBlog($blog_info);
|
||||
$now_cnt++;
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/blogs/<?= $blog['id'] ?>" class="text-decoration-none"><?= $blog['title'] ?></a>
|
||||
<?= $new_tag ?>
|
||||
</td>
|
||||
<td>by <?= getUserLink($blog['poster']) ?></td>
|
||||
<td><small><?= $blog['post_time'] ?></small></td>
|
||||
<td><?= $blog->getLink(['show_new_tag' => true]) ?></td>
|
||||
<td>by <?= getUserLink($blog->info['poster']) ?></td>
|
||||
<td><small><?= $blog->info['post_time'] ?></small></td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
<?php for ($i = $now_cnt + 1; $i <= 5; $i++): ?>
|
||||
<tr><td colspan="233"> </td></tr>
|
||||
<?php for ($i = $now_cnt + 1; $i <= 5; $i++) : ?>
|
||||
<tr>
|
||||
<td colspan="233"> </td>
|
||||
</tr>
|
||||
<?php endfor ?>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -52,27 +59,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (!UOJConfig::$data['switch']['force-login'] || Auth::check()): ?>
|
||||
<?php if (!UOJConfig::$data['switch']['force-login'] || isNormalUser($myUser)): ?>
|
||||
|
||||
<?php if (Auth::check()) : ?>
|
||||
<div class="mt-4 card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title"><?= UOJLocale::get('top solver') ?></h4>
|
||||
<?php echoRanklist([
|
||||
'echo_full' => true,
|
||||
'top10' => true,
|
||||
'by_accepted' => true,
|
||||
'table_classes' => ['table', 'text-center'],
|
||||
]) ?>
|
||||
<div class="text-center">
|
||||
<h4 class="card-title mb-2"><?= UOJLocale::get('top solver') ?></h4>
|
||||
<?php UOJRanklist::printHTML(['top10' => true]) ?>
|
||||
<div class="text-center mt-2">
|
||||
<a href="/solverlist" class="text-decoration-none">
|
||||
<?= UOJLocale::get('view all') ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php else: ?>
|
||||
<?php else : ?>
|
||||
<div class="mt-4 card card-default">
|
||||
<div class="card-body text-center">
|
||||
请 <a role="button" class="btn btn-outline-primary" href="<?= HTML::url('/login') ?>">登录</a> 以查看更多内容。
|
||||
@ -90,22 +89,22 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-unstyled mb-0">
|
||||
<?php foreach ($countdowns as $countdown): ?>
|
||||
<?php foreach ($countdowns as $countdown) : ?>
|
||||
<?php
|
||||
$enddate = strtotime($countdown['end_time']);
|
||||
$enddate = strtotime($countdown['end_time']);
|
||||
$nowdate = time();
|
||||
$diff = floor(($enddate - $nowdate) / (24 * 60 * 60));
|
||||
$diff = ceil(($enddate - $nowdate) / (24 * 60 * 60));
|
||||
?>
|
||||
<li>
|
||||
<?php if ($diff > 0): ?>
|
||||
<?php if ($diff > 0) : ?>
|
||||
<?= UOJLocale::get('x days until countdown title', $countdown['title'], $diff) ?>
|
||||
<?php else: ?>
|
||||
<?php else : ?>
|
||||
<?= UOJLocale::get("countdown title has begun", $countdown['title']) ?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php if (count($countdowns) == 0): ?>
|
||||
<?php if (count($countdowns) == 0) : ?>
|
||||
<div class="text-center">
|
||||
<?= UOJLocale::get('none') ?>
|
||||
</div>
|
||||
@ -113,7 +112,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (Auth::check()): ?>
|
||||
<?php if (Auth::check()) : ?>
|
||||
<?php uojIncludeView('sidebar', ['assignments_hidden' => '', 'groups_hidden' => '']) ?>
|
||||
<?php endif ?>
|
||||
|
||||
@ -123,15 +122,15 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="ps-3 mb-0">
|
||||
<?php foreach ($friend_links as $friend_link): ?>
|
||||
<?php foreach ($friend_links as $friend_link) : ?>
|
||||
<li>
|
||||
<a class="text-decoration-none" href="<?= $friend_link['url'] ?>" target="_blank">
|
||||
<a class="text-decoration-none" href="<?= $friend_link['url'] ?>" target="_blank">
|
||||
<?= $friend_link['title'] ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php if (count($friend_links) == 0): ?>
|
||||
<?php if (count($friend_links) == 0) : ?>
|
||||
<div class="text-center">
|
||||
<?= UOJLocale::get('none') ?>
|
||||
</div>
|
||||
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
requirePHPLib('judger');
|
||||
|
||||
if (!authenticateJudger()) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
switch ($_GET['type']) {
|
||||
case 'submission':
|
||||
$file_name = UOJContext::storagePath()."/submission/{$_GET['id']}/{$_GET['rand_str_id']}";
|
||||
$download_name = "submission.zip";
|
||||
break;
|
||||
case 'tmp':
|
||||
$file_name = UOJContext::storagePath()."/tmp/{$_GET['rand_str_id']}";
|
||||
$download_name = "tmp";
|
||||
break;
|
||||
case 'problem':
|
||||
$id = $_GET['id'];
|
||||
if (!validateUInt($id) || !($problem = queryProblemBrief($id))) {
|
||||
become404Page();
|
||||
}
|
||||
$file_name = "/var/uoj_data/$id.zip";
|
||||
$download_name = "$id.zip";
|
||||
break;
|
||||
case 'judger':
|
||||
$file_name = UOJContext::storagePath()."/judge_client.zip";
|
||||
$download_name = "judge_client.zip";
|
||||
break;
|
||||
default:
|
||||
become404Page();
|
||||
}
|
||||
|
||||
$finfo = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfo, $file_name);
|
||||
if ($mimetype === false) {
|
||||
become404Page();
|
||||
}
|
||||
finfo_close($finfo);
|
||||
|
||||
header("X-Sendfile: $file_name");
|
||||
header("Content-type: $mimetype");
|
||||
header("Content-Disposition: attachment; filename=$download_name");
|
||||
?>
|
@ -1,212 +1,400 @@
|
||||
<?php
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (!authenticateJudger()) {
|
||||
become404Page();
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (!authenticateJudger()) {
|
||||
UOJResponse::page404();
|
||||
}
|
||||
|
||||
function submissionJudged() {
|
||||
UOJSubmission::onJudged(UOJRequest::post('id'), UOJRequest::post('result'), UOJRequest::post('judge_time'));
|
||||
}
|
||||
|
||||
function customTestSubmissionJudged() {
|
||||
$submission = DB::selectFirst([
|
||||
"select submitter, status, content, result, problem_id from custom_test_submissions",
|
||||
"where", ['id' => $_POST['id']]
|
||||
]);
|
||||
if ($submission == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
function submissionJudged() {
|
||||
$submission = DB::selectFirst("select submitter, status, content, result, problem_id from submissions where id = {$_POST['id']}");
|
||||
if ($submission == null) {
|
||||
if ($submission['status'] != 'Judging') {
|
||||
return;
|
||||
}
|
||||
$result = json_decode($_POST['result'], true);
|
||||
$result['details'] = uojTextEncode($result['details']);
|
||||
DB::update([
|
||||
"update custom_test_submissions",
|
||||
"set", [
|
||||
'status' => $result['status'],
|
||||
'status_details' => '',
|
||||
'result' => json_encode($result, JSON_UNESCAPED_UNICODE)
|
||||
], "where", ['id' => $_POST['id']]
|
||||
]);
|
||||
}
|
||||
|
||||
function hackJudged() {
|
||||
$result = json_decode($_POST['result'], true);
|
||||
|
||||
UOJHack::init($_POST['id']);
|
||||
UOJHack::cur()->setProblem();
|
||||
UOJHack::cur()->setSubmission();
|
||||
|
||||
if ($result['score']) {
|
||||
$status = 'Judged, Waiting';
|
||||
} else {
|
||||
$status = 'Judged';
|
||||
}
|
||||
|
||||
$ok = DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
'success' => $result['score'],
|
||||
'status' => $status,
|
||||
'details' => uojTextEncode($result['details'])
|
||||
], "where", ['id' => $_POST['id']]
|
||||
]);
|
||||
|
||||
if (!$result['score']) {
|
||||
return;
|
||||
}
|
||||
if (!$ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(validateUploadedFile('hack_input') && validateUploadedFile('std_output'))) {
|
||||
UOJLog::error("hack successfully but received no data. id: {$_POST['id']}");
|
||||
return;
|
||||
}
|
||||
|
||||
$input = UOJContext::storagePath() . UOJHack::info('input');
|
||||
$up_in = $_FILES["hack_input"]['tmp_name'];
|
||||
$up_out = $_FILES["std_output"]['tmp_name'];
|
||||
|
||||
if (!UOJHack::cur()->problem->needToReviewHack()) {
|
||||
$err = dataAddHackPoint(UOJHack::cur()->problem->info, $up_in, $up_out);
|
||||
if ($err === '') {
|
||||
unlink($input);
|
||||
DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
'status' => 'Judged'
|
||||
], "where", ['id' => $_POST['id']]
|
||||
]);
|
||||
return;
|
||||
}
|
||||
if ($submission['status'] != 'Judging' && $submission['status'] != 'Judged, Judging') {
|
||||
return;
|
||||
}
|
||||
$content = json_decode($submission['content'], true);
|
||||
|
||||
if (isset($content['first_test_config'])) {
|
||||
$result = json_decode($submission['result'], true);
|
||||
$result['final_result'] = json_decode($_POST['result'], true);
|
||||
$result['final_result']['details'] = uojTextEncode($result['final_result']['details']);
|
||||
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$content['final_test_config'] = $content['config'];
|
||||
$content['config'] = $content['first_test_config'];
|
||||
unset($content['first_test_config']);
|
||||
$esc_content = DB::escape(json_encode($content));
|
||||
|
||||
DB::update("update submissions set status = 'Judged', result = '$esc_result', content = '$esc_content' where id = {$_POST['id']}");
|
||||
} else {
|
||||
$result = json_decode($_POST['result'], true);
|
||||
$result['details'] = uojTextEncode($result['details']);
|
||||
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
|
||||
if (isset($result["error"])) {
|
||||
DB::update("update submissions set status = '{$result['status']}', result_error = '{$result['error']}', result = '$esc_result', score = null, used_time = null, used_memory = null where id = {$_POST['id']}");
|
||||
UOJLog::error("hack successfully but failed to add an extra test: {$err}");
|
||||
}
|
||||
}
|
||||
move_uploaded_file($up_in, "{$input}_in");
|
||||
move_uploaded_file($up_out, "{$input}_out");
|
||||
DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
'status' => 'Judged, WaitingM'
|
||||
], "where", ['id' => $_POST['id']]
|
||||
]);
|
||||
}
|
||||
|
||||
if (isset($_POST['submit'])) {
|
||||
if (!validateUInt($_POST['id'])) {
|
||||
die("Wow! hacker! T_T....");
|
||||
}
|
||||
if (isset($_POST['is_hack'])) {
|
||||
hackJudged();
|
||||
} elseif (isset($_POST['is_custom_test'])) {
|
||||
customTestSubmissionJudged();
|
||||
} else {
|
||||
submissionJudged();
|
||||
}
|
||||
}
|
||||
if (isset($_POST['update-status'])) {
|
||||
if (!validateUInt($_POST['id'])) {
|
||||
die("Wow! hacker! T_T....");
|
||||
}
|
||||
|
||||
$status_details = $_POST['status'];
|
||||
if (isset($_POST['is_custom_test'])) {
|
||||
DB::update([
|
||||
"update custom_test_submissions",
|
||||
"set", ["status_details" => $status_details],
|
||||
"where", ["id" => $_POST['id']]
|
||||
]);
|
||||
} else {
|
||||
DB::update([
|
||||
"update submissions",
|
||||
"set", ["status_details" => $status_details],
|
||||
"where", ["id" => $_POST['id']]
|
||||
]);
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
$problem_ban_list = DB::selectAll([
|
||||
"select id from problems",
|
||||
"where", [
|
||||
["assigned_to_judger", "!=", "any"],
|
||||
["assigned_to_judger", "!=", $_POST['judger_name']]
|
||||
]
|
||||
]);
|
||||
foreach ($problem_ban_list as &$val) {
|
||||
$val = $val['id'];
|
||||
}
|
||||
$assignCond = $problem_ban_list ? [["problem_id", "not in", DB::rawtuple($problem_ban_list)]] : [];
|
||||
|
||||
$submission = null;
|
||||
$hack = null;
|
||||
function querySubmissionToJudge($status, $set_q) {
|
||||
global $assignCond;
|
||||
|
||||
for ($times = 0; $times < 10; $times++) {
|
||||
$submission = DB::selectFirst([
|
||||
"select id from submissions",
|
||||
"where", array_merge(["status" => $status], $assignCond),
|
||||
"order by id limit 1"
|
||||
]);
|
||||
if (!$submission) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ok = DB::transaction(function () use (&$submission, $set_q, $status) {
|
||||
DB::update([
|
||||
"update submissions",
|
||||
"set", $set_q,
|
||||
"where", [
|
||||
"id" => $submission['id'],
|
||||
"status" => $status
|
||||
]
|
||||
]);
|
||||
if (DB::affected_rows() == 1) {
|
||||
$submission = DB::selectFirst([
|
||||
"select id, problem_id, content, status, judge_time from submissions",
|
||||
"where", ["id" => $submission['id']]
|
||||
]);
|
||||
return true;
|
||||
} else {
|
||||
DB::update("update submissions set status = '{$result['status']}', result_error = null, result = '$esc_result', score = {$result['score']}, used_time = {$result['time']}, used_memory = {$result['memory']} where id = {$_POST['id']}");
|
||||
}
|
||||
|
||||
if (isset($content['final_test_config'])) {
|
||||
$content['first_test_config'] = $content['config'];
|
||||
$content['config'] = $content['final_test_config'];
|
||||
unset($content['final_test_config']);
|
||||
$esc_content = DB::escape(json_encode($content));
|
||||
|
||||
DB::update("update submissions set status = 'Judged, Waiting', content = '$esc_content' where id = ${_POST['id']}");
|
||||
}
|
||||
}
|
||||
DB::update("update submissions set status_details = '' where id = {$_POST['id']}");
|
||||
updateBestACSubmissions($submission['submitter'], $submission['problem_id']);
|
||||
}
|
||||
|
||||
function customTestSubmissionJudged() {
|
||||
$submission = DB::selectFirst("select submitter, status, content, result, problem_id from custom_test_submissions where id = {$_POST['id']}");
|
||||
if ($submission == null) {
|
||||
return;
|
||||
}
|
||||
if ($submission['status'] != 'Judging') {
|
||||
return;
|
||||
}
|
||||
$content = json_decode($submission['content'], true);
|
||||
$result = json_decode($_POST['result'], true);
|
||||
$result['details'] = uojTextEncode($result['details']);
|
||||
$esc_result = DB::escape(json_encode($result, JSON_UNESCAPED_UNICODE));
|
||||
if (isset($result["error"])) {
|
||||
DB::update("update custom_test_submissions set status = '{$result['status']}', result = '$esc_result' where id = {$_POST['id']}");
|
||||
} else {
|
||||
DB::update("update custom_test_submissions set status = '{$result['status']}', result = '$esc_result' where id = {$_POST['id']}");
|
||||
}
|
||||
DB::update("update custom_test_submissions set status_details = '' where id = {$_POST['id']}");
|
||||
}
|
||||
|
||||
function hackJudged() {
|
||||
$result = json_decode($_POST['result'], true);
|
||||
$esc_details = DB::escape(uojTextEncode($result['details']));
|
||||
$ok = DB::update("update hacks set success = {$result['score']}, details = '$esc_details' where id = {$_POST['id']}");
|
||||
|
||||
if ($ok) {
|
||||
list($hack_input) = DB::fetch(DB::query("select input from hacks where id = {$_POST['id']}"), MYSQLI_NUM);
|
||||
unlink(UOJContext::storagePath().$hack_input);
|
||||
|
||||
if ($result['score']) {
|
||||
list($problem_id) = DB::selectFirst("select problem_id from hacks where id = ${_POST['id']}", MYSQLI_NUM);
|
||||
if (validateUploadedFile('hack_input') && validateUploadedFile('std_output')) {
|
||||
dataAddExtraTest(queryProblemBrief($problem_id), $_FILES["hack_input"]["tmp_name"], $_FILES["std_output"]["tmp_name"]);
|
||||
} else {
|
||||
error_log("hack successfully but received no data. id: ${_POST['id']}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['submit'])) {
|
||||
if (!validateUInt($_POST['id'])) {
|
||||
die("Wow! hacker! T_T....");
|
||||
}
|
||||
if (isset($_POST['is_hack'])) {
|
||||
hackJudged();
|
||||
} elseif (isset($_POST['is_custom_test'])) {
|
||||
customTestSubmissionJudged();
|
||||
} else {
|
||||
submissionJudged();
|
||||
}
|
||||
}
|
||||
if (isset($_POST['update-status'])) {
|
||||
if (!validateUInt($_POST['id'])) {
|
||||
die("Wow! hacker! T_T....");
|
||||
}
|
||||
$esc_status_details = DB::escape($_POST['status']);
|
||||
if (isset($_POST['is_custom_test'])) {
|
||||
DB::update("update custom_test_submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
|
||||
} else {
|
||||
DB::update("update submissions set status_details = '$esc_status_details' where id = {$_POST['id']}");
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
$submission = null;
|
||||
$hack = null;
|
||||
function querySubmissionToJudge($status, $set_q) {
|
||||
global $submission;
|
||||
$submission = DB::selectFirst("select id, problem_id, content from submissions where status = '$status' order by id limit 1");
|
||||
if ($submission) {
|
||||
DB::update("update submissions set $set_q where id = {$submission['id']} and status = '$status'");
|
||||
if (DB::affected_rows() != 1) {
|
||||
$submission = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
function queryCustomTestSubmissionToJudge() {
|
||||
global $submission;
|
||||
$submission = DB::selectFirst("select id, problem_id, content from custom_test_submissions where judge_time is null order by id limit 1");
|
||||
if ($submission) {
|
||||
DB::update("update custom_test_submissions set judge_time = now(), status = 'Judging' where id = {$submission['id']} and judge_time is null");
|
||||
if (DB::affected_rows() != 1) {
|
||||
$submission = null;
|
||||
}
|
||||
}
|
||||
if ($submission) {
|
||||
$submission['is_custom_test'] = '';
|
||||
}
|
||||
}
|
||||
function queryHackToJudge() {
|
||||
global $hack;
|
||||
$hack = DB::selectFirst("select id, submission_id, input, input_type from hacks where judge_time is null order by id limit 1");
|
||||
if ($hack) {
|
||||
DB::update("update hacks set judge_time = now() where id = {$hack['id']} and judge_time is null");
|
||||
if (DB::affected_rows() != 1) {
|
||||
$hack = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
function findSubmissionToJudge() {
|
||||
global $submission, $hack;
|
||||
querySubmissionToJudge('Waiting', "judge_time = now(), status = 'Judging'");
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
queryCustomTestSubmissionToJudge();
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
querySubmissionToJudge('Waiting Rejudge', "judge_time = now(), status = 'Judging'");
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
querySubmissionToJudge('Judged, Waiting', "status = 'Judged, Judging'");
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
queryHackToJudge();
|
||||
if ($hack) {
|
||||
$submission = DB::selectFirst("select id, problem_id, content from submissions where id = {$hack['submission_id']} and score = 100");
|
||||
if (!$submission) {
|
||||
$details = "<error>the score gained by the hacked submission is not 100.\n</error>";
|
||||
$esc_details = DB::escape(uojTextEncode($details));
|
||||
DB::update("update hacks set success = 0, details = '$esc_details' where id = {$hack['id']}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if ($ok) {
|
||||
return $submission;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isset($_POST['fetch_new']) && !$_POST['fetch_new']) {
|
||||
die("Nothing to judge");
|
||||
}
|
||||
function queryMinorSubmissionToJudge($status, $set_q) {
|
||||
global $assignCond;
|
||||
|
||||
for ($times = 0; $times < 10; $times++) {
|
||||
$submission = null;
|
||||
$his = DB::selectFirst([
|
||||
"select id, submission_id from submissions_history",
|
||||
"where", ["status" => $status, "major" => 0], // $assignCond is removed!!! fix this bug in the future!
|
||||
"order by id limit 1"
|
||||
]);
|
||||
if (!$his) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ok = DB::transaction(function () use (&$submission, &$his, $set_q, $status) {
|
||||
$submission = DB::selectFirst([
|
||||
"select id, problem_id, content from submissions",
|
||||
"where", ["id" => $his['submission_id']], DB::for_share()
|
||||
]);
|
||||
if (!$submission) {
|
||||
return false;
|
||||
}
|
||||
DB::update([
|
||||
"update submissions_history",
|
||||
"set", $set_q,
|
||||
"where", [
|
||||
"id" => $his['id'],
|
||||
"status" => $status
|
||||
]
|
||||
]);
|
||||
if (DB::affected_rows() == 1) {
|
||||
$ret = DB::selectFirst([
|
||||
"select status, judge_time from submissions_history",
|
||||
"where", ["id" => $his['id']]
|
||||
]);
|
||||
if ($ret === false) {
|
||||
return false;
|
||||
}
|
||||
$submission += $ret;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if ($ok) {
|
||||
return $submission;
|
||||
}
|
||||
}
|
||||
if (!findSubmissionToJudge()) {
|
||||
die("Nothing to judge");
|
||||
}
|
||||
function queryCustomTestSubmissionToJudge() {
|
||||
global $assignCond;
|
||||
|
||||
while (true) {
|
||||
$submission = DB::selectFirst([
|
||||
"select id, problem_id, content from custom_test_submissions",
|
||||
"where", array_merge(["judge_time" => null], $assignCond),
|
||||
"order by id limit 1"
|
||||
]);
|
||||
if (!$submission) {
|
||||
return null;
|
||||
}
|
||||
$submission['is_custom_test'] = '';
|
||||
|
||||
DB::update([
|
||||
"update custom_test_submissions",
|
||||
"set", [
|
||||
"judge_time" => DB::now(),
|
||||
"status" => 'Judging'
|
||||
], "where", [
|
||||
"id" => $submission['id'],
|
||||
"judge_time" => null
|
||||
]
|
||||
]);
|
||||
if (DB::affected_rows() == 1) {
|
||||
$submission['status'] = 'Judging';
|
||||
return $submission;
|
||||
}
|
||||
}
|
||||
|
||||
$submission['id'] = (int)$submission['id'];
|
||||
$submission['problem_id'] = (int)$submission['problem_id'];
|
||||
$submission['problem_mtime'] = filemtime("/var/uoj_data/{$submission['problem_id']}");
|
||||
$submission['content'] = json_decode($submission['content']);
|
||||
|
||||
}
|
||||
function queryHackToJudge() {
|
||||
global $assignCond;
|
||||
|
||||
while (true) {
|
||||
if (DB::selectFirst([
|
||||
"select 1 from hacks",
|
||||
"where", [
|
||||
["status", "!=", "Waiting"],
|
||||
["status", "!=", "Judged"],
|
||||
], "order by id limit 1"
|
||||
])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$hack = DB::selectFirst([
|
||||
"select id, submission_id, input, input_type from hacks",
|
||||
"where", array_merge(["judge_time" => null], $assignCond),
|
||||
"order by id limit 1"
|
||||
]);
|
||||
if (!$hack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
"judge_time" => DB::now(),
|
||||
"status" => 'Judging'
|
||||
],
|
||||
"where", [
|
||||
"id" => $hack['id'],
|
||||
"judge_time" => null
|
||||
]
|
||||
]);
|
||||
if (DB::affected_rows() == 1) {
|
||||
$hack['status'] = 'Judging';
|
||||
return $hack;
|
||||
}
|
||||
}
|
||||
}
|
||||
function findSubmissionToJudge() {
|
||||
global $submission, $hack;
|
||||
$submission = querySubmissionToJudge('Waiting', [
|
||||
"judge_time" => DB::now(),
|
||||
"judger" => $_POST['judger_name'],
|
||||
"status" => 'Judging'
|
||||
]);
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$submission = queryCustomTestSubmissionToJudge();
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$submission = querySubmissionToJudge('Waiting Rejudge', [
|
||||
"judge_time" => DB::now(),
|
||||
"judger" => $_POST['judger_name'],
|
||||
"status" => 'Judging'
|
||||
]);
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$submission = querySubmissionToJudge('Judged, Waiting', [
|
||||
"status" => 'Judged, Judging'
|
||||
]);
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$submission = queryMinorSubmissionToJudge('Waiting Rejudge', [
|
||||
"judge_time" => DB::now(),
|
||||
"judger" => $_POST['judger_name'],
|
||||
"status" => 'Judging'
|
||||
]);
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$submission = queryMinorSubmissionToJudge('Judged, Waiting', [
|
||||
"status" => 'Judged, Judging'
|
||||
]);
|
||||
if ($submission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$hack = queryHackToJudge();
|
||||
if ($hack) {
|
||||
$submission['is_hack'] = "";
|
||||
$submission['hack']['id'] = (int)$hack['id'];
|
||||
$submission['hack']['input'] = $hack['input'];
|
||||
$submission['hack']['input_type'] = $hack['input_type'];
|
||||
$submission = DB::selectFirst([
|
||||
"select id, problem_id, content from submissions",
|
||||
"where", [
|
||||
"id" => $hack['submission_id'],
|
||||
"score" => 100
|
||||
]
|
||||
]);
|
||||
if (!$submission) {
|
||||
$details = "<error>the score gained by the hacked submission is not 100.</error>";
|
||||
DB::update([
|
||||
"update hacks",
|
||||
"set", [
|
||||
'success' => 0,
|
||||
'status' => 'Judged',
|
||||
'details' => uojTextEncode($details)
|
||||
], "where", ["id" => $hack['id']]
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
echo json_encode($submission);
|
||||
?>
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($_POST['fetch_new']) && !$_POST['fetch_new']) {
|
||||
die("Nothing to judge");
|
||||
}
|
||||
if (!findSubmissionToJudge()) {
|
||||
die("Nothing to judge");
|
||||
}
|
||||
|
||||
$submission['id'] = (int)$submission['id'];
|
||||
$submission['problem_id'] = (int)$submission['problem_id'];
|
||||
$submission['problem_mtime'] = filemtime("/var/uoj_data/{$submission['problem_id']}");
|
||||
$submission['content'] = json_decode($submission['content'], true);
|
||||
if (isset($submission['status']) && $submission['status'] == 'Judged, Judging' && isset($submission['content']['final_test_config'])) {
|
||||
$submission['content']['config'] = $submission['content']['final_test_config'];
|
||||
unset($submission['content']['final_test_config']);
|
||||
}
|
||||
|
||||
if ($hack) {
|
||||
$submission['is_hack'] = "";
|
||||
$submission['hack']['id'] = (int)$hack['id'];
|
||||
$submission['hack']['input'] = $hack['input'];
|
||||
$submission['hack']['input_type'] = $hack['input_type'];
|
||||
}
|
||||
|
||||
echo json_encode($submission);
|
||||
|
@ -1,21 +1,28 @@
|
||||
<?php
|
||||
requirePHPLib('judger');
|
||||
|
||||
if (!authenticateJudger()) {
|
||||
become404Page();
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (!authenticateJudger()) {
|
||||
UOJResponse::page404();
|
||||
}
|
||||
|
||||
$res = DB::selectAll([
|
||||
"select * from judger_info",
|
||||
"where", [
|
||||
["ip", "!=", ""],
|
||||
"enabled" => true
|
||||
]
|
||||
]);
|
||||
foreach ($res as $judger) {
|
||||
$socket = fsockopen($judger['ip'], UOJConfig::$data['judger']['socket']['port']);
|
||||
if ($socket === false) {
|
||||
die("judge client {$judger['ip']} lost.");
|
||||
}
|
||||
|
||||
foreach (DB::selectAll("select * from judger_info where ip != ''") as $judger) {
|
||||
$socket = fsockopen($judger['ip'], UOJConfig::$data['judger']['socket']['port']);
|
||||
if ($socket === false) {
|
||||
die("judge client {$judger['ip']} lost.");
|
||||
}
|
||||
fwrite($socket, json_encode([
|
||||
'password' => UOJConfig::$data['judger']['socket']['password'],
|
||||
'cmd' => 'update'
|
||||
]));
|
||||
fclose($socket);
|
||||
}
|
||||
|
||||
die("ok");
|
||||
?>
|
||||
fwrite($socket, json_encode([
|
||||
'password' => UOJConfig::$data['judger']['socket']['password'],
|
||||
'cmd' => 'update'
|
||||
]));
|
||||
fclose($socket);
|
||||
}
|
||||
|
||||
die("ok");
|
||||
|
@ -1,12 +1,8 @@
|
||||
<?php
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
requireLib('bootstrap5');
|
||||
requireLib('mathjax');
|
||||
requirePHPLib('form');
|
||||
@ -73,7 +69,7 @@ EOD;
|
||||
echo "<td>{$extra_config['difficulty']}</td>";
|
||||
}
|
||||
}
|
||||
echo '<td class="text-start">', getClickZanBlock('P', $problem['id'], $problem['zan'], null, false), '</td>';
|
||||
echo '<td class="text-start">', ClickZans::getBlock('P', $problem['id'], $problem['zan'], null, false), '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
}
|
||||
@ -121,7 +117,7 @@ EOD;
|
||||
<!-- title container -->
|
||||
<div class="d-flex justify-content-between">
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?= $list['title'] ?>
|
||||
<span class="fs-5">(ID: #<?= $list['id'] ?>)</span>
|
||||
<?php if ($list['is_hidden']): ?>
|
||||
@ -146,7 +142,7 @@ EOD;
|
||||
<!-- description -->
|
||||
<div class="card my-2">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">题单简介</h2>
|
||||
<h2 class="h4 mb-3">题单简介</h2>
|
||||
<?php $description = HTML::purifier()->purify(HTML::parsedown()->text($list['description'])) ?>
|
||||
<?php if ($description): ?>
|
||||
<?= $description ?>
|
||||
@ -224,7 +220,7 @@ $('#input-show_difficulty').click(function() {
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($pag->get() as $idx => $row): ?>
|
||||
<?php echoProblem($row) ?>
|
||||
<?php echoProblem($row) ?>
|
||||
<?php endforeach ?>
|
||||
<?php if ($pag->isEmpty()): ?>
|
||||
<tr>
|
||||
|
@ -44,7 +44,7 @@
|
||||
if ($cur_tab == 'profile') {
|
||||
$list_tags = queryProblemListTags($list_id);
|
||||
|
||||
$update_profile_form = new UOJForm('update_profile');
|
||||
$update_profile_form = new UOJBs4Form('update_profile');
|
||||
$update_profile_form->addVInput('name', 'text', '标题', $list['title'],
|
||||
function($title, &$vdata) {
|
||||
if ($title == '') {
|
||||
@ -151,7 +151,7 @@ function(res) {
|
||||
$(window).scrollTop(0);
|
||||
}
|
||||
EOD);
|
||||
$update_profile_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$update_profile_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$update_profile_form->submit_button_config['text'] = '更新';
|
||||
$update_profile_form->runAtServer();
|
||||
} elseif ($cur_tab == 'problems') {
|
||||
@ -179,7 +179,7 @@ EOD);
|
||||
|
||||
$n_problems = DB::selectCount("SELECT count(*) FROM `lists_problems` WHERE `list_id` = {$list['id']}");
|
||||
|
||||
$add_new_problem_form = new UOJForm('add_new_problem');
|
||||
$add_new_problem_form = new UOJBs4Form('add_new_problem');
|
||||
$add_new_problem_form->addVInput('problem_id', 'text', '题目 ID', '',
|
||||
function ($problem_id, &$vdata) use ($list) {
|
||||
if (!validateUInt($problem_id)) {
|
||||
@ -200,7 +200,7 @@ EOD);
|
||||
},
|
||||
null
|
||||
);
|
||||
$add_new_problem_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_new_problem_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$add_new_problem_form->submit_button_config['text'] = '添加';
|
||||
$add_new_problem_form->handle = function($vdata) use ($list) {
|
||||
DB::insert("INSERT INTO `lists_problems` (`list_id`, `problem_id`) values ({$list['id']}, {$vdata['problem_id']})");
|
||||
@ -250,7 +250,7 @@ EOD);
|
||||
dieWithAlert('移除成功!');
|
||||
}
|
||||
|
||||
$add_new_assignment_form = new UOJForm('add_new_assignment');
|
||||
$add_new_assignment_form = new UOJBs4Form('add_new_assignment');
|
||||
$add_new_assignment_form->addVInput('new_assignment_group_id', 'text', '小组 ID', '',
|
||||
function ($group_id, &$vdata) use ($list) {
|
||||
if (!validateUInt($group_id)) {
|
||||
@ -300,7 +300,7 @@ EOD);
|
||||
'message' => '题单 #' . $list['id'] . ' 已经被添加到小组 #' . $vdata['group_id'] . ' 的作业列表中,结束时间为 ' . $vdata['end_time']->format('Y-m-d H:i:s') . '。'
|
||||
]);
|
||||
};
|
||||
$add_new_assignment_form->submit_button_config['margin_class'] = 'mt-3';
|
||||
$add_new_assignment_form->submit_button_config['class_str'] = 'btn btn-secondary mt-3';
|
||||
$add_new_assignment_form->submit_button_config['text'] = '添加';
|
||||
$add_new_assignment_form->setAjaxSubmit(<<<EOD
|
||||
function(res) {
|
||||
@ -330,7 +330,7 @@ EOD);
|
||||
|
||||
<?php echoUOJPageHeader('管理 - ' . $list['title']) ?>
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?= $list['title'] ?>
|
||||
<small class="fs-5">(ID: #<?= $list['id'] ?>)</small>
|
||||
管理
|
||||
|
@ -1,19 +1,15 @@
|
||||
<?php
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
if (!Auth::check()) {
|
||||
redirectToLogin();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requirePHPLib('data');
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$new_list_form = new UOJForm('new_list');
|
||||
$new_list_form = new UOJBs4Form('new_list');
|
||||
$new_list_form->handle = function() {
|
||||
DB::query("insert into lists (title, is_hidden) values ('未命名题单', 1)");
|
||||
};
|
||||
@ -66,7 +62,7 @@
|
||||
<!-- title container -->
|
||||
<div class="d-flex justify-content-between">
|
||||
|
||||
<h1 class="h2">
|
||||
<h1>
|
||||
<?= UOJLocale::get('problems lists') ?>
|
||||
</h1>
|
||||
|
||||
@ -147,7 +143,6 @@ EOD;
|
||||
'page_len' => 40,
|
||||
'table_classes' => ['table', 'table-bordered', 'table-hover', 'table-striped'],
|
||||
'head_pagination' => true,
|
||||
'pagination_table' => 'lists',
|
||||
'div_classes' => ['card', 'my-3'],
|
||||
'table_classes' => ['table', 'uoj-table', 'mb-0'],
|
||||
]
|
||||
|
@ -1,58 +1,57 @@
|
||||
<?php
|
||||
use Gregwar\Captcha\PhraseBuilder;
|
||||
use Gregwar\Captcha\CaptchaBuilder;
|
||||
|
||||
requireLib('md5');
|
||||
requireLib('bootstrap5');
|
||||
|
||||
if (Auth::check()) {
|
||||
redirectTo('/');
|
||||
use Gregwar\Captcha\PhraseBuilder;
|
||||
|
||||
requireLib('md5');
|
||||
requireLib('bootstrap5');
|
||||
|
||||
Auth::check() && redirectTo('/');
|
||||
|
||||
function handleLoginPost() {
|
||||
if (!crsf_check()) {
|
||||
return 'expired';
|
||||
}
|
||||
if (!isset($_POST['username'])) {
|
||||
return "failed";
|
||||
}
|
||||
if (!isset($_POST['password'])) {
|
||||
return "failed";
|
||||
}
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
$captcha = $_POST['captcha'];
|
||||
|
||||
if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $captcha)) {
|
||||
return "bad_captcha";
|
||||
}
|
||||
|
||||
function handleLoginPost() {
|
||||
if (!crsf_check()) {
|
||||
return 'expired';
|
||||
}
|
||||
if (!isset($_POST['username'])) {
|
||||
return "failed";
|
||||
}
|
||||
if (!isset($_POST['password'])) {
|
||||
return "failed";
|
||||
}
|
||||
$username = $_POST['username'];
|
||||
$password = $_POST['password'];
|
||||
$captcha = $_POST['captcha'];
|
||||
if (!validateUsername($username)) {
|
||||
return "failed";
|
||||
}
|
||||
if (!validatePassword($password)) {
|
||||
return "failed";
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['phrase']) || !PhraseBuilder::comparePhrases($_SESSION['phrase'], $captcha)) {
|
||||
return "bad_captcha";
|
||||
}
|
||||
|
||||
if (!validateUsername($username)) {
|
||||
return "failed";
|
||||
}
|
||||
if (!validatePassword($password)) {
|
||||
return "failed";
|
||||
}
|
||||
|
||||
$user = queryUser($username);
|
||||
if (!$user || !checkPassword($user, $password)) {
|
||||
return "failed";
|
||||
}
|
||||
|
||||
if ($user['usergroup'] == 'B') {
|
||||
return "banned";
|
||||
}
|
||||
|
||||
Auth::login($user['username']);
|
||||
return "ok";
|
||||
$user = UOJUser::query($username);
|
||||
if (!$user || !checkPassword($user, $password)) {
|
||||
return "failed";
|
||||
}
|
||||
|
||||
if (isset($_POST['login'])) {
|
||||
echo handleLoginPost();
|
||||
unset($_SESSION['phrase']);
|
||||
die();
|
||||
|
||||
$account_status = UOJUser::getAccountStatus($user);
|
||||
if ($account_status != 'ok') {
|
||||
return 'account:' . $account_status;
|
||||
}
|
||||
?>
|
||||
|
||||
Auth::login($user['username']);
|
||||
return "ok";
|
||||
}
|
||||
|
||||
if (isset($_POST['login'])) {
|
||||
echo handleLoginPost();
|
||||
unset($_SESSION['phrase']);
|
||||
die();
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader(UOJLocale::get('login')) ?>
|
||||
|
||||
<style>
|
||||
@ -107,79 +106,78 @@
|
||||
</main>
|
||||
|
||||
<script type="text/javascript">
|
||||
function validateLoginPost() {
|
||||
var ok = true;
|
||||
ok &= getFormErrorAndShowHelp('username', validateUsername);
|
||||
ok &= getFormErrorAndShowHelp('password', validatePassword);
|
||||
return ok;
|
||||
}
|
||||
|
||||
function refreshCaptcha() {
|
||||
var timestamp = new Date().getTime();
|
||||
$("#captcha").attr("src", "/captcha" + '?' + timestamp);
|
||||
}
|
||||
|
||||
function submitLoginPost() {
|
||||
if (!validateLoginPost()) {
|
||||
return false;
|
||||
function validateLoginPost() {
|
||||
var ok = true;
|
||||
ok &= getFormErrorAndShowHelp('username', validateUsername);
|
||||
ok &= getFormErrorAndShowHelp('password', validatePassword);
|
||||
return ok;
|
||||
}
|
||||
|
||||
$.post('/login', {
|
||||
_token : "<?= crsf_token() ?>",
|
||||
login : '',
|
||||
username : $('#input-username').val(),
|
||||
password : md5($('#input-password').val(), "<?= getPasswordClientSalt() ?>"),
|
||||
captcha: $('#input-captcha').val(),
|
||||
}, function(msg) {
|
||||
$('#div-username, #div-password, #div-captcha').removeClass('has-validation');
|
||||
$('#input-username, #input-password, #input-captcha').removeClass('is-invalid');
|
||||
$('#help-username, #help-passwor, #help-captcha').html('');
|
||||
|
||||
if (msg == 'ok') {
|
||||
var prevUrl = document.referrer;
|
||||
if (prevUrl == '' || /.*\/login.*/.test(prevUrl) || /.*\/logout.*/.test(prevUrl) || /.*\/register.*/.test(prevUrl) || /.*\/reset-password.*/.test(prevUrl)) {
|
||||
prevUrl = '/';
|
||||
};
|
||||
window.location.href = prevUrl;
|
||||
} else if (msg == 'bad_captcha') {
|
||||
$('#div-captcha').addClass('has-validation');
|
||||
$('#div-captcha > .form-floating, #input-captcha').addClass('is-invalid');
|
||||
$('#help-captcha').html('验证码错误。');
|
||||
refreshCaptcha();
|
||||
} else if (msg == 'banned') {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#help-username').html('该用户已被封停,请联系管理员。');
|
||||
refreshCaptcha();
|
||||
} else if (msg == 'expired') {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#help-username').html('页面会话已过期。');
|
||||
refreshCaptcha();
|
||||
} else {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#div-password').addClass('has-validation');
|
||||
$('#div-password > .form-floating, #input-password').addClass('is-invalid');
|
||||
$('#help-password').html('用户名或密码错误。<a href="/forgot-password">忘记密码?</a>');
|
||||
refreshCaptcha();
|
||||
function refreshCaptcha() {
|
||||
var timestamp = new Date().getTime();
|
||||
$("#captcha").attr("src", "/captcha" + '?' + timestamp);
|
||||
}
|
||||
|
||||
function submitLoginPost() {
|
||||
if (!validateLoginPost()) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
refreshCaptcha();
|
||||
$.post('/login', {
|
||||
_token: "<?= crsf_token() ?>",
|
||||
login: '',
|
||||
username: $('#input-username').val(),
|
||||
password: md5($('#input-password').val(), "<?= getPasswordClientSalt() ?>"),
|
||||
captcha: $('#input-captcha').val(),
|
||||
}, function(msg) {
|
||||
$('#div-username, #div-password, #div-captcha').removeClass('has-validation');
|
||||
$('#input-username, #input-password, #input-captcha').removeClass('is-invalid');
|
||||
$('#help-username, #help-passwor, #help-captcha').html('');
|
||||
|
||||
$('#form-login').submit(function(e) {
|
||||
e.preventDefault();
|
||||
submitLoginPost();
|
||||
});
|
||||
$("#captcha").click(function(e) {
|
||||
if (msg == 'ok') {
|
||||
var prevUrl = document.referrer;
|
||||
if (prevUrl == '' || /.*\/login.*/.test(prevUrl) || /.*\/logout.*/.test(prevUrl) || /.*\/register.*/.test(prevUrl) || /.*\/reset-password.*/.test(prevUrl)) {
|
||||
prevUrl = '/';
|
||||
};
|
||||
window.location.href = prevUrl;
|
||||
} else if (msg == 'bad_captcha') {
|
||||
$('#div-captcha').addClass('has-validation');
|
||||
$('#div-captcha > .form-floating, #input-captcha').addClass('is-invalid');
|
||||
$('#help-captcha').html('验证码错误。');
|
||||
refreshCaptcha();
|
||||
} else if (msg == 'banned') {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#help-username').html('该用户已被封停,请联系管理员。');
|
||||
refreshCaptcha();
|
||||
} else if (msg == 'expired') {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#help-username').html('页面会话已过期。');
|
||||
refreshCaptcha();
|
||||
} else {
|
||||
$('#div-username').addClass('has-validation');
|
||||
$('#div-username > .form-floating, #input-username').addClass('is-invalid');
|
||||
$('#div-password').addClass('has-validation');
|
||||
$('#div-password > .form-floating, #input-password').addClass('is-invalid');
|
||||
$('#help-password').html('用户名或密码错误。<a href="/forgot-password">忘记密码?</a>');
|
||||
refreshCaptcha();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
refreshCaptcha();
|
||||
});
|
||||
});
|
||||
|
||||
$('#form-login').submit(function(e) {
|
||||
e.preventDefault();
|
||||
submitLoginPost();
|
||||
});
|
||||
$("#captcha").click(function(e) {
|
||||
refreshCaptcha();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
@ -1,12 +1,12 @@
|
||||
<?php
|
||||
crsf_defend();
|
||||
Auth::logout();
|
||||
?>
|
||||
crsf_defend();
|
||||
Auth::logout();
|
||||
?>
|
||||
|
||||
<script type="text/javascript">
|
||||
var prevUrl = document.referrer;
|
||||
if (!prevUrl) {
|
||||
prevUrl = '/';
|
||||
};
|
||||
window.location.href = prevUrl;
|
||||
var prevUrl = document.referrer;
|
||||
if (!prevUrl) {
|
||||
prevUrl = '/';
|
||||
};
|
||||
window.location.href = prevUrl;
|
||||
</script>
|
||||
|
@ -1,482 +1,431 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
requireLib('mathjax');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
requireLib('bootstrap5');
|
||||
requireLib('hljs');
|
||||
requireLib('mathjax');
|
||||
requirePHPLib('form');
|
||||
requirePHPLib('judger');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
$problem = UOJProblem::cur()->info;
|
||||
$problem_content = UOJProblem::cur()->queryContent();
|
||||
|
||||
$problem_content = queryProblemContent($problem['id']);
|
||||
|
||||
$contest = validateUInt($_GET['contest_id']) ? queryContest($_GET['contest_id']) : null;
|
||||
if ($contest != null) {
|
||||
genMoreContestInfo($contest);
|
||||
$problem_rank = queryContestProblemRank($contest, $problem);
|
||||
if ($problem_rank == null) {
|
||||
become404Page();
|
||||
} else {
|
||||
$problem_letter = chr(ord('A') + $problem_rank - 1);
|
||||
if (UOJRequest::get('contest_id')) {
|
||||
UOJContest::init(UOJRequest::get('contest_id')) || UOJResponse::page404();
|
||||
UOJProblem::upgradeToContestProblem() || UOJResponse::page404();
|
||||
}
|
||||
UOJProblem::cur()->userCanView(Auth::user(), ['ensure' => true]);
|
||||
|
||||
$pre_submit_check_ret = UOJProblem::cur()->preSubmitCheck();
|
||||
|
||||
$is_participating = false;
|
||||
$no_more_submission = false;
|
||||
$submission_warning = null;
|
||||
if (UOJContest::cur()) {
|
||||
if (UOJContest::cur()->userCanParticipateNow(Auth::user())) {
|
||||
if (!UOJContest::cur()->userHasMarkedParticipated(Auth::user())) {
|
||||
redirectTo(UOJContest::cur()->getUri("/confirm"));
|
||||
}
|
||||
}
|
||||
|
||||
$is_in_contest = false;
|
||||
$ban_in_contest = false;
|
||||
if ($contest != null) {
|
||||
if (!hasContestPermission($myUser, $contest)) {
|
||||
if ($contest['cur_progress'] == CONTEST_NOT_STARTED) {
|
||||
become404Page();
|
||||
} elseif ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if (Auth::check()) {
|
||||
if (hasParticipated($myUser, $contest)) {
|
||||
$is_in_contest = true;
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
} else {
|
||||
redirectToLogin();
|
||||
$is_participating = true;
|
||||
$submit_time_limit = UOJContestProblem::cur()->submitTimeLimit();
|
||||
$max_cnt = UOJContest::cur()->maxSubmissionCountPerProblem();
|
||||
if ($submit_time_limit != -1) {
|
||||
$cur_contest_time = (UOJTime::$time_now->getTimestamp() - UOJContest::info('start_time')->getTimestamp()) / 60;
|
||||
if ($cur_contest_time > $submit_time_limit) {
|
||||
$no_more_submission = "本题只能在比赛的前 {$submit_time_limit} 分钟提交,没法再交咯";
|
||||
}
|
||||
}
|
||||
if (!$no_more_submission) {
|
||||
if ($max_cnt != -1) {
|
||||
$cnt = UOJContestProblem::cur()->queryUserSubmissionCountInContest(Auth::user());
|
||||
if ($cnt >= $max_cnt) {
|
||||
$no_more_submission = "提交次数已达到 {$cnt} 次,没法再交咯";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$no_more_submission) {
|
||||
if ($max_cnt != -1) {
|
||||
$warning1 = "已使用 {$cnt}/{$max_cnt} 次提交机会";
|
||||
} else {
|
||||
$ban_in_contest = !isProblemVisibleToUser($problem, $myUser);
|
||||
|
||||
if (!hasRegistered($myUser, $contest) && !isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
$warning1 = null;
|
||||
}
|
||||
} else {
|
||||
if ($contest['cur_progress'] == CONTEST_IN_PROGRESS) {
|
||||
if (hasRegistered($myUser, $contest)) {
|
||||
if (hasParticipated($myUser, $contest)) {
|
||||
$is_in_contest = true;
|
||||
} else {
|
||||
redirectTo("/contest/{$contest['id']}/confirm");
|
||||
}
|
||||
}
|
||||
if ($submit_time_limit != -1) {
|
||||
$warning2 = "注意本题只能在比赛的前 {$submit_time_limit} 分钟提交";
|
||||
} else {
|
||||
$warning2 = null;
|
||||
}
|
||||
if ($warning1 && $warning2) {
|
||||
$submission_warning = "{$warning1}({$warning2})";
|
||||
} else {
|
||||
$submission_warning = $warning1 !== null ? $warning1 : $warning2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!isProblemVisibleToUser($problem, $myUser)) {
|
||||
become404Page();
|
||||
}
|
||||
|
||||
if (!isNormalUser($myUser) && UOJConfig::$data['switch']['force-login']) {
|
||||
become403Page();
|
||||
}
|
||||
}
|
||||
|
||||
$submission_requirement = json_decode($problem['submission_requirement'], true);
|
||||
$problem_extra_config = getProblemExtraConfig($problem);
|
||||
$custom_test_requirement = getProblemCustomTestRequirement($problem);
|
||||
// 比赛导航
|
||||
$tabs_info = [
|
||||
'dashboard' => [
|
||||
'name' => UOJLocale::get('contests::contest dashboard'),
|
||||
'url' => '/contest/' . UOJContest::info('id'),
|
||||
],
|
||||
'submissions' => [
|
||||
'name' => UOJLocale::get('contests::contest submissions'),
|
||||
'url' => '/contest/' . UOJContest::info('id') . '/submissions',
|
||||
],
|
||||
'standings' => [
|
||||
'name' => UOJLocale::get('contests::contest standings'),
|
||||
'url' => '/contest/' . UOJContest::info('id') . '/standings',
|
||||
],
|
||||
];
|
||||
|
||||
if ($custom_test_requirement && Auth::check()) {
|
||||
$custom_test_submission = DB::selectFirst("select * from custom_test_submissions where submitter = '".Auth::id()."' and problem_id = {$problem['id']} order by id desc limit 1");
|
||||
$custom_test_submission_result = json_decode($custom_test_submission['result'], true);
|
||||
if (UOJContest::cur()->progress() > CONTEST_TESTING) {
|
||||
$tabs_info['after_contest_standings'] = [
|
||||
'name' => UOJLocale::get('contests::after contest standings'),
|
||||
'url' => '/contest/' . UOJContest::info('id') . '/after_contest_standings',
|
||||
];
|
||||
$tabs_info['self_reviews'] = [
|
||||
'name' => UOJLocale::get('contests::contest self reviews'),
|
||||
'url' => '/contest/' . UOJContest::info('id') . '/self_reviews',
|
||||
];
|
||||
}
|
||||
if ($custom_test_requirement && $_GET['get'] == 'custom-test-status-details' && Auth::check()) {
|
||||
if ($custom_test_submission == null) {
|
||||
|
||||
if (UOJContest::cur()->userCanManage(Auth::user())) {
|
||||
$tabs_info['backstage'] = [
|
||||
'name' => UOJLocale::get('contests::contest backstage'),
|
||||
'url' => '/contest/' . UOJContest::info('id') . '/backstage',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$submission_requirement = UOJProblem::cur()->getSubmissionRequirement();
|
||||
$custom_test_requirement = UOJProblem::cur()->getCustomTestRequirement();
|
||||
$custom_test_enabled = $custom_test_requirement && $pre_submit_check_ret === true;
|
||||
|
||||
function handleUpload($zip_file_name, $content, $tot_size) {
|
||||
global $is_participating;
|
||||
UOJSubmission::onUpload($zip_file_name, $content, $tot_size, $is_participating);
|
||||
}
|
||||
function handleCustomTestUpload($zip_file_name, $content, $tot_size) {
|
||||
UOJCustomTestSubmission::onUpload($zip_file_name, $content, $tot_size);
|
||||
}
|
||||
if ($custom_test_enabled) {
|
||||
UOJCustomTestSubmission::init(UOJProblem::cur(), Auth::user());
|
||||
|
||||
if (UOJRequest::get('get') == 'custom-test-status-details') {
|
||||
if (!UOJCustomTestSubmission::cur()) {
|
||||
echo json_encode(null);
|
||||
} elseif ($custom_test_submission['status'] != 'Judged') {
|
||||
echo json_encode(array(
|
||||
} elseif (!UOJCustomTestSubmission::cur()->hasJudged()) {
|
||||
echo json_encode([
|
||||
'judged' => false,
|
||||
'html' => getSubmissionStatusDetails($custom_test_submission)
|
||||
));
|
||||
'waiting' => true,
|
||||
'html' => UOJCustomTestSubmission::cur()->getStatusDetailsHTML(),
|
||||
]);
|
||||
} else {
|
||||
ob_start();
|
||||
$styler = new CustomTestSubmissionDetailsStyler();
|
||||
if (!hasViewPermission($problem_extra_config['view_details_type'], $myUser, $problem, $submission)) {
|
||||
if (!UOJCustomTestSubmission::cur()->userPermissionCodeCheck(Auth::user(), UOJProblem::cur()->getExtraConfig('view_details_type'))) {
|
||||
$styler->fade_all_details = true;
|
||||
}
|
||||
echoJudgementDetails($custom_test_submission_result['details'], $styler, 'custom_test_details');
|
||||
echoJudgmentDetails(UOJCustomTestSubmission::cur()->getResult('details'), $styler, 'custom_test_details');
|
||||
$result = ob_get_contents();
|
||||
ob_end_clean();
|
||||
echo json_encode(array(
|
||||
echo json_encode([
|
||||
'judged' => true,
|
||||
'html' => getSubmissionStatusDetails($custom_test_submission),
|
||||
'waiting' => false,
|
||||
'html' => UOJCustomTestSubmission::cur()->getStatusDetailsHTML(),
|
||||
'result' => $result
|
||||
));
|
||||
]);
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
$can_use_zip_upload = true;
|
||||
foreach ($submission_requirement as $req) {
|
||||
if ($req['type'] == 'source code') {
|
||||
$can_use_zip_upload = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleUpload($zip_file_name, $content, $tot_size) {
|
||||
global $problem, $contest, $myUser, $is_in_contest;
|
||||
|
||||
$content['config'][] = array('problem_id', $problem['id']);
|
||||
if ($is_in_contest && $contest['extra_config']["contest_type"]!='IOI' && !isset($contest['extra_config']["problem_{$problem['id']}"])) {
|
||||
$content['final_test_config'] = $content['config'];
|
||||
$content['config'][] = array('test_sample_only', 'on');
|
||||
}
|
||||
$esc_content = DB::escape(json_encode($content));
|
||||
|
||||
$language = '/';
|
||||
foreach ($content['config'] as $row) {
|
||||
if (strEndWith($row[0], '_language')) {
|
||||
$language = $row[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($language != '/') {
|
||||
Cookie::set('uoj_preferred_language', $language, time() + 60 * 60 * 24 * 365, '/');
|
||||
}
|
||||
$esc_language = DB::escape($language);
|
||||
|
||||
$result = array();
|
||||
$result['status'] = "Waiting";
|
||||
$result_json = json_encode($result);
|
||||
|
||||
if ($is_in_contest) {
|
||||
DB::query("insert into submissions (problem_id, contest_id, submit_time, submitter, content, language, tot_size, status, result, is_hidden) values (${problem['id']}, ${contest['id']}, now(), '${myUser['username']}', '$esc_content', '$esc_language', $tot_size, '${result['status']}', '$result_json', 0)");
|
||||
} else {
|
||||
DB::query("insert into submissions (problem_id, submit_time, submitter, content, language, tot_size, status, result, is_hidden) values (${problem['id']}, now(), '${myUser['username']}', '$esc_content', '$esc_language', $tot_size, '${result['status']}', '$result_json', {$problem['is_hidden']})");
|
||||
}
|
||||
}
|
||||
function handleCustomTestUpload($zip_file_name, $content, $tot_size) {
|
||||
global $problem, $contest, $myUser;
|
||||
|
||||
$content['config'][] = array('problem_id', $problem['id']);
|
||||
$content['config'][] = array('custom_test', 'on');
|
||||
$esc_content = DB::escape(json_encode($content));
|
||||
|
||||
$language = '/';
|
||||
foreach ($content['config'] as $row) {
|
||||
if (strEndWith($row[0], '_language')) {
|
||||
$language = $row[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($language != '/') {
|
||||
Cookie::set('uoj_preferred_language', $language, time() + 60 * 60 * 24 * 365, '/');
|
||||
}
|
||||
$esc_language = DB::escape($language);
|
||||
|
||||
$result = array();
|
||||
$result['status'] = "Waiting";
|
||||
$result_json = json_encode($result);
|
||||
|
||||
DB::insert("insert into custom_test_submissions (problem_id, submit_time, submitter, content, status, result) values ({$problem['id']}, now(), '{$myUser['username']}', '$esc_content', '{$result['status']}', '$result_json')");
|
||||
}
|
||||
|
||||
if ($can_use_zip_upload) {
|
||||
$zip_answer_form = newZipSubmissionForm('zip_answer',
|
||||
$submission_requirement,
|
||||
'uojRandAvaiableSubmissionFileName',
|
||||
'handleUpload');
|
||||
$zip_answer_form->extra_validator = function() {
|
||||
global $ban_in_contest;
|
||||
if ($ban_in_contest) {
|
||||
return '请耐心等待比赛结束后题目对所有人可见了再提交';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
$zip_answer_form->succ_href = $is_in_contest ? "/contest/{$contest['id']}/submissions" : '/submissions';
|
||||
$zip_answer_form->runAtServer();
|
||||
}
|
||||
|
||||
$answer_form = newSubmissionForm('answer',
|
||||
$submission_requirement,
|
||||
'uojRandAvaiableSubmissionFileName',
|
||||
'handleUpload');
|
||||
$answer_form->extra_validator = function() {
|
||||
global $ban_in_contest;
|
||||
if ($ban_in_contest) {
|
||||
return '请耐心等待比赛结束后题目对所有人可见了再提交';
|
||||
$custom_test_form = newSubmissionForm(
|
||||
'custom_test',
|
||||
$custom_test_requirement,
|
||||
'FS::randomAvailableTmpFileName',
|
||||
'handleCustomTestUpload'
|
||||
);
|
||||
$custom_test_form->appendHTML('<div id="div-custom_test_result"></div>');
|
||||
$custom_test_form->succ_href = 'none';
|
||||
$custom_test_form->extra_validator = function () {
|
||||
if (UOJCustomTestSubmission::cur() && !UOJCustomTestSubmission::cur()->hasJudged()) {
|
||||
return '上一个测评尚未结束';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
$answer_form->succ_href = $is_in_contest ? "/contest/{$contest['id']}/submissions" : '/submissions';
|
||||
$answer_form->runAtServer();
|
||||
$custom_test_form->ctrl_enter_submit = true;
|
||||
$custom_test_form->setAjaxSubmit(
|
||||
<<<EOD
|
||||
function(response_text) {
|
||||
custom_test_onsubmit(
|
||||
response_text,
|
||||
$('#div-custom_test_result')[0],
|
||||
'{$_SERVER['REQUEST_URI']}?get=custom-test-status-details'
|
||||
)
|
||||
}
|
||||
EOD
|
||||
);
|
||||
$custom_test_form->submit_button_config['text'] = UOJLocale::get('problems::run');
|
||||
$custom_test_form->runAtServer();
|
||||
}
|
||||
|
||||
if ($custom_test_requirement) {
|
||||
$custom_test_form = newSubmissionForm('custom_test',
|
||||
$custom_test_requirement,
|
||||
function() {
|
||||
return uojRandAvaiableFileName('/tmp/');
|
||||
},
|
||||
'handleCustomTestUpload');
|
||||
$custom_test_form->appendHTML(<<<EOD
|
||||
<div id="div-custom_test_result"></div>
|
||||
EOD
|
||||
);
|
||||
$custom_test_form->succ_href = 'none';
|
||||
$custom_test_form->extra_validator = function() {
|
||||
global $ban_in_contest, $custom_test_submission;
|
||||
if ($ban_in_contest) {
|
||||
return '请耐心等待比赛结束后题目对所有人可见了再提交';
|
||||
}
|
||||
if ($custom_test_submission && $custom_test_submission['status'] != 'Judged') {
|
||||
return '上一个测评尚未结束';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
$custom_test_form->ctrl_enter_submit = true;
|
||||
$custom_test_form->setAjaxSubmit(<<<EOD
|
||||
function(response_text) {custom_test_onsubmit(response_text, $('#div-custom_test_result')[0], '{$_SERVER['REQUEST_URI']}?get=custom-test-status-details')}
|
||||
EOD
|
||||
);
|
||||
$custom_test_form->submit_button_config['text'] = UOJLocale::get('problems::run');
|
||||
$custom_test_form->runAtServer();
|
||||
$can_use_zip_upload = true;
|
||||
foreach ($submission_requirement as $req) {
|
||||
if ($req['type'] == 'source code') {
|
||||
$can_use_zip_upload = false;
|
||||
}
|
||||
?>
|
||||
}
|
||||
|
||||
if ($pre_submit_check_ret === true && !$no_more_submission) {
|
||||
$submission_extra_validator = function () {
|
||||
if (!submission_frequency_check()) {
|
||||
UOJLog::warning('a user exceeds the submission frequency limit! ' . Auth::id() . ' at problem #' . UOJProblem::info('id'));
|
||||
return '交题交得太快啦,坐下来喝杯阿华田休息下吧?';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
if (UOJProblem::cur()->userCanUploadSubmissionViaZip(Auth::user())) {
|
||||
$zip_answer_form = newZipSubmissionForm(
|
||||
'zip-answer',
|
||||
$submission_requirement,
|
||||
'FS::randomAvailableSubmissionFileName',
|
||||
'handleUpload'
|
||||
);
|
||||
$zip_answer_form->extra_validators[] = $submission_extra_validator;
|
||||
$zip_answer_form->succ_href = $is_participating ? '/contest/' . UOJContest::info('id') . '/submissions' : '/submissions';
|
||||
$zip_answer_form->runAtServer();
|
||||
}
|
||||
|
||||
$answer_form = newSubmissionForm(
|
||||
'answer',
|
||||
$submission_requirement,
|
||||
'FS::randomAvailableSubmissionFileName',
|
||||
'handleUpload'
|
||||
);
|
||||
$answer_form->extra_validator = $submission_extra_validator;
|
||||
$answer_form->succ_href = $is_participating ? '/contest/' . UOJContest::info('id') . '/submissions' : '/submissions';
|
||||
$answer_form->runAtServer();
|
||||
}
|
||||
|
||||
$conf = UOJProblem::cur()->getProblemConf();
|
||||
?>
|
||||
|
||||
<?php echoUOJPageHeader(HTML::stripTags($problem['title']) . ' - ' . UOJLocale::get('problems::problem')) ?>
|
||||
<?php
|
||||
$limit = getUOJConf("/var/uoj_data/{$problem['id']}/problem.conf");
|
||||
$time_limit = $limit['time_limit'];
|
||||
$memory_limit = $limit['memory_limit'];
|
||||
|
||||
$problem_uploader = $problem['uploader'];
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<!-- Left col -->
|
||||
<div class="col-lg-9">
|
||||
|
||||
<!-- Left col -->
|
||||
<div class="col-lg-9">
|
||||
|
||||
<?php if ($contest): ?>
|
||||
<!-- 比赛导航 -->
|
||||
<?php
|
||||
$tabs_info = array(
|
||||
'dashboard' => array(
|
||||
'name' => UOJLocale::get('contests::contest dashboard'),
|
||||
'url' => "/contest/{$contest['id']}"
|
||||
),
|
||||
'submissions' => array(
|
||||
'name' => UOJLocale::get('contests::contest submissions'),
|
||||
'url' => "/contest/{$contest['id']}/submissions"
|
||||
),
|
||||
'standings' => array(
|
||||
'name' => UOJLocale::get('contests::contest standings'),
|
||||
'url' => "/contest/{$contest['id']}/standings"
|
||||
),
|
||||
);
|
||||
|
||||
if ($contest['cur_progress'] > CONTEST_TESTING) {
|
||||
$tabs_info['after_contest_standings'] = array(
|
||||
'name' => UOJLocale::get('contests::after contest standings'),
|
||||
'url' => "/contest/{$contest['id']}/after_contest_standings"
|
||||
);
|
||||
$tabs_info['self_reviews'] = array(
|
||||
'name' => UOJLocale::get('contests::contest self reviews'),
|
||||
'url' => "/contest/{$contest['id']}/self_reviews"
|
||||
);
|
||||
}
|
||||
|
||||
if (hasContestPermission(Auth::user(), $contest)) {
|
||||
$tabs_info['backstage'] = array(
|
||||
'name' => UOJLocale::get('contests::contest backstage'),
|
||||
'url' => "/contest/{$contest['id']}/backstage"
|
||||
);
|
||||
}
|
||||
?>
|
||||
<div class="mb-2">
|
||||
<?= HTML::tablist($tabs_info, '', 'nav-pills') ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
|
||||
<h1 class="h2 card-title text-center">
|
||||
<?php if ($contest): ?>
|
||||
<?= $problem_letter ?>. <?= $problem['title'] ?>
|
||||
<?php else: ?>
|
||||
#<?= $problem['id']?>. <?= $problem['title'] ?>
|
||||
<?php endif ?>
|
||||
</h1>
|
||||
|
||||
<div class="text-center small">
|
||||
时间限制: <?= $time_limit != null ? "$time_limit s" : "N/A" ?>
|
||||
 
|
||||
空间限制: <?= $memory_limit != null ? "$memory_limit MB" : "N/A" ?>
|
||||
 
|
||||
上传者: <?= getUserLink($problem_uploader ?: "root") ?>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="statement">
|
||||
<article class="mt-3 markdown-body">
|
||||
<?= $problem_content['statement'] ?>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tab-pane" id="submit">
|
||||
<div class="top-buffer-sm"></div>
|
||||
<?php if ($can_use_zip_upload): ?>
|
||||
<?php $zip_answer_form->printHTML(); ?>
|
||||
<hr />
|
||||
<strong><?= UOJLocale::get('problems::or upload files one by one') ?><br /></strong>
|
||||
<?php if (isset($tabs_info)) : ?>
|
||||
<!-- 比赛导航 -->
|
||||
<div class="mb-2">
|
||||
<?= HTML::tablist($tabs_info, '', 'nav-pills') ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?php $answer_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php if ($custom_test_requirement): ?>
|
||||
<div class="tab-pane" id="custom-test">
|
||||
<div class="top-buffer-sm"></div>
|
||||
<?php $custom_test_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
|
||||
</div>
|
||||
<!-- End left col -->
|
||||
<h1 class="card-title text-center">
|
||||
<?php if (UOJContest::cur()) : ?>
|
||||
<?= UOJProblem::cur()->getTitle(['with' => 'letter', 'simplify' => true]) ?>
|
||||
<?php else : ?>
|
||||
<?= UOJProblem::cur()->getTitle(['with' => 'id']) ?>
|
||||
<?php endif ?>
|
||||
</h1>
|
||||
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<!-- Right col -->
|
||||
<?php
|
||||
$time_limit = $conf instanceof UOJProblemConf ? $conf->getVal('time_limit', null) : null;
|
||||
$memory_limit = $conf instanceof UOJProblemConf ? $conf->getVal('memory_limit', null) : null;
|
||||
?>
|
||||
<div class="text-center small">
|
||||
时间限制: <?= $time_limit ? "$time_limit s" : "N/A" ?>
|
||||
 
|
||||
空间限制: <?= $memory_limit ? "$memory_limit MB" : "N/A" ?>
|
||||
 
|
||||
上传者: <?= UOJProblem::cur()->getUploaderLink() ?>
|
||||
</div>
|
||||
|
||||
<?php if ($contest): ?>
|
||||
<!-- Contest card -->
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
<h3 class="h5 card-title text-center">
|
||||
<a class="text-decoration-none text-body" href="/contest/<?= $contest['id'] ?>">
|
||||
<?= $contest['name'] ?>
|
||||
</a>
|
||||
</h3>
|
||||
<div class="card-text text-center text-muted">
|
||||
<?php if ($contest['cur_progress'] <= CONTEST_IN_PROGRESS): ?>
|
||||
<span id="contest-countdown"></span>
|
||||
<?php else: ?>
|
||||
<?= UOJLocale::get('contests::contest ended') ?>
|
||||
<?php endif ?>
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="statement">
|
||||
<article class="mt-3 markdown-body">
|
||||
<?= $problem_content['statement'] ?>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tab-pane" id="submit">
|
||||
<?php if ($pre_submit_check_ret !== true) : ?>
|
||||
<h3 class="text-warning"><?= $pre_submit_check_ret ?></h3>
|
||||
<?php elseif ($no_more_submission) : ?>
|
||||
<h3 class="text-warning"><?= $no_more_submission ?></h3>
|
||||
<?php else : ?>
|
||||
<?php if ($submission_warning) : ?>
|
||||
<h3 class="text-warning"><?= $submission_warning ?></h3>
|
||||
<?php endif ?>
|
||||
<?php if (isset($zip_answer_form)) : ?>
|
||||
<?php $zip_answer_form->printHTML(); ?>
|
||||
<hr />
|
||||
<strong><?= UOJLocale::get('problems::or upload files one by one') ?><br /></strong>
|
||||
<?php endif ?>
|
||||
<?php $answer_form->printHTML(); ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php if ($custom_test_enabled) : ?>
|
||||
<div class="tab-pane" id="custom-test">
|
||||
<?php $custom_test_form->printHTML(); ?>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
比赛评价:<?= getClickZanBlock('C', $contest['id'], $contest['zan']) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($contest['cur_progress'] <= CONTEST_IN_PROGRESS): ?>
|
||||
<script type="text/javascript">
|
||||
$('#contest-countdown').countdown(<?= $contest['end_time']->getTimestamp() - UOJTime::$time_now->getTimestamp() ?>, function(){}, '1.75rem', false);
|
||||
</script>
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
|
||||
<!-- 题目导航卡片 -->
|
||||
<div class="card card-default mb-2">
|
||||
<ul class="nav nav-pills nav-fill flex-column" role="tablist">
|
||||
<li class="nav-item text-start">
|
||||
<a href="#statement" class="nav-link active" role="tab" data-bs-toggle="pill" data-bs-target="#statement">
|
||||
<i class="bi bi-journal-text"></i>
|
||||
<?= UOJLocale::get('problems::statement') ?>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item text-start">
|
||||
<a href="#submit" class="nav-link" role="tab" data-bs-toggle="pill" data-bs-target="#submit">
|
||||
<i class="bi bi-upload"></i>
|
||||
<?= UOJLocale::get('problems::submit') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php if ($custom_test_requirement): ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="#custom-test" role="tab" data-bs-toggle="pill" data-bs-target="#custom-test">
|
||||
<i class="bi bi-braces"></i>
|
||||
<?= UOJLocale::get('problems::custom test') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if (!$contest || $contest['cur_progress'] >= CONTEST_FINISHED): ?>
|
||||
<li class="nav-item text-start">
|
||||
<a href="/problem/<?= $problem['id'] ?>/solutions" class="nav-link" role="tab">
|
||||
<i class="bi bi-journal-bookmark"></i>
|
||||
<?= UOJLocale::get('problems::solutions') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link"
|
||||
<?php if ($contest): ?>
|
||||
href="/contest/<?= $contest['id'] ?>/problem/<?= $problem['id'] ?>/statistics"
|
||||
<?php else: ?>
|
||||
href="/problem/<?= $problem['id'] ?>/statistics"
|
||||
</div>
|
||||
<!-- End left col -->
|
||||
|
||||
<aside class="col-lg-3 mt-3 mt-lg-0">
|
||||
<!-- Right col -->
|
||||
|
||||
<?php if (UOJContest::cur()) : ?>
|
||||
<!-- Contest card -->
|
||||
<div class="card card-default mb-2">
|
||||
<div class="card-body">
|
||||
<h3 class="h4 card-title text-center">
|
||||
<a class="text-decoration-none text-body" href="/contest/<?= UOJContest::info('id') ?>">
|
||||
<?= UOJContest::info('name') ?>
|
||||
</a>
|
||||
</h3>
|
||||
<div class="card-text text-center text-muted">
|
||||
<?php if (UOJContest::cur()->progress() <= CONTEST_IN_PROGRESS) : ?>
|
||||
<span id="contest-countdown"></span>
|
||||
<?php else : ?>
|
||||
<?= UOJLocale::get('contests::contest ended') ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-transparent">
|
||||
比赛评价:<?= ClickZans::getBlock('C', UOJContest::info('id'), UOJContest::info('zan')) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (UOJContest::cur()->progress() <= CONTEST_IN_PROGRESS) : ?>
|
||||
<script>
|
||||
$('#contest-countdown').countdown(<?= UOJContest::info('end_time')->getTimestamp() - UOJTime::$time_now->getTimestamp() ?>, function() {}, '1.75rem', false);
|
||||
</script>
|
||||
<?php endif ?>
|
||||
>
|
||||
<i class="bi bi-graph-up"></i>
|
||||
<?= UOJLocale::get('problems::statistics') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php if (hasProblemPermission($myUser, $problem)): ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="/problem/<?= $problem['id'] ?>/manage/statement" role="tab">
|
||||
<i class="bi bi-sliders"></i>
|
||||
<?= UOJLocale::get('problems::manage') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<div class="card-footer bg-transparent">
|
||||
评价:<?= getClickZanBlock('P', $problem['id'], $problem['zan']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 附件 -->
|
||||
<div class="card card-default mb-2">
|
||||
<ul class="nav nav-fill flex-column">
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="<?= HTML::url("/download.php?type=problem&id={$problem['id']}") ?>">
|
||||
<i class="bi bi-hdd-stack"></i>
|
||||
测试数据
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="<?= HTML::url("/download.php?type=attachment&id={$problem['id']}") ?>">
|
||||
<i class="bi bi-download"></i>
|
||||
附件下载
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- 题目导航卡片 -->
|
||||
<div class="card card-default mb-2">
|
||||
<ul class="nav nav-pills nav-fill flex-column" role="tablist">
|
||||
<li class="nav-item text-start">
|
||||
<a href="#statement" class="nav-link active" role="tab" data-bs-toggle="pill" data-bs-target="#statement">
|
||||
<i class="bi bi-journal-text"></i>
|
||||
<?= UOJLocale::get('problems::statement') ?>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item text-start">
|
||||
<a href="#submit" class="nav-link" role="tab" data-bs-toggle="pill" data-bs-target="#submit">
|
||||
<i class="bi bi-upload"></i>
|
||||
<?= UOJLocale::get('problems::submit') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php if ($custom_test_enabled) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="#custom-test" role="tab" data-bs-toggle="pill" data-bs-target="#custom-test">
|
||||
<i class="bi bi-braces"></i>
|
||||
<?= UOJLocale::get('problems::custom test') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if (!UOJContest::cur() || UOJContest::cur()->progress() >= CONTEST_FINISHED) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a href="/problem/<?= $problem['id'] ?>/solutions" class="nav-link" role="tab">
|
||||
<i class="bi bi-journal-bookmark"></i>
|
||||
<?= UOJLocale::get('problems::solutions') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if (UOJContest::cur() && UOJContest::cur()->userCanSeeProblemStatistics(Auth::user())) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="/contest/<?= UOJContest::info('id') ?>/problem/<?= $problem['id'] ?>/statistics">
|
||||
<i class="bi bi-graph-up"></i>
|
||||
<?= UOJLocale::get('problems::statistics') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php elseif (!UOJContest::cur()) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="/problem/<?= $problem['id'] ?>/statistics">
|
||||
<i class="bi bi-graph-up"></i>
|
||||
<?= UOJLocale::get('problems::statistics') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<?php if (UOJProblem::cur()->userCanManage(Auth::user())) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="/problem/<?= $problem['id'] ?>/manage/statement" role="tab">
|
||||
<i class="bi bi-sliders"></i>
|
||||
<?= UOJLocale::get('problems::manage') ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<div class="card-footer bg-transparent">
|
||||
评价:<?= ClickZans::getBlock('P', $problem['id'], $problem['zan']) ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$sidebar_config = array();
|
||||
if ($contest && $contest['cur_progress'] <= CONTEST_IN_PROGRESS) {
|
||||
$sidebar_config['upcoming_contests_hidden'] = '';
|
||||
}
|
||||
uojIncludeView('sidebar', $sidebar_config);
|
||||
?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
<!-- 附件 -->
|
||||
<div class="card card-default mb-2">
|
||||
<ul class="nav nav-fill flex-column">
|
||||
<?php if (UOJProblem::cur()->userCanDownloadTestData(Auth::user())) : ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="<?= HTML::url("/download/problem/{$problem['id']}/data.zip") ?>">
|
||||
<i class="bi bi-hdd-stack"></i>
|
||||
测试数据
|
||||
</a>
|
||||
</li>
|
||||
<?php endif ?>
|
||||
<li class="nav-item text-start">
|
||||
<a class="nav-link" href="<?= HTML::url("/download/problem/{$problem['id']}/attachment.zip") ?>">
|
||||
<i class="bi bi-download"></i>
|
||||
附件下载
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$sidebar_config = [];
|
||||
if (UOJContest::cur() && UOJContest::cur()->progress() <= CONTEST_IN_PROGRESS) {
|
||||
$sidebar_config['upcoming_contests_hidden'] = '';
|
||||
}
|
||||
uojIncludeView('sidebar', $sidebar_config);
|
||||
?>
|
||||
</aside>
|
||||
<!-- end right col -->
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Javascript to enable link to tab
|
||||
var hash = location.hash.replace(/^#/, '');
|
||||
if (hash) {
|
||||
bootstrap.Tab.jQueryInterface.call($('.nav-pills a[href="#' + hash + '"]'), 'show').blur();
|
||||
}
|
||||
|
||||
// Change hash for page-reload
|
||||
$('.nav-pills a').on('shown.bs.tab', function(e) {
|
||||
if (e.target.hash == '#statement') {
|
||||
window.location.hash = '';
|
||||
} else {
|
||||
window.location.hash = e.target.hash;
|
||||
$(document).ready(function() {
|
||||
// Javascript to enable link to tab
|
||||
var hash = location.hash.replace(/^#/, '');
|
||||
if (hash) {
|
||||
bootstrap.Tab.jQueryInterface.call($('.nav-pills a[href="#' + hash + '"]'), 'show').blur();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php if ($contest && $contest['cur_progress'] <= CONTEST_IN_PROGRESS): ?>
|
||||
<script type="text/javascript">
|
||||
checkContestNotice(<?= $contest['id'] ?>, '<?= UOJTime::$time_now_str ?>');
|
||||
// Change hash for page-reload
|
||||
$('.nav-pills a').on('shown.bs.tab', function(e) {
|
||||
if (e.target.hash == '#statement') {
|
||||
window.location.hash = '';
|
||||
} else {
|
||||
window.location.hash = e.target.hash;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php endif ?>
|
||||
|
||||
<?php echoUOJPageFooter() ?>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,169 +1,171 @@
|
||||
<?php
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
requireLib('bootstrap5');
|
||||
requirePHPLib('form');
|
||||
|
||||
if (!Auth::check() && UOJConfig::$data['switch']['force-login']) {
|
||||
redirectToLogin();
|
||||
}
|
||||
Auth::check() || redirectToLogin();
|
||||
UOJProblem::init(UOJRequest::get('id')) || UOJResponse::page404();
|
||||
UOJProblem::cur()->userCanManage(Auth::user()) || UOJResponse::page403();
|
||||
|
||||
if (!validateUInt($_GET['id']) || !($problem = queryProblemBrief($_GET['id']))) {
|
||||
become404Page();
|
||||
}
|
||||
if (!hasProblemPermission($myUser, $problem)) {
|
||||
become403Page();
|
||||
$managers_form = newAddDelCmdForm(
|
||||
'managers',
|
||||
'validateUserAndStoreByUsername',
|
||||
function ($type, $username, &$vdata) {
|
||||
$user = $vdata['user'][$username];
|
||||
if ($type == '+') {
|
||||
DB::insert([
|
||||
"insert into problems_permissions",
|
||||
"(problem_id, username)",
|
||||
"values", DB::tuple([UOJProblem::info('id'), $user['username']])
|
||||
]);
|
||||
} else if ($type == '-') {
|
||||
DB::delete([
|
||||
"delete from problems_permissions",
|
||||
"where", [
|
||||
"problem_id" => UOJProblem::info('id'),
|
||||
"username" => $user['username']
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$managers_form = newAddDelCmdForm('managers',
|
||||
function($username) {
|
||||
if (!validateUsername($username) || !queryUser($username)) {
|
||||
return "不存在名为{$username}的用户";
|
||||
$managers_form->runAtServer();
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$update_uploader_form = new UOJBs4Form('update_uploader');
|
||||
$update_uploader_form->addInput(
|
||||
'new_uploader_username',
|
||||
'text',
|
||||
'用户名',
|
||||
$problem['uploader'] ?: 'root',
|
||||
function ($username, &$vdata) {
|
||||
if (!UOJUser::query($username)) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
$vdata['username'] = $username;
|
||||
|
||||
return '';
|
||||
},
|
||||
function($type, $username) {
|
||||
global $problem;
|
||||
if ($type == '+') {
|
||||
DB::query("insert into problems_permissions (problem_id, username) values (${problem['id']}, '$username')");
|
||||
} elseif ($type == '-') {
|
||||
DB::query("delete from problems_permissions where problem_id = ${problem['id']} and username = '$username'");
|
||||
}
|
||||
}
|
||||
null
|
||||
);
|
||||
|
||||
$managers_form->runAtServer();
|
||||
|
||||
|
||||
if (isSuperUser($myUser)) {
|
||||
$update_uploader_form = new UOJForm('update_uploader');
|
||||
$update_uploader_form->addInput('new_uploader_username', 'text', '用户名', $problem['uploader'] ?: 'root',
|
||||
function ($x) {
|
||||
if (!validateUsername($x)) {
|
||||
return '用户名不合法';
|
||||
}
|
||||
|
||||
if (!queryUser($x)) {
|
||||
return '用户不存在';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
null
|
||||
);
|
||||
$update_uploader_form->submit_button_config['align'] = 'compressed';
|
||||
$update_uploader_form->submit_button_config['text'] = '修改上传者';
|
||||
$update_uploader_form->submit_button_config['class_str'] = 'mt-2 btn btn-warning';
|
||||
$update_uploader_form->handle = function() {
|
||||
global $problem;
|
||||
|
||||
$username = $_POST['new_uploader_username'];
|
||||
|
||||
DB::query("update problems set uploader = '{$username}' where id = {$problem['id']}");
|
||||
};
|
||||
$update_uploader_form->runAtServer();
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader(HTML::stripTags($problem['title']) . ' - 管理者 - 题目管理') ?>
|
||||
$update_uploader_form->submit_button_config['align'] = 'compressed';
|
||||
$update_uploader_form->submit_button_config['text'] = '修改上传者';
|
||||
$update_uploader_form->submit_button_config['class_str'] = 'mt-2 btn btn-warning';
|
||||
$update_uploader_form->handle = function (&$vdata) {
|
||||
DB::update([
|
||||
"update problems",
|
||||
"set", ["uploader" => $vdata['username']],
|
||||
"where", ["id" => UOJProblem::info('id')]
|
||||
]);
|
||||
};
|
||||
$update_uploader_form->runAtServer();
|
||||
}
|
||||
?>
|
||||
<?php echoUOJPageHeader('管理者 - ' . HTML::stripTags($problem['title'])) ?>
|
||||
|
||||
<div class="row">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<!-- left col -->
|
||||
<div class="col-lg-9">
|
||||
<h1>
|
||||
<?= UOJProblem::cur()->getTitle() ?> 管理
|
||||
</h1>
|
||||
|
||||
<h1 class="h2">
|
||||
#<?= $problem['id'] ?>. <?= $problem['title'] ?> 管理
|
||||
</h1>
|
||||
<ul class="nav nav-pills my-3" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/problem/<?= UOJProblem::info('id') ?>/manage/statement" role="tab">
|
||||
题面
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/problem/<?= UOJProblem::info('id') ?>/manage/managers" role="tab">
|
||||
管理者
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/problem/<?= UOJProblem::info('id') ?>/manage/data" role="tab">
|
||||
数据
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav nav-pills my-3" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/problem/<?= $problem['id'] ?>/manage/statement" role="tab">
|
||||
题面
|
||||
</a>
|
||||
</li>
|
||||