├── .gitignore
├── .travis.yml
├── Android
├── .gitignore
├── README.md
├── build.gradle
├── gradlew
├── gradlew.bat
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── lzc
│ │ └── lpoj
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── lzc
│ │ │ └── lpoj
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── lzc
│ └── lpoj
│ └── ExampleUnitTest.java
├── Backend
├── Backend
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── Dockerfile
├── ProblemData
│ └── README.md
├── README.md
├── blog
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── board
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── classes
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── contest
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── item
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── judgestatus
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── problem
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── requirements.txt
├── user
│ ├── __init__.py
│ ├── admin.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
└── wiki
│ ├── __init__.py
│ ├── migrations
│ └── __init__.py
│ ├── models.py
│ ├── permission.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── CrawlingServer
├── CodeForceContestCounter.py
├── Codeforces.py
├── CodeforcesRate.py
├── Dockerfile
├── HDU.py
├── LPOJ.py
├── README.md
├── Vjudge.py
├── main.py
├── requirements.txt
└── setting.json
├── Database
├── Dockerfile
├── README.md
├── conf
│ ├── mysqld.cnf
│ └── mysqld_safe_syslog.cnf
└── init_database.sql
├── Docs
├── .gitignore
├── README.md
├── docs
│ ├── .vuepress
│ │ ├── config.js
│ │ └── public
│ │ │ └── img
│ │ │ ├── donate.jpg
│ │ │ ├── faq
│ │ │ ├── db.png
│ │ │ ├── db2.png
│ │ │ ├── db3.png
│ │ │ └── db4.png
│ │ │ ├── favicon.ico
│ │ │ └── logo.jpg
│ ├── README.md
│ ├── deploy
│ │ ├── README.md
│ │ ├── backend.md
│ │ ├── crawlingserver.md
│ │ ├── frontend.md
│ │ ├── judger.md
│ │ └── judgeserver.md
│ ├── dev
│ │ ├── README.md
│ │ ├── backend.md
│ │ ├── frontend.md
│ │ ├── judger.md
│ │ └── judgerserver.md
│ ├── doc
│ │ ├── README.md
│ │ ├── faq.md
│ │ ├── judger.md
│ │ ├── oj.md
│ │ └── utils.md
│ └── faq
│ │ ├── README.md
│ │ ├── intro.md
│ │ ├── systemstruct.md
│ │ └── whatisoj.md
├── package-lock.json
└── package.json
├── Frontend
├── .babelrc
├── .dockerignore
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── Dockerfile
├── README.md
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── nginx.conf
├── package-lock.json
├── package.json
├── src
│ ├── App.vue
│ ├── components
│ │ ├── admin
│ │ │ ├── adminaddchoiceproblem.vue
│ │ │ ├── adminaddcontest.vue
│ │ │ ├── adminaddproblem.vue
│ │ │ ├── adminboard.vue
│ │ │ ├── adminchangechoiceproblem.vue
│ │ │ ├── adminchangecontest.vue
│ │ │ ├── adminchangepro.vue
│ │ │ ├── adminclassmanage.vue
│ │ │ ├── adminmanageuser.vue
│ │ │ ├── adminrejudge.vue
│ │ │ ├── adminsetting.vue
│ │ │ ├── admintrainning.vue
│ │ │ └── givechoiceproblemscore.vue
│ │ ├── chart
│ │ │ ├── echarts.js
│ │ │ ├── rankchart.vue
│ │ │ ├── ratingchart.vue
│ │ │ └── teamchart.vue
│ │ ├── contest
│ │ │ ├── contestannounce.vue
│ │ │ ├── contestchoiceproblem.vue
│ │ │ ├── contestcomment.vue
│ │ │ ├── contestdetail.vue
│ │ │ ├── contestoverview.vue
│ │ │ ├── contestproblem.vue
│ │ │ ├── contestrank.vue
│ │ │ ├── contestsubmit.vue
│ │ │ └── contesttutorial.vue
│ │ ├── main.vue
│ │ ├── mainpage
│ │ │ ├── admin.vue
│ │ │ ├── billboard.vue
│ │ │ ├── blog.vue
│ │ │ ├── classdetail.vue
│ │ │ ├── classes.vue
│ │ │ ├── contest.vue
│ │ │ ├── homework.vue
│ │ │ ├── problem.vue
│ │ │ ├── rank.vue
│ │ │ ├── setting.vue
│ │ │ ├── statue.vue
│ │ │ ├── user.vue
│ │ │ └── wiki.vue
│ │ ├── problem
│ │ │ └── problemdetail.vue
│ │ ├── utils
│ │ │ ├── acrank.vue
│ │ │ ├── algorithmselect.vue
│ │ │ ├── blogmini.vue
│ │ │ ├── cfrate.vue
│ │ │ ├── contestmini.vue
│ │ │ ├── description.vue
│ │ │ ├── languageselect.vue
│ │ │ ├── ojmessage.vue
│ │ │ ├── prostatistice.vue
│ │ │ ├── ratingrule.vue
│ │ │ ├── soulrow.vue
│ │ │ ├── statusmini.vue
│ │ │ ├── todolist.vue
│ │ │ ├── topuser.vue
│ │ │ ├── welcomemessage.vue
│ │ │ └── wikidetail.vue
│ │ └── wiki
│ │ │ ├── algorithm.vue
│ │ │ ├── algorithmpages
│ │ │ ├── basic.vue
│ │ │ ├── dp.vue
│ │ │ ├── ds.vue
│ │ │ ├── editalgorithm.vue
│ │ │ ├── geometry.vue
│ │ │ ├── graph.vue
│ │ │ ├── intro.vue
│ │ │ ├── math.vue
│ │ │ ├── misc.vue
│ │ │ ├── search.vue
│ │ │ └── string.vue
│ │ │ ├── code.vue
│ │ │ ├── mbcode
│ │ │ ├── codeedit.vue
│ │ │ ├── viewcode.vue
│ │ │ └── viewcodedetail.vue
│ │ │ ├── newalgorithm.vue
│ │ │ ├── trainning.vue
│ │ │ └── trainning
│ │ │ └── trainningdetail.vue
│ ├── login.vue
│ ├── main.js
│ ├── register.vue
│ └── router
│ │ └── index.js
└── static
│ ├── .gitkeep
│ └── js
│ ├── MathJax.js
│ ├── config
│ └── TeX-AMS-MML_HTMLorMML.js
│ ├── fonts
│ └── HTML-CSS
│ │ └── TeX
│ │ └── woff
│ │ ├── MathJax_AMS-Regular.woff
│ │ ├── MathJax_Caligraphic-Bold.woff
│ │ ├── MathJax_Caligraphic-Regular.woff
│ │ ├── MathJax_Fraktur-Bold.woff
│ │ ├── MathJax_Fraktur-Regular.woff
│ │ ├── MathJax_Main-Bold.woff
│ │ ├── MathJax_Main-Italic.woff
│ │ ├── MathJax_Main-Regular.woff
│ │ ├── MathJax_Math-BoldItalic.woff
│ │ ├── MathJax_Math-Italic.woff
│ │ ├── MathJax_Math-Regular.woff
│ │ ├── MathJax_SansSerif-Bold.woff
│ │ ├── MathJax_SansSerif-Italic.woff
│ │ ├── MathJax_SansSerif-Regular.woff
│ │ ├── MathJax_Script-Regular.woff
│ │ ├── MathJax_Size1-Regular.woff
│ │ ├── MathJax_Size2-Regular.woff
│ │ ├── MathJax_Size3-Regular.woff
│ │ ├── MathJax_Size4-Regular.woff
│ │ └── MathJax_Typewriter-Regular.woff
│ └── jax
│ └── output
│ └── HTML-CSS
│ ├── fonts
│ └── TeX
│ │ └── fontdata.js
│ └── jax.js
├── FrontendMobile
├── .babelrc
├── .dockerignore
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── Dockerfile
├── README.md
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── nginx.conf
├── package-lock.json
├── package.json
├── src
│ ├── App.vue
│ ├── components
│ │ ├── contest
│ │ │ ├── contestdetail.vue
│ │ │ ├── contestoverview.vue
│ │ │ ├── contestrank.vue
│ │ │ └── contestsubmit.vue
│ │ ├── main.vue
│ │ ├── mainpage
│ │ │ ├── billboard.vue
│ │ │ ├── blog.vue
│ │ │ ├── contest.vue
│ │ │ ├── problem.vue
│ │ │ ├── rank.vue
│ │ │ ├── statue.vue
│ │ │ ├── user.vue
│ │ │ └── wiki.vue
│ │ ├── problem
│ │ │ └── problemdetail.vue
│ │ ├── utils
│ │ │ ├── acrank.vue
│ │ │ ├── algorithmselect.vue
│ │ │ ├── contestmini.vue
│ │ │ ├── topuser.vue
│ │ │ ├── welcomemessage.vue
│ │ │ └── wikidetail.vue
│ │ └── wiki
│ │ │ ├── newalgorithm.vue
│ │ │ ├── trainning.vue
│ │ │ └── trainning
│ │ │ └── trainningdetail.vue
│ ├── login.vue
│ ├── main.js
│ ├── register.vue
│ └── router
│ │ └── index.js
└── static
│ └── .gitkeep
├── HomePage
├── assets
│ ├── css
│ │ ├── animate.min.css
│ │ ├── bootstrap.min.css
│ │ ├── default.css
│ │ ├── fontawesome-all.min.css
│ │ ├── magnific-popup.css
│ │ ├── meanmenu.css
│ │ ├── owl.carousel.min.css
│ │ ├── owl.theme.default.min.css
│ │ ├── responsive.css
│ │ └── scrolltop.css
│ ├── fonts
│ │ └── fontawesome-webfont.woff2
│ ├── img
│ │ ├── about
│ │ │ ├── about-1.png
│ │ │ ├── shape-1.png
│ │ │ ├── shape-2.png
│ │ │ ├── shape-3.png
│ │ │ └── shape-4.png
│ │ ├── breadcrumb
│ │ │ └── breadcrumb.png
│ │ ├── cta
│ │ │ ├── 2.jpg
│ │ │ ├── 5.png
│ │ │ ├── cta-bg.jpg
│ │ │ └── cta-bg.png
│ │ ├── faqs
│ │ │ └── faqs-1.png
│ │ ├── footer
│ │ │ └── foot-bg.png
│ │ ├── hero
│ │ │ └── hero-bg-1.png
│ │ ├── logo-1.png
│ │ ├── logo-2.png
│ │ ├── screen
│ │ │ ├── screen-1.jpg
│ │ │ ├── screen-2.jpg
│ │ │ ├── screen-3.jpg
│ │ │ └── screen-4.jpg
│ │ ├── services
│ │ │ ├── icon-1-1.png
│ │ │ ├── icon-1-2.png
│ │ │ ├── icon-1-3.png
│ │ │ ├── icon-1.png
│ │ │ ├── icon-2.png
│ │ │ ├── icon-3.png
│ │ │ ├── shape-1.png
│ │ │ ├── shape-2.png
│ │ │ └── shape-3.png
│ │ └── top-arrow.svg
│ └── js
│ │ ├── ajax-form.js
│ │ ├── bootstrap.min.js
│ │ ├── counterup.min.js
│ │ ├── jquery-1.12.4.min.js
│ │ ├── magnific-popup.min.js
│ │ ├── main.js
│ │ ├── maps.active.js
│ │ ├── meanmenu.min.js
│ │ ├── modernizr-3.5.0.min.js
│ │ ├── owl.carousel.min.js
│ │ ├── plugins.js
│ │ ├── popper.min.js
│ │ ├── scrolltop.js
│ │ ├── waypoints.min.js
│ │ └── wow.min.js
├── index.html
└── style.css
├── Judger
├── CMakeLists.txt
├── Dockerfile
├── JudgeHDU
│ └── JudgeHDU.py
├── JudgerCore
│ ├── _judger
│ │ ├── __init__.py
│ │ └── __init__.pyc
│ ├── build
│ │ ├── lib.linux-x86_64-2.7
│ │ │ └── _judger
│ │ │ │ └── __init__.py
│ │ └── lib
│ │ │ └── _judger
│ │ │ └── __init__.py
│ └── setup.py
├── ProblemData
│ └── README.md
├── README.md
├── datatime.json
├── main.py
├── output
│ └── libjudger.so
├── requirements.txt
├── setting.json
└── src
│ ├── argtable3.c
│ ├── argtable3.h
│ ├── child.c
│ ├── child.h
│ ├── killer.c
│ ├── killer.h
│ ├── logger.c
│ ├── logger.h
│ ├── main.c
│ ├── rules
│ ├── c_cpp.c
│ ├── general.c
│ └── seccomp_rules.h
│ ├── runner.c
│ └── runner.h
├── JudgerServer
├── Dockerfile
├── README.md
├── main.py
├── requirements.txt
└── setting.json
├── LICENSE
├── README.md
├── Tools
├── HDUSpider.py
├── README.md
├── RaiseCheck.py
├── RatingCalculator.py
├── RecoverBoard.py
├── SubmitExport.py
├── UserImporter.py
├── duplication_checking.py
└── setting.json
├── docker-compose-build.yml
└── docker-compose.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__
2 | Judger/build
3 | Judger/test
4 | *.pyc
5 | Judger/*.cpp
6 | Judger/*.c
7 | Judger/*out
8 | Judger/*.log
9 | Judger/*.out
10 | *.in
11 | *.out
12 | *.log
13 | Judger/output/libjudger.so
14 | *.zip
15 | *.exe
16 | .vscode
17 | *.class
18 | # GDUFSTeamScore.py
19 | # GDUFSTeamExport.py
20 | CrawlingServer/contest.json
21 | Database/data
22 | 数据
23 |
24 | CrawlingServer/NowCoderSpider.py
25 | CrawlingServer/CFSpider.py
26 | CrawlingServer/HDUSpider.py
27 | 00*
28 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | services:
2 | - docker
3 |
4 | env:
5 | DOCKER_COMPOSE_VERSION: 1.24.0
6 |
7 | before_install:
8 | - sudo rm /usr/local/bin/docker-compose
9 | - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
10 | - chmod +x docker-compose
11 | - sudo mv docker-compose /usr/local/bin
12 |
13 | script:
14 | - docker-compose -f docker-compose-build.yml build
--------------------------------------------------------------------------------
/Android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
3 | .gradle
4 | *.jks
5 | /local.properties
6 | .DS_Store
7 | /build
8 | /release
9 | /gradle
10 | /push/build
11 | /captures
12 | .externalNativeBuild
--------------------------------------------------------------------------------
/Android/README.md:
--------------------------------------------------------------------------------
1 | # LPOJ的安卓版
2 |
3 | 其实就是一个浏览器,访问手机版……
--------------------------------------------------------------------------------
/Android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 | defaultConfig {
7 | applicationId "com.lzc.lpoj"
8 | minSdkVersion 15
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | implementation fileTree(dir: 'libs', include: ['*.jar'])
24 | implementation 'androidx.appcompat:appcompat:1.1.0'
25 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
26 | testImplementation 'junit:junit:4.12'
27 | androidTestImplementation 'androidx.test:runner:1.2.0'
28 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
29 | }
30 | buildscript {
31 | repositories {
32 | google()
33 | jcenter()
34 |
35 | }
36 | dependencies {
37 | classpath 'com.android.tools.build:gradle:3.4.2'
38 |
39 | // NOTE: Do not place your application dependencies here; they belong
40 | // in the individual module build.gradle files
41 | }
42 | }
43 |
44 | allprojects {
45 | repositories {
46 | google()
47 | jcenter()
48 |
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/Android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/Android/src/androidTest/java/com/lzc/lpoj/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.lzc.lpoj;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.InstrumentationRegistry;
6 | import androidx.test.runner.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getTargetContext();
24 |
25 | assertEquals("com.lzc.lpoj", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Android/src/main/java/com/lzc/lpoj/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.lzc.lpoj;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.os.Bundle;
6 |
7 | import android.os.Bundle;
8 | import android.app.Activity;
9 | import android.view.Menu;
10 | import android.view.Window;
11 | import android.webkit.WebChromeClient;
12 | import android.webkit.WebSettings;
13 | import android.webkit.WebView;
14 | import android.webkit.WebViewClient;
15 | import android.view.KeyEvent;
16 |
17 |
18 | public class MainActivity extends Activity {
19 |
20 | private WebView webView;
21 |
22 | @Override
23 | public boolean onKeyDown(int keyCode, KeyEvent event) {
24 | if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
25 | webView.goBack(); // goBack()表示返回WebView的上一页面
26 | return true;
27 | }
28 | return super.onKeyDown(keyCode,event);
29 | }
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | requestWindowFeature(Window.FEATURE_NO_TITLE);
35 | setContentView(R.layout.activity_main);
36 |
37 | webView = (WebView) findViewById(R.id.webView);
38 |
39 | webView.loadUrl("https://m.lpoj.cn");
40 |
41 | webView.setWebViewClient(new WebViewClient() {
42 | // 当点击链接时,覆盖窗口
43 | @Override
44 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
45 | // TODO Auto-generated method stub
46 | view.loadUrl(url);// 加载url
47 | return super.shouldOverrideUrlLoading(view, url);
48 | }
49 | });
50 |
51 | WebSettings webSettings = webView.getSettings();
52 | webSettings.setJavaScriptEnabled(true);// 启用JS脚本
53 | // 这里可以有很多设置
54 | // webSettings.setSupportZoom(true); // 支持缩放
55 | // webSettings.setBuiltInZoomControls(true); // 启用内置缩放装置
56 |
57 | webView.setWebChromeClient(new WebChromeClient() {
58 | // 当WebView进度改变时更新窗口进度
59 | @Override
60 | public void onProgressChanged(WebView view, int newProgress) {
61 | // TODO Auto-generated method stub
62 | // 自己实现
63 | super.onProgressChanged(view, newProgress);
64 | }
65 | });
66 |
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/Android/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/Android/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/Android/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/Android/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LPOJ
3 |
4 |
--------------------------------------------------------------------------------
/Android/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Android/src/test/java/com/lzc/lpoj/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.lzc.lpoj;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/Backend/Backend/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/Backend/__init__.py
--------------------------------------------------------------------------------
/Backend/Backend/urls.py:
--------------------------------------------------------------------------------
1 | """Backend URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.conf.urls import url, include
14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
15 | """
16 | from django.conf.urls import url, include
17 | from django.contrib import admin
18 | from django.urls import path
19 |
20 | urlpatterns = [
21 | url(r'^admin/', admin.site.urls),
22 | url(r'', include('problem.urls')),
23 | url(r'', include('judgestatus.urls')),
24 | url(r'', include('user.urls')),
25 | url(r'', include('contest.urls')),
26 | url(r'', include('board.urls')),
27 | url(r'', include('blog.urls')),
28 | url(r'', include('wiki.urls')),
29 | url(r'', include('item.urls')),
30 | url(r'', include('classes.urls')),
31 |
32 | ]
33 |
--------------------------------------------------------------------------------
/Backend/Backend/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for Backend project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Backend.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/Backend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7.2
2 | MAINTAINER linzecong
3 | ADD . ./Backend
4 | WORKDIR /Backend
5 | ENV DB_HOST "lpojdatabase"
6 | ENV DB_PASSWORD "lpojdatabase"
7 | ENV DB_USER 'root'
8 | ENV DB_PORT 3306
9 | RUN apt-get update && apt-get install python-django -y
10 | RUN pip install -r requirements.txt
11 | EXPOSE 8000
12 | CMD python manage.py makemigrations && python manage.py makemigrations judgestatus item problem user contest board blog wiki classes && python manage.py migrate && echo "from django.contrib.auth.models import User; User.objects.filter(email=\"admin@example.com\").delete(); User.objects.create_superuser(\"admin\", \"admin@example.com\", \"admin\")" | python manage.py shell && gunicorn -w 5 --bind 0.0.0.0:8000 -k 'gevent' Backend.wsgi:application
13 |
14 |
--------------------------------------------------------------------------------
/Backend/ProblemData/README.md:
--------------------------------------------------------------------------------
1 | # 数据文件夹
2 |
3 | 所有数据将由后端保存在ProblemData中,因此目录结构不要改变!即
4 |
5 | Backend
6 |
7 | ----Backend
8 |
9 | ----ProblemData
10 |
11 | ----manage.py
12 |
13 | ......
14 |
15 |
16 | 前端会通过后端将数据压缩包上传到这个文件夹,当然,你也可以手动上传。务必是zip文件,且zip内没有文件夹
--------------------------------------------------------------------------------
/Backend/README.md:
--------------------------------------------------------------------------------
1 | # 后端与数据库部署
2 |
3 | ## Docker部署
4 | 非专业用户不推荐使用Docker单独部署
5 | 修改Dockerfile中的ENV为你的数据库地址和密码等
6 | ```
7 | docker build -t lpojbackend .
8 | docker run -d -p 8000:8000 lpojbackend
9 | ```
10 |
11 | ## 一般部署
12 |
13 | 1. 首先安装Django
14 | ```
15 | pip install django
16 |
17 | pip install djangorestframework
18 |
19 | pip install django-filter
20 |
21 | sudo apt-get install python-django
22 |
23 | pip install django-cors-headers
24 |
25 | pip install mysqlclient
26 | ```
27 | 2. 安装数据库,已安装的可跳过
28 | ```
29 | sudo apt-get install mysql-server
30 |
31 | mysql -uroot -p
32 | mysql > CREATE DATABASE LPOJ DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
33 | mysql > USE mysql
34 | mysql > GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_password' WITH GRANT OPTION;
35 | mysql > ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password by 'your_password';
36 | mysql > flush privileges;
37 |
38 | sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
39 |
40 | #修改bind-address 为 0.0.0.0
41 | ```
42 | 3. 部署后端
43 | ```
44 | cd Backend
45 |
46 | cd Backend
47 |
48 | sudo nano setting.py
49 | # 修改数据库配置为你自己的数据库IP和用户名密码
50 |
51 | cd ..
52 |
53 | python manage.py makemigrations
54 |
55 | python manage.py migrate
56 |
57 | echo "from django.contrib.auth.models import User; User.objects.filter(email=\"admin@example.com\").delete(); User.objects.create_superuser(\"admin\", \"admin@example.com\", \"admin\")" | python manage.py shell
58 |
59 | python manage.py runserver 0.0.0.0:8000
60 | ```
61 |
62 | 1. 添加管理员
63 | > 安装成功后,先通过IP:80访问OJ,注册一个用户
64 | >
65 | > 然后进入 IP:8000/admin 以用户名admin 密码admin 登录后台(请及时修改后台密码)
66 | >
67 | > 修改User表中,你注册的超级用户的type为3,使得你注册的用户变为超级管理员
--------------------------------------------------------------------------------
/Backend/blog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/blog/__init__.py
--------------------------------------------------------------------------------
/Backend/blog/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/blog/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/blog/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | class Banner(models.Model):
4 |
5 | msg = models.CharField(max_length=500)
6 | time = models.DateField(auto_now=True)
7 |
8 | objects = models.Manager()
9 |
10 | def __str__(self):
11 | return self.username
12 |
13 | class OJMessage(models.Model):
14 |
15 | username = models.CharField(max_length=50)
16 | msg = models.CharField(max_length=500)
17 | time = models.DateField(auto_now=True)
18 | rating = models.IntegerField(default=1500)
19 |
20 | objects = models.Manager()
21 |
22 | def __str__(self):
23 | return self.username
24 |
25 |
26 | class Blog(models.Model):
27 |
28 | username = models.CharField(max_length=50)
29 | title = models.CharField(max_length=500)
30 | url = models.CharField(max_length=500)
31 | summary = models.CharField(max_length=1000)
32 | time = models.CharField(max_length=50)
33 |
34 | objects = models.Manager()
35 |
36 | def __str__(self):
37 | return self.username
38 |
--------------------------------------------------------------------------------
/Backend/blog/permission.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import permissions
3 | from board.models import SettingBoard
4 |
5 | def getVisitorPermission(request):
6 | setting = SettingBoard.objects.filter(id=1)
7 | if len(setting) != 0:
8 | if setting[0].openvisitor is False:
9 | userid = request.session.get('user_id', None)
10 | if userid:
11 | return True
12 | else:
13 | return False
14 | else:
15 | return True
16 | else:
17 | return True
18 |
19 | class UserRatingOnly(permissions.BasePermission):
20 | def has_permission(self, request, view):
21 | if getVisitorPermission(request) == False:
22 | return False
23 |
24 | if request.method in permissions.SAFE_METHODS:
25 | return True
26 | data = request.data
27 | username = data.get('username')
28 | userid = request.session.get('user_id', None)
29 | r1 = data.get('rating')
30 | r2 = request.session.get('rating', None)
31 | if r1 != r2:
32 | return False
33 | if userid == username or request.session.get('type', 1) != 1:
34 | return True
35 | else:
36 | return False
37 |
38 | def has_object_permission(self, request, view, blog):
39 | if getVisitorPermission(request) == False:
40 | return False
41 | if request.method in permissions.SAFE_METHODS:
42 | return True
43 | data = request.data
44 | username = blog.username
45 | userid = request.session.get('user_id', None)
46 | r1 = blog.rating
47 | r2 = request.session.get('rating', None)
48 | if r1 != r2:
49 | return False
50 | if userid == username or request.session.get('type', 1) != 1:
51 | return True
52 | else:
53 | return False
54 |
55 |
56 | class ManagerOnly(permissions.BasePermission):
57 | def has_permission(self, request, view):
58 | if getVisitorPermission(request) == False:
59 | return False
60 | if request.method in permissions.SAFE_METHODS:
61 | return True
62 |
63 | type = request.session.get('type', 1)
64 | if type == 2 or type == 3:
65 | return True
66 | else:
67 | return False
68 |
--------------------------------------------------------------------------------
/Backend/blog/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import OJMessage, Blog,Banner
4 |
5 | class BannerSerializer(serializers.ModelSerializer):
6 | class Meta:
7 | model = Banner
8 | fields = '__all__'
9 |
10 | class OJMessageSerializer(serializers.ModelSerializer):
11 | class Meta:
12 | model = OJMessage
13 | fields = '__all__'
14 |
15 |
16 | class BlogSerializer(serializers.ModelSerializer):
17 | class Meta:
18 | model = Blog
19 | fields = '__all__'
20 |
--------------------------------------------------------------------------------
/Backend/blog/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('ojmessage', views.OJMessageView)
8 | routers.register('blog', views.BlogView)
9 | routers.register('banner', views.BannerView)
10 |
11 | urlpatterns = [
12 | url('', include(routers.urls)),
13 | ]
14 |
--------------------------------------------------------------------------------
/Backend/blog/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from rest_framework import viewsets
3 | from rest_framework.pagination import LimitOffsetPagination
4 | from rest_framework.throttling import ScopedRateThrottle
5 | from .models import OJMessage, Blog,Banner
6 | from .serializers import OJMessageSerializer, BlogSerializer,BannerSerializer
7 | from .permission import ManagerOnly, UserRatingOnly
8 |
9 | class BannerView(viewsets.ModelViewSet):
10 | queryset = Banner.objects.all().order_by("-id")
11 | serializer_class = BannerSerializer
12 | filter_fields = ('time',)
13 | permission_classes = (ManagerOnly,)
14 | pagination_class = LimitOffsetPagination
15 | throttle_scope = "post"
16 | throttle_classes = [ScopedRateThrottle, ]
17 |
18 |
19 | class OJMessageView(viewsets.ModelViewSet):
20 | queryset = OJMessage.objects.all().order_by("-id")
21 | serializer_class = OJMessageSerializer
22 | filter_fields = ('username', 'time')
23 | permission_classes = (UserRatingOnly,)
24 | pagination_class = LimitOffsetPagination
25 | throttle_scope = "post"
26 | throttle_classes = [ScopedRateThrottle, ]
27 |
28 |
29 | class BlogView(viewsets.ModelViewSet):
30 | queryset = Blog.objects.all().order_by("-id")
31 | serializer_class = BlogSerializer
32 | filter_fields = ('username', 'time')
33 | pagination_class = LimitOffsetPagination
34 | permission_classes = (ManagerOnly,)
35 | throttle_scope = "post"
36 | throttle_classes = [ScopedRateThrottle, ]
37 |
--------------------------------------------------------------------------------
/Backend/board/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/board/__init__.py
--------------------------------------------------------------------------------
/Backend/board/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/board/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/board/permission.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import permissions
3 | from board.models import SettingBoard
4 |
5 | def getVisitorPermission(request):
6 | setting = SettingBoard.objects.filter(id=1)
7 | if len(setting) != 0:
8 | if setting[0].openvisitor is False:
9 | userid = request.session.get('user_id', None)
10 | if userid:
11 | return True
12 | else:
13 | return False
14 | else:
15 | return True
16 | else:
17 | return True
18 |
19 | class ManagerOnly(permissions.BasePermission):
20 | def has_permission(self, request, view):
21 | if getVisitorPermission(request) == False:
22 | return False
23 | if request.method in permissions.SAFE_METHODS:
24 | return True
25 |
26 | type = request.session.get('type', 1)
27 | if type == 2 or type == 3:
28 | return True
29 | else:
30 | return False
31 |
--------------------------------------------------------------------------------
/Backend/board/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import Board, DailyBoard, TeamBoard, DailyContestBoard,SettingBoard
4 |
5 |
6 | class SettingBoardSerializer(serializers.ModelSerializer):
7 | class Meta:
8 | model = SettingBoard
9 | fields = '__all__'
10 |
11 |
12 | class BoardSerializer(serializers.ModelSerializer):
13 | class Meta:
14 | model = Board
15 | fields = '__all__'
16 |
17 |
18 | class DailyBoardSerializer(serializers.ModelSerializer):
19 | class Meta:
20 | model = DailyBoard
21 | fields = '__all__'
22 |
23 |
24 | class TeamBoardSerializer(serializers.ModelSerializer):
25 | class Meta:
26 | model = TeamBoard
27 | fields = '__all__'
28 |
29 |
30 | class DailyContestBoardSerializer(serializers.ModelSerializer):
31 | class Meta:
32 | model = DailyContestBoard
33 | fields = '__all__'
34 |
--------------------------------------------------------------------------------
/Backend/board/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('board', views.BoardView)
8 | routers.register('dailyboard', views.DailyBoardView)
9 | routers.register('teamboard', views.TeamBoardView)
10 | routers.register('dailycontestboard', views.DailyContestBoardView)
11 | routers.register('settingboard', views.SettingBoardView)
12 |
13 | urlpatterns = [
14 | url('', include(routers.urls)),
15 | ]
16 |
--------------------------------------------------------------------------------
/Backend/board/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from rest_framework import viewsets
3 | from rest_framework.throttling import ScopedRateThrottle
4 | from rest_framework.pagination import LimitOffsetPagination
5 | from .serializers import BoardSerializer,SettingBoardSerializer, DailyBoardSerializer, TeamBoardSerializer, DailyContestBoardSerializer
6 | from .permission import ManagerOnly
7 | from .models import Board, DailyBoard, TeamBoard, DailyContestBoard,SettingBoard
8 | import datetime
9 |
10 | class SettingBoardView(viewsets.ModelViewSet):
11 | queryset = SettingBoard.objects.all()
12 | serializer_class = SettingBoardSerializer
13 | permission_classes = (ManagerOnly,)
14 | throttle_scope = "post"
15 | throttle_classes = [ScopedRateThrottle, ]
16 |
17 |
18 | class BoardView(viewsets.ModelViewSet):
19 | queryset = Board.objects.all()
20 | serializer_class = BoardSerializer
21 | filter_fields = ('username',)
22 | pagination_class = LimitOffsetPagination
23 | permission_classes = (ManagerOnly,)
24 | throttle_scope = "post"
25 | throttle_classes = [ScopedRateThrottle, ]
26 |
27 |
28 |
29 | class DailyBoardView(viewsets.ModelViewSet):
30 | queryset = DailyBoard.objects.filter(collecttime__gte=datetime.datetime.now(
31 | )-datetime.timedelta(days=10)).order_by('collecttime') # 这里有bug,不应该在queryset里写filter。时间会提前算好,导致不准确
32 | serializer_class = DailyBoardSerializer
33 | filter_fields = ('username', 'collecttime')
34 | pagination_class = LimitOffsetPagination
35 | permission_classes = (ManagerOnly,)
36 | throttle_scope = "post"
37 | throttle_classes = [ScopedRateThrottle, ]
38 |
39 |
40 | class TeamBoardView(viewsets.ModelViewSet):
41 | queryset = TeamBoard.objects.all()
42 | serializer_class = TeamBoardSerializer
43 | filter_fields = ('teammember', 'collecttime')
44 | pagination_class = LimitOffsetPagination
45 | permission_classes = (ManagerOnly,)
46 | throttle_scope = "post"
47 | throttle_classes = [ScopedRateThrottle, ]
48 |
49 |
50 | class DailyContestBoardView(viewsets.ModelViewSet):
51 | queryset = DailyContestBoard.objects.all()
52 | serializer_class = DailyContestBoardSerializer
53 | filter_fields = ('contestdate', 'teammember')
54 | pagination_class = LimitOffsetPagination
55 | permission_classes = (ManagerOnly,)
56 | throttle_scope = "post"
57 | throttle_classes = [ScopedRateThrottle, ]
58 |
--------------------------------------------------------------------------------
/Backend/classes/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/classes/__init__.py
--------------------------------------------------------------------------------
/Backend/classes/admin.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 |
4 | from django.contrib import admin
5 | # Register your models here.
6 |
7 |
--------------------------------------------------------------------------------
/Backend/classes/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/classes/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/classes/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.db import models
3 | # Create your models here.
4 | class ClassStudentData(models.Model):
5 | studentUserName = models.CharField(max_length=50, null=False,default="")
6 | studentNumber = models.CharField(max_length=50, null=False)
7 | className = models.CharField(max_length=50, null=False)
8 | studentRealName = models.CharField(max_length=50, null=False)
9 |
10 | objects = models.Manager()
11 |
12 | def __str__(self):
13 | return self.studentUserName
14 |
15 | class theClasses(models.Model):
16 | className = models.CharField(max_length=50,default="None")
17 | classSize = models.CharField(max_length=50, default="None")
18 | canjoinclass = models.CharField(max_length=50, default="open")
19 |
20 | objects = models.Manager()
21 |
22 | def __str__(self):
23 | return self.className
24 |
--------------------------------------------------------------------------------
/Backend/classes/permission.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import permissions
3 | from .models import ClassStudentData, theClasses
4 |
5 | from board.models import SettingBoard
6 | import datetime
7 |
8 | def getVisitorPermission(request):
9 | setting = SettingBoard.objects.filter(id=1)
10 | if len(setting) != 0:
11 | if setting[0].openvisitor is False:
12 | userid = request.session.get('user_id', None)
13 | if userid:
14 | return True
15 | else:
16 | return False
17 | else:
18 | return True
19 | else:
20 | return True
21 |
22 | class ManagerOnly(permissions.BasePermission):
23 | def has_permission(self, request, view):
24 | if getVisitorPermission(request) == False:
25 | return False
26 | type = request.session.get('type', 1)
27 | if type == 2 or type == 3:
28 | return True
29 |
30 | if request.method in permissions.SAFE_METHODS:
31 | return True
32 |
33 | return False
34 |
--------------------------------------------------------------------------------
/Backend/classes/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import theClasses,ClassStudentData
4 | class ClassDataSerializer(serializers.ModelSerializer):
5 | class Meta:
6 | model = theClasses
7 | fields = '__all__'
8 |
9 | class ClassStudentDataSerializer(serializers.ModelSerializer):
10 | class Meta:
11 | model = ClassStudentData
12 | fields = '__all__'
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Backend/classes/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('classes', views.ClassDataView)
8 | routers.register('classStudent', views.ClassStudentDataView)
9 |
10 | urlpatterns = [
11 | url('', include(routers.urls)),
12 | url(r'^ADDclasses', views.ClassDataAPIView.as_view()),
13 | url(r'^AddClass', views.ClassStudentDataAPIView.as_view()),
14 | url(r'^DeleteClass', views.DeleteClassDataAPIView.as_view()),
15 | ]
16 |
--------------------------------------------------------------------------------
/Backend/contest/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/contest/__init__.py
--------------------------------------------------------------------------------
/Backend/contest/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/contest/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/contest/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import ContestAnnouncement,ContestTutorial, ContestComingInfo, ContestRatingChange, ContestBoard, ContestComment, ContestInfo, ContestProblem, ContestRegister, ContestBoardTotal, StudentChoiceAnswer,ContestChoiceProblem
4 |
5 |
6 | class ContestAnnouncementSerializer(serializers.ModelSerializer):
7 | class Meta:
8 | model = ContestAnnouncement
9 | fields = '__all__'
10 |
11 | class ContestTutorialSerializer(serializers.ModelSerializer):
12 | class Meta:
13 | model = ContestTutorial
14 | fields = '__all__'
15 |
16 |
17 | class ContestBoardSerializer(serializers.ModelSerializer):
18 | class Meta:
19 | model = ContestBoard
20 | fields = '__all__'
21 |
22 |
23 | class ContestCommentSerializer(serializers.ModelSerializer):
24 | class Meta:
25 | model = ContestComment
26 | fields = '__all__'
27 |
28 |
29 | class ContestInfoSerializer(serializers.ModelSerializer):
30 | class Meta:
31 | model = ContestInfo
32 | fields = '__all__'
33 |
34 |
35 | class ContestProblemSerializer(serializers.ModelSerializer):
36 | class Meta:
37 | model = ContestProblem
38 | fields = '__all__'
39 |
40 |
41 | class ContestRegisterSerializer(serializers.ModelSerializer):
42 | class Meta:
43 | model = ContestRegister
44 | fields = '__all__'
45 |
46 |
47 | class ContestRatingChangeSerializer(serializers.ModelSerializer):
48 | class Meta:
49 | model = ContestRatingChange
50 | fields = '__all__'
51 |
52 |
53 | class ContestComingInfoSerializer(serializers.ModelSerializer):
54 | class Meta:
55 | model = ContestComingInfo
56 | fields = '__all__'
57 |
58 | class ContestBoardTotalSerializer(serializers.ModelSerializer):
59 | class Meta:
60 | model = ContestBoardTotal
61 | fields = '__all__'
62 |
63 | class StudentChoiceAnswerSerializer(serializers.ModelSerializer):
64 | class Meta:
65 | model = StudentChoiceAnswer
66 | fields = '__all__'
67 |
68 | class ContestChoiceProblemSerializer(serializers.ModelSerializer):
69 | class Meta:
70 | model = ContestChoiceProblem
71 | fields = '__all__'
72 |
--------------------------------------------------------------------------------
/Backend/contest/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('contestannouncement', views.ContestAnnouncementView)
8 | routers.register('contestcomment', views.ContestCommentView)
9 | routers.register('contestinfo', views.ContestInfoView)
10 | routers.register('contestcominginfo', views.ContestComingInfoView)
11 | routers.register('contestproblem', views.ContestProblemView)
12 | routers.register('contestboard', views.ContestBoardView)
13 | routers.register('contestregister', views.ContestRegisterView)
14 | routers.register('contestratingchange', views.ContestRatingChangeView)
15 | routers.register('contesttutorial', views.ContestTutorialView)
16 | routers.register('contesttotalboard', views.ContestBoardTotalView)
17 | routers.register('conteststudentchoiceanswer', views.StudentChoiceAnswerView)
18 | routers.register('contestchoiceproblem', views.ContestChoiceProblemView)
19 |
20 | urlpatterns = [
21 | url('', include(routers.urls)),
22 | url(r'^currenttime', views.CurrentTimeView.as_view()),
23 | url(r'^contestfilterboard', views.ContestBoardFilterAPIView.as_view()),
24 | url(r'^getcontestchoiceproblems', views.GetContestChoiceProblems.as_view()),
25 | url(r'^scorecontestchoiceproblems', views.ScoreContestChoiceProblems.as_view()),
26 | url(r'^isboardlock', views.ContestIsBoardLockAPIView.as_view()),
27 |
28 | ]
29 |
--------------------------------------------------------------------------------
/Backend/item/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/item/__init__.py
--------------------------------------------------------------------------------
/Backend/item/admin.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | from django.contrib import admin
4 | from .models import Item
5 |
6 | admin.site.register(Item)
--------------------------------------------------------------------------------
/Backend/item/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/item/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/item/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.db import models
3 | from user.models import User
4 | import datetime
5 |
6 | class Item(models.Model):
7 | user = models.ForeignKey(User, on_delete=models.CASCADE)
8 | title = models.TextField(default="待补题",null=False)
9 | detail = models.TextField(null=True,blank=True)
10 | createtime = models.DateTimeField(null=False,default=datetime.datetime.now)
11 | deadtime = models.DateTimeField(null=True,default=datetime.datetime.now)
12 | status = models.IntegerField(default=1) # 1 新建 0 已完成
13 | tag = models.IntegerField(default=1) # 1 便签 # 2 待办事项 # 3 待补题
14 |
15 | objects = models.Manager()
16 |
17 | def __str__(self):
18 |
19 | return self.title
20 |
21 |
--------------------------------------------------------------------------------
/Backend/item/permission.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import permissions
3 | from .models import User
4 |
5 | from board.models import SettingBoard
6 |
7 |
8 | def getWikiPermission():
9 | setting = SettingBoard.objects.filter(id=1)
10 | if len(setting) != 0:
11 | if setting[0].openwiki is False:
12 | return False
13 | else:
14 | return True
15 | else:
16 | return False
17 |
18 | def getVisitorPermission(request):
19 | setting = SettingBoard.objects.filter(id=1)
20 | if len(setting) != 0:
21 | if setting[0].openvisitor is False:
22 | userid = request.session.get('user_id', None)
23 | if userid:
24 | return True
25 | else:
26 | return False
27 | else:
28 | return True
29 | else:
30 | return True
31 |
32 | class UserOnly(permissions.BasePermission):
33 | def has_permission(self, request, view):
34 | if getVisitorPermission(request) == False:
35 | return False
36 |
37 | if getWikiPermission() == False:
38 | return False
39 |
40 | if request.method == "DELETE":
41 | return True
42 | if request.method == "GET":
43 | return False
44 | else:
45 | data = request.data
46 | username = str(data.get('user'))
47 | userid = request.session.get('user_id', None)
48 | if userid == username:
49 | return True
50 | else:
51 | return False
52 |
53 | def has_object_permission(self, request, view, item):
54 | if getVisitorPermission(request) == False:
55 | return False
56 |
57 | if getWikiPermission() == False:
58 | return False
59 |
60 | if request.method == "GET":
61 | return False
62 | else:
63 | username = str(item.user.username)
64 | userid = request.session.get('user_id', None)
65 | if userid == username:
66 | return True
67 | else:
68 | return False
69 |
70 |
--------------------------------------------------------------------------------
/Backend/item/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import Item
4 |
5 | class ItemSerializer(serializers.ModelSerializer):
6 |
7 | class Meta:
8 | model = Item
9 | fields = '__all__'
10 |
11 |
--------------------------------------------------------------------------------
/Backend/item/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('putitem', views.ItemPutView)
8 |
9 | urlpatterns = [
10 | url('', include(routers.urls)),
11 | url(r'^item', views.ItemGetAPIView.as_view()),
12 | ]
13 |
--------------------------------------------------------------------------------
/Backend/item/views.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django_filters.rest_framework import DjangoFilterBackend
3 | from django.contrib.auth.hashers import make_password, check_password
4 | from rest_framework import viewsets,filters,generics,mixins
5 | from rest_framework.permissions import AllowAny
6 | from rest_framework.response import Response
7 | from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
8 | from rest_framework.views import APIView
9 | from rest_framework.pagination import LimitOffsetPagination
10 | from rest_framework.throttling import ScopedRateThrottle
11 | from .models import Item
12 | from .serializers import ItemSerializer
13 | from .permission import UserOnly
14 | from board.models import SettingBoard
15 |
16 |
17 | def getWikiPermission():
18 | setting = SettingBoard.objects.filter(id=1)
19 | if len(setting) != 0:
20 | if setting[0].openwiki is False:
21 | return False
22 | else:
23 | return True
24 | else:
25 | return False
26 |
27 | class ItemPutView(viewsets.ModelViewSet):
28 | queryset = Item.objects.all()
29 | serializer_class = ItemSerializer
30 | permission_classes = (UserOnly,)
31 |
32 | class ItemGetAPIView(generics.GenericAPIView):
33 | queryset = Item.objects.all()
34 | serializer_class = ItemSerializer
35 | permission_classes = (AllowAny,)
36 |
37 | def get(self, request, format=None):
38 | if getWikiPermission() == False:
39 | return Response("not open!", HTTP_400_BAD_REQUEST)
40 | username = request.session.get('user_id', None)
41 | user = Item.objects.filter(user=username)
42 | serializer = ItemSerializer(user, many=True)
43 | return Response(serializer.data, HTTP_200_OK)
44 |
--------------------------------------------------------------------------------
/Backend/judgestatus/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/judgestatus/__init__.py
--------------------------------------------------------------------------------
/Backend/judgestatus/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/judgestatus/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/judgestatus/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from django.db import models
4 |
5 |
6 | class JudgeStatus(models.Model):
7 |
8 | user = models.CharField(max_length=50)
9 | oj = models.CharField(max_length=50, default="LPOJ")
10 | problem = models.CharField(max_length=50)
11 | result = models.IntegerField()
12 | time = models.IntegerField()
13 | memory = models.IntegerField()
14 | length = models.IntegerField()
15 | language = models.CharField(max_length=50)
16 | submittime = models.DateTimeField()
17 | judger = models.CharField(max_length=50)
18 | contest = models.IntegerField()
19 | contestproblem = models.IntegerField(default=-1) # 对应比赛里的哪一题
20 | code = models.TextField(max_length=200000)
21 | testcase = models.CharField(max_length=50, default="0")
22 | message = models.TextField() # 也作为 其他OJ 的 proid
23 | problemtitle = models.CharField(max_length=100, default="")
24 | rating = models.IntegerField(default=1500)
25 | ip = models.CharField(max_length=50, default="无法获取ip")
26 |
27 | objects = models.Manager()
28 |
29 | def __str__(self):
30 | return self.user
31 |
32 |
33 | class CaseStatus(models.Model):
34 |
35 | statusid = models.IntegerField()
36 | username = models.CharField(max_length=50)
37 | problem = models.CharField(max_length=50)
38 | result = models.CharField(max_length=500, default="System Error")
39 | time = models.IntegerField(default=0)
40 | memory = models.IntegerField(default=0)
41 | testcase = models.CharField(max_length=500, default="unknow")
42 | casedata = models.CharField(max_length=500) # 非比赛才能查看,Judger中控制
43 | outputdata = models.CharField(
44 | max_length=500, default="") # 非比赛才能查看,Judger中控制
45 | useroutput = models.CharField(
46 | max_length=500, default="") # 非比赛才能查看,Judger中控制
47 |
48 | objects = models.Manager()
49 |
50 | def __str__(self):
51 | return self.statusid
52 |
--------------------------------------------------------------------------------
/Backend/judgestatus/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from rest_framework import serializers
4 | from .models import JudgeStatus, CaseStatus
5 |
6 |
7 | class JudgeStatusSerializer(serializers.ModelSerializer):
8 | class Meta:
9 | model = JudgeStatus
10 | exclude = ['code', 'message']
11 |
12 |
13 | class JudgeStatusCodeSerializer(serializers.ModelSerializer):
14 | class Meta:
15 | model = JudgeStatus
16 | fields = '__all__'
17 |
18 |
19 | class CaseStatusSerializer(serializers.ModelSerializer):
20 | class Meta:
21 | model = CaseStatus
22 | fields = '__all__'
23 |
--------------------------------------------------------------------------------
/Backend/judgestatus/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('judgestatus', views.JudgeStatusView)
8 | routers.register('judgestatusput', views.JudgeStatusPutView)
9 | routers.register('judgestatuscode', views.JudgeStatusCodeView)
10 | routers.register('casestatus', views.CaseStatusView)
11 | routers.register('acrank', views.ACRankView)
12 |
13 | urlpatterns = [
14 | url('', include(routers.urls)),
15 | url(r'^rejudge', views.RejudgeAPIView.as_view()),
16 | ]
17 |
--------------------------------------------------------------------------------
/Backend/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Backend.settings")
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError:
10 | # The above import may fail for some other reason. Ensure that the
11 | # issue is really that Django is missing to avoid masking other
12 | # exceptions on Python 2.
13 | try:
14 | import django
15 | except ImportError:
16 | raise ImportError(
17 | "Couldn't import Django. Are you sure it's installed and "
18 | "available on your PYTHONPATH environment variable? Did you "
19 | "forget to activate a virtual environment?"
20 | )
21 | raise
22 | execute_from_command_line(sys.argv)
23 |
--------------------------------------------------------------------------------
/Backend/problem/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/problem/__init__.py
--------------------------------------------------------------------------------
/Backend/problem/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/problem/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/problem/permission.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from rest_framework import permissions
3 |
4 | from board.models import SettingBoard
5 |
6 | def getVisitorPermission(request):
7 | setting = SettingBoard.objects.filter(id=1)
8 | if len(setting) != 0:
9 | if setting[0].openvisitor is False:
10 | userid = request.session.get('user_id', None)
11 | if userid:
12 | return True
13 | else:
14 | return False
15 | else:
16 | return True
17 | else:
18 | return True
19 |
20 | class ManagerOnly(permissions.BasePermission):
21 | def has_permission(self, request, view):
22 | if getVisitorPermission(request) == False:
23 | return False
24 | if request.method in permissions.SAFE_METHODS:
25 | return True
26 |
27 | type = request.session.get('type', 1)
28 | if type == 2 or type == 3:
29 | return True
30 | else:
31 | return False
32 |
33 |
34 | class AuthOnly(permissions.BasePermission):
35 | def has_permission(self, request, view):
36 | if getVisitorPermission(request) == False:
37 | return False
38 | if request.method in permissions.SAFE_METHODS:
39 | return True
40 | type = request.session.get('type', 1)
41 | if type == 2 or type == 3:
42 | return True
43 | else:
44 | return False
45 |
46 | def has_object_permission(self, request, view, problem):
47 | if getVisitorPermission(request) == False:
48 | return False
49 | type = request.session.get('type', 1)
50 | if type == 2 or type == 3:
51 | return True
52 | return problem.auth == 1 or problem.auth == 3
53 |
--------------------------------------------------------------------------------
/Backend/problem/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import Problem, ProblemData, ProblemTag,ChoiceProblem
4 |
5 |
6 | class ProblemSerializer(serializers.ModelSerializer):
7 | class Meta:
8 | model = Problem
9 | fields = '__all__'
10 |
11 | class ChoiceProblemSerializer(serializers.ModelSerializer):
12 | class Meta:
13 | model = ChoiceProblem
14 | fields = '__all__'
15 |
16 |
17 | class ProblemDataSerializer(serializers.ModelSerializer):
18 | class Meta:
19 | model = ProblemData
20 | fields = '__all__'
21 |
22 |
23 | class ProblemTagSerializer(serializers.ModelSerializer):
24 | class Meta:
25 | model = ProblemTag
26 | fields = '__all__'
27 |
28 |
--------------------------------------------------------------------------------
/Backend/problem/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('problem', views.ProblemView)
8 | routers.register('problemdata', views.ProblemDataView)
9 | routers.register('problemtag', views.ProblemTagView)
10 | routers.register('choiceproblem', views.ChoiceProblemView)
11 |
12 | urlpatterns = [
13 | url('', include(routers.urls)),
14 | url(r'^uploadfile', views.UploadFileAPIView.as_view()),
15 | url(r'^downloadfile/',views.filedown,name='download'),
16 | url(r'^showpic/',views.showpic,name='show_picture'),
17 | url(r'^judgerdownloadfile/',views.judgerfiledown,name='judgerfiledown'),
18 | url(r'^judgerfiletime/',views.judgerfiletime,name='judgerfiletime'),
19 | ]
20 |
--------------------------------------------------------------------------------
/Backend/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==2.2.8
2 | djangorestframework==3.9.3
3 | django-filter==2.1.0
4 | django-cors-headers==2.5.3
5 | mysqlclient==1.4.2.post1
6 | django-sslserver
7 | gevent
8 | gunicorn==19.9.0
--------------------------------------------------------------------------------
/Backend/user/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/user/__init__.py
--------------------------------------------------------------------------------
/Backend/user/admin.py:
--------------------------------------------------------------------------------
1 | from __future__ import unicode_literals
2 |
3 | from django.contrib import admin
4 | from .models import User,UserData
5 |
6 | admin.site.register(User)
7 | admin.site.register(UserData)
--------------------------------------------------------------------------------
/Backend/user/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/user/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/user/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.db import models
3 | class User(models.Model):
4 | username = models.CharField(max_length=50, null=False, primary_key=True)
5 | password = models.CharField(max_length=50, null=False)
6 | name = models.CharField(max_length=50, null=False) # 名称
7 | regtime = models.DateTimeField(auto_now=True)
8 | logintime = models.DateTimeField(auto_now=True)
9 | school = models.CharField(max_length=50, null=False, default="")
10 | course = models.CharField(max_length=50, null=False, default="")
11 | classes = models.CharField(max_length=50, null=False, default="") #行政班
12 | number = models.CharField(max_length=50, null=False, default="")
13 | realname = models.CharField(max_length=50, null=False)
14 | qq = models.CharField(max_length=50, null=True, default="")
15 | email = models.CharField(max_length=50, null=True, default="")
16 | type = models.IntegerField(null=False, default=1) # 1 普通 2 管理员 3 超级管理员
17 |
18 | objects = models.Manager()
19 |
20 | def __str__(self):
21 | return self.username
22 |
23 |
24 | class UserData(models.Model):
25 | username = models.CharField(max_length=50, null=False, primary_key=True)
26 | ac = models.IntegerField(null=False, default=0)
27 | submit = models.IntegerField(null=False, default=0)
28 | score = models.IntegerField(default=0)
29 | des = models.CharField(max_length=50, null=True)
30 | rating = models.IntegerField(default=1500)
31 | acpro = models.TextField(null=True, default="")
32 |
33 | objects = models.Manager()
34 |
35 | def __str__(self):
36 | return self.username
37 |
38 | class UserLoginData(models.Model):
39 | username = models.CharField(max_length=50, null=False)
40 | ip = models.CharField(max_length=50, null=True,default="unknow")
41 | logintime = models.DateTimeField(auto_now=True)
42 | msg = models.TextField(null=True)
43 |
44 | objects = models.Manager()
45 |
46 | def __str__(self):
47 | return self.username
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Backend/user/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import User, UserData, UserLoginData
4 |
5 | class UserLoginDataSerializer(serializers.ModelSerializer):
6 | class Meta:
7 | model = UserLoginData
8 | fields = '__all__'
9 |
10 | class UserSerializer(serializers.ModelSerializer):
11 | class Meta:
12 | model = User
13 | fields = '__all__'
14 |
15 |
16 | class UserNoPassSerializer(serializers.ModelSerializer):
17 | class Meta:
18 | model = User
19 | exclude = ['password']
20 |
21 |
22 | class UserNoTypeSerializer(serializers.ModelSerializer):
23 | class Meta:
24 | model = User
25 | exclude = ['type']
26 |
27 |
28 | class UserDataSerializer(serializers.ModelSerializer):
29 | class Meta:
30 | model = UserData
31 | fields = '__all__'
32 |
--------------------------------------------------------------------------------
/Backend/user/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('userdata', views.UserDataView)
8 | routers.register('user', views.UserView)
9 | #routers.register('change', views.UserChangeView)
10 | #routers.register('changeall', views.UserChangeAllView)
11 | routers.register('userlogindata', views.UserLoginDataView)
12 |
13 | urlpatterns = [
14 | url('', include(routers.urls)),
15 | url(r'^register', views.UserRegisterAPIView.as_view()),
16 | url(r'^login', views.UserLoginAPIView.as_view()),
17 | url(r'^logout', views.UserLogoutAPIView.as_view()),
18 | url(r'^updaterating', views.UserUpdateRatingAPIView.as_view()),
19 | url(r'^setlogindata', views.UserLoginDataAPIView.as_view()),
20 | url(r'^changeone', views.UserChangeView.as_view()),
21 | url(r'^changeall', views.UserChangeAllView.as_view()),
22 | ]
23 |
--------------------------------------------------------------------------------
/Backend/wiki/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/wiki/__init__.py
--------------------------------------------------------------------------------
/Backend/wiki/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Backend/wiki/migrations/__init__.py
--------------------------------------------------------------------------------
/Backend/wiki/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 |
4 | class Wiki(models.Model):
5 |
6 | username = models.CharField(max_length=50, default="std") # 发布人的用户名
7 | type = models.CharField(max_length=50) # 发布了哪篇文章
8 | value = models.TextField(default="暂无文本")
9 | time = models.DateTimeField(auto_now=True)
10 | group = models.CharField(max_length=50, null=True, default="") # 新添加的算法的分类
11 | std = models.IntegerField(default=0) # 是否是标准算法,0代表是,1代表新添加的算法
12 | title = models.CharField(max_length=50, null=True, default="") # 新添加的算法标题
13 |
14 | objects = models.Manager()
15 |
16 | def __str__(self):
17 | return self.username
18 |
19 |
20 | class MBCode(models.Model):
21 |
22 | username = models.CharField(
23 | max_length=50, default="std", primary_key=True) # 发布人的用户名
24 | des = models.CharField(max_length=500)
25 | time = models.DateTimeField(auto_now=True)
26 |
27 | objects = models.Manager()
28 |
29 | def __str__(self):
30 | return self.username
31 |
32 |
33 | class MBCodeDetail(models.Model):
34 |
35 | username = models.CharField(max_length=50, default="std") # 发布人的用户名
36 | title = models.CharField(max_length=50)
37 | des = models.CharField(max_length=1000, default="none")
38 | group = models.CharField(max_length=50, default="none")
39 | code = models.TextField(default="暂无代码")
40 | time = models.DateTimeField(auto_now=True)
41 |
42 | objects = models.Manager()
43 |
44 | def __str__(self):
45 | return self.username
46 |
47 |
48 | class TrainningContest(models.Model):
49 |
50 | title = models.CharField(max_length=50) # 标题
51 | des = models.CharField(max_length=500)
52 | tips = models.CharField(max_length=500, null=True,
53 | blank=True, default="") # 教程 | 隔开
54 | group = models.IntegerField() # 第几章
55 | num = models.IntegerField() # 第几关
56 | problem = models.CharField(
57 | max_length=500, null=True, blank=True, default="") # 题目 | 隔开
58 |
59 | objects = models.Manager()
60 |
61 | def __str__(self):
62 | return self.title
63 |
--------------------------------------------------------------------------------
/Backend/wiki/serializers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from rest_framework import serializers
3 | from .models import Wiki, MBCode, MBCodeDetail, TrainningContest
4 |
5 |
6 | class WikiSerializer(serializers.ModelSerializer):
7 | class Meta:
8 | model = Wiki
9 | fields = '__all__'
10 |
11 |
12 | class WikiCountSerializer(serializers.ModelSerializer):
13 | class Meta:
14 | model = Wiki
15 | exclude = ['value']
16 |
17 |
18 | class MBCodeSerializer(serializers.ModelSerializer):
19 | class Meta:
20 | model = MBCode
21 | fields = '__all__'
22 |
23 |
24 | class MBCodeDetailSerializer(serializers.ModelSerializer):
25 | class Meta:
26 | model = MBCodeDetail
27 | fields = '__all__'
28 |
29 |
30 | class MBCodeDetailNoCodeSerializer(serializers.ModelSerializer):
31 | class Meta:
32 | model = MBCodeDetail
33 | exclude = ['code']
34 |
35 |
36 | class TrainningContestSerializer(serializers.ModelSerializer):
37 | class Meta:
38 | model = TrainningContest
39 | fields = '__all__'
40 |
--------------------------------------------------------------------------------
/Backend/wiki/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.conf.urls import url, include
3 | from . import views
4 | from rest_framework import routers
5 |
6 | routers = routers.DefaultRouter()
7 | routers.register('wiki', views.WikiView)
8 | routers.register('wikicount', views.WikiCountView)
9 | routers.register('mbcode', views.MBCodeView)
10 | routers.register('mbcodedetail', views.MBCodeDetailView)
11 | routers.register('mbcodedetailnocode', views.MBCodeDetailNoCodeView)
12 | routers.register('trainning', views.TrainningContestView)
13 |
14 | urlpatterns = [
15 | url('', include(routers.urls)),
16 | ]
17 |
--------------------------------------------------------------------------------
/Backend/wiki/views.py:
--------------------------------------------------------------------------------
1 | from rest_framework.throttling import ScopedRateThrottle
2 | from rest_framework import viewsets
3 | from .serializers import TrainningContestSerializer, WikiSerializer, WikiCountSerializer, MBCodeSerializer, MBCodeDetailSerializer, MBCodeDetailNoCodeSerializer
4 | from .permission import UserOnly, ManagerOnly, WikiUserOnly
5 | from .models import Wiki, MBCode, MBCodeDetail, TrainningContest
6 |
7 |
8 | class WikiView(viewsets.ModelViewSet):
9 | queryset = Wiki.objects.all()
10 | serializer_class = WikiSerializer
11 | filter_fields = ('username', 'type', 'group', 'std',)
12 | permission_classes = (WikiUserOnly,)
13 | throttle_scope = "post"
14 | throttle_classes = [ScopedRateThrottle, ]
15 |
16 |
17 | class WikiCountView(viewsets.ModelViewSet):
18 | queryset = Wiki.objects.all()
19 | serializer_class = WikiCountSerializer
20 | filter_fields = ('username', 'type')
21 | permission_classes = (UserOnly,)
22 | throttle_scope = "post"
23 | throttle_classes = [ScopedRateThrottle, ]
24 |
25 |
26 | class MBCodeView(viewsets.ModelViewSet):
27 | queryset = MBCode.objects.all()
28 | serializer_class = MBCodeSerializer
29 | filter_fields = ('username',)
30 | permission_classes = (UserOnly,)
31 | throttle_scope = "post"
32 | throttle_classes = [ScopedRateThrottle, ]
33 |
34 |
35 | class MBCodeDetailView(viewsets.ModelViewSet):
36 | queryset = MBCodeDetail.objects.all()
37 | serializer_class = MBCodeDetailSerializer
38 | filter_fields = ('username', 'group', 'des', 'title')
39 | permission_classes = (UserOnly,)
40 | throttle_scope = "post"
41 | throttle_classes = [ScopedRateThrottle, ]
42 |
43 |
44 | class MBCodeDetailNoCodeView(viewsets.ModelViewSet):
45 | queryset = MBCodeDetail.objects.all()
46 | serializer_class = MBCodeDetailNoCodeSerializer
47 | filter_fields = ('username', 'group', 'des', 'title')
48 | permission_classes = (UserOnly,)
49 | throttle_scope = "post"
50 | throttle_classes = [ScopedRateThrottle, ]
51 |
52 |
53 | class TrainningContestView(viewsets.ModelViewSet):
54 | queryset = TrainningContest.objects.all().order_by("num")
55 | serializer_class = TrainningContestSerializer
56 | filter_fields = ('group', 'title',)
57 | permission_classes = (ManagerOnly,)
58 | throttle_scope = "post"
59 | throttle_classes = [ScopedRateThrottle, ]
60 |
--------------------------------------------------------------------------------
/CrawlingServer/CodeForceContestCounter.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import datetime
3 | import json
4 |
5 | # 返回一个月内的cf场数和上/掉分情况
6 | def get_CF_ContestCount(name):
7 | apiUrl = "https://codeforces.com/api/user.rating?handle=" + name
8 |
9 | try:
10 | page = urllib.request.urlopen(apiUrl, timeout=2000)
11 | s = page.read().decode('utf-8')
12 | contestsData = json.loads(s)['result']
13 |
14 | # 改为直接用rating变化的时间当做比赛时间
15 | # 由于rating变化时间一般延迟一天,放宽到32天
16 | lastTime=(datetime.timedelta(days=-32) +
17 | datetime.datetime.now()).timestamp()
18 |
19 | sum=0
20 | cnt=0
21 | for contest in contestsData:
22 | if contest['ratingUpdateTimeSeconds'] < lastTime:
23 | continue
24 | cnt += 1
25 | sum += contest['newRating'] - contest['oldRating']
26 | return [cnt, sum]
27 |
28 | except Exception as e:
29 | print(str(e))
30 | return [-1, -1]
31 |
32 | if __name__ == "__main__":
33 | while(True):
34 | name=input("请输入要爬的ID:")
35 | print(get_CF_ContestCount(name))
36 |
--------------------------------------------------------------------------------
/CrawlingServer/Codeforces.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import json
3 | def get_CF_data(name):
4 | api_url = "http://codeforces.com/api/user.status?handle="+name
5 | try:
6 | response = urllib.request.urlopen(api_url,timeout=2000)
7 | response_data=response.read()
8 |
9 | response_data = json.loads(response_data)
10 |
11 | # print(response_data)
12 | acpro = set()
13 | attpro = set()
14 |
15 | for data in response_data["result"]:
16 | if data["verdict"]=="OK":
17 | acpro.add(str(data["problem"]["contestId"])+str(data["problem"]["index"]))
18 | attpro.add(str(data["problem"]["contestId"])+str(data["problem"]["index"]))
19 | return [len(acpro),len(attpro)]
20 | except:
21 | return [-1,-1]
22 |
23 | if __name__ == "__main__":
24 | while(True):
25 | name = input("请输入要爬的ID:")
26 | print(get_CF_data(name))
--------------------------------------------------------------------------------
/CrawlingServer/CodeforcesRate.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import re
3 |
4 | def get_CF_Rate(name):
5 | api_url = "https://codeforces.com/profile/"+name
6 | try:
7 | response = urllib.request.urlopen(api_url,timeout=2000)
8 | response_data=response.read().decode('utf-8')
9 |
10 | score = re.findall('([0-9]{2,4})', response_data)[0]
11 | return score
12 | except:
13 | return -1
14 |
15 | if __name__ == "__main__":
16 | while(True):
17 | name = input("请输入要爬的ID:")
18 | print(get_CF_Rate(name))
19 |
--------------------------------------------------------------------------------
/CrawlingServer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7.2
2 | MAINTAINER linzecong
3 | ADD . ./CrawlingServer
4 | WORKDIR /CrawlingServer
5 | RUN pip install -r requirements.txt
6 | CMD ["python", "main.py"]
7 |
--------------------------------------------------------------------------------
/CrawlingServer/HDU.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import json
3 | def get_HDU_data(name):
4 | try:
5 | api_url = "http://acm.hdu.edu.cn/userstatus.php?user="+name
6 | response = urllib.request.urlopen(api_url,timeout=2000)
7 | response_data=response.read()
8 | response_data = str(response_data)
9 |
10 | ac = response_data[response_data.find("Problems Solved
")+len("Problems Solved | "):response_data.find(" | ",response_data.find("Problems Solved"))]
11 | submit =response_data[response_data.find("Problems Submitted | ")+len("Problems Submitted | "):response_data.find(" | ",response_data.find("Problems Submitted"))]
12 | return [int(ac),int(submit)]
13 | except:
14 | return [-1,-1]
15 |
16 | if __name__ == "__main__":
17 | while(True):
18 | name = input("请输入要爬的ID:")
19 | print(get_HDU_data(name))
--------------------------------------------------------------------------------
/CrawlingServer/LPOJ.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import json
3 | import urllib.parse
4 | import ssl
5 | ssl._create_default_https_context = ssl._create_unverified_context
6 |
7 |
8 | def get_LPOJ_data(name):
9 | if name == "":
10 | return [-1, -1]
11 |
12 | api_url = "https://www.lpoj.cn/api/userdata/?username=" + \
13 | urllib.parse.quote(name)
14 | try:
15 | response = urllib.request.urlopen(api_url, timeout=2000)
16 | response_data = response.read()
17 |
18 | response_data = json.loads(response_data)
19 | if len(response_data) == 0:
20 | return [-1, -1]
21 | for data in response_data:
22 | return [data["ac"], data["submit"]]
23 | except:
24 | return [-1, -1]
25 |
26 |
27 | if __name__ == "__main__":
28 | while(True):
29 | name = input("请输入要爬的ID:")
30 | print(get_LPOJ_data(name))
31 |
--------------------------------------------------------------------------------
/CrawlingServer/README.md:
--------------------------------------------------------------------------------
1 | # 爬虫机器人
2 |
3 | 主要用于爬取学生的博客和大OJ的做题数
4 |
5 | ## Docker部署
6 |
7 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
8 | ```
9 | cd CrawlingServer
10 | nano setting.json
11 | ```
12 | 接着运行容器
13 | ```
14 | docker build -t lpojcrawlingserver .
15 | docker run -d lpojcrawlingserver
16 | ```
17 |
18 | ## 一般部署
19 |
20 | ```
21 | cd CrawlingServer
22 | nano setting.json
23 | # 修改对应的数据库IP和端口保存退出
24 | pip install feedparser
25 | pip install mysqlclient
26 | sudo python main.py
27 | ```
--------------------------------------------------------------------------------
/CrawlingServer/Vjudge.py:
--------------------------------------------------------------------------------
1 | import urllib.request
2 | import urllib.parse
3 | import json
4 | import ssl
5 | ssl._create_default_https_context = ssl._create_unverified_context
6 |
7 | def get_VJ_data(name):
8 | try:
9 | api_url = "https://vjudge.net/user/"+name
10 | response = urllib.request.urlopen(api_url)
11 | response_data=response.read()
12 | response_data = str(response_data)
13 |
14 | ac = response_data[response_data.find("title=\"Overall solved\" target=\"_blank\">")+len("title=\"Overall solved\" target=\"_blank\">"):response_data.find("",response_data.find("title=\"Overall solved\" target=\"_blank\">"))]
15 | submit =response_data[response_data.find("title=\"Overall attempted\" target=\"_blank\">")+len("title=\"Overall attempted\" target=\"_blank\">"):response_data.find("",response_data.find("title=\"Overall attempted\" target=\"_blank\">"))]
16 | return [int(ac),int(submit)]
17 | except:
18 | return [-1,-1]
19 |
20 | if __name__ == "__main__":
21 | while(True):
22 | name = input("请输入要爬的ID:")
23 | print(get_VJ_data(name))
--------------------------------------------------------------------------------
/CrawlingServer/requirements.txt:
--------------------------------------------------------------------------------
1 | feedparser==5.2.1
2 | mysqlclient==1.4.2.post1
3 |
--------------------------------------------------------------------------------
/CrawlingServer/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_user":"root",
3 | "db_pass":"504603913",
4 | "db_ip":"localhost",
5 | "db_port":"3306",
6 | "db_database":"LPOJ"
7 | }
--------------------------------------------------------------------------------
/Database/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mysql:5.7
2 | MAINTAINER linzecong
3 | ENV AUTO_RUN_DIR /docker-entrypoint-initdb.d
4 | ENV INSTALL_DB_SQL init_database.sql
5 | COPY ./$INSTALL_DB_SQL $AUTO_RUN_DIR/
6 | EXPOSE 3306 33060
7 | RUN chmod a+x $AUTO_RUN_DIR/$INSTALL_DB_SQL
--------------------------------------------------------------------------------
/Database/README.md:
--------------------------------------------------------------------------------
1 | # 这里主要存放数据库文件
2 |
3 | 数据库初始脚本等
--------------------------------------------------------------------------------
/Database/conf/mysqld_safe_syslog.cnf:
--------------------------------------------------------------------------------
1 | [mysqld_safe]
2 | syslog
3 |
--------------------------------------------------------------------------------
/Database/init_database.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE LPOJ DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
2 | GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
3 | FLUSH PRIVILEGES;
4 | SET time_zone = '+8:00';
5 | FLUSH PRIVILEGES;
--------------------------------------------------------------------------------
/Docs/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | docs/.vuepress/dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/Docs/README.md:
--------------------------------------------------------------------------------
1 | # 文档文件夹
2 |
3 | # [docs.lpoj.cn](http://docs.lpoj.cn)
4 |
5 | npm run docs:dev
6 | npm run docs:build
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: 'LPOJ 文档',
3 | description: 'LPOJ 的开发与使用文档',
4 | head: [
5 | ['link', { rel: 'icon', href: '/img/favicon.ico' }],
6 | ],
7 | base: '/',
8 | markdown: {
9 | lineNumbers: true // 代码块显示行号
10 | },
11 | themeConfig: {
12 | sidebarDepth: 5,
13 | nav: [
14 | { text: 'Demo', link: 'https://www.lpoj.cn/' },
15 | { text: 'GitHub首页', link: 'https://github.com/Linzecong/LPOJ/' },
16 | { text: '作者首页', link: 'https://github.com/Linzecong/' },
17 | ],
18 |
19 | sidebar: [
20 | {
21 | title: '开始上手',
22 | collapsable: true,
23 | children: [
24 | '/faq/',
25 | '/faq/intro',
26 | '/faq/whatisoj',
27 | '/faq/systemstruct'
28 | ]
29 | },
30 | {
31 | title: '部署文档',
32 | collapsable: true,
33 | children: [
34 | '/deploy/',
35 | '/deploy/frontend',
36 | '/deploy/backend',
37 | '/deploy/judgeserver',
38 | '/deploy/judger',
39 | '/deploy/crawlingserver'
40 | ]
41 | },
42 | {
43 | title: '开发文档',
44 | collapsable: true,
45 | children: [
46 | '/dev/',
47 | '/dev/frontend',
48 | '/dev/backend',
49 | '/dev/judgerserver',
50 | '/dev/judger',
51 | ]
52 | },
53 | {
54 | title: '使用文档',
55 | collapsable: true,
56 | children: [
57 | '/doc/',
58 | '/doc/oj',
59 | '/doc/judger',
60 | '/doc/utils',
61 | '/doc/faq',
62 | ]
63 | },
64 | ]
65 |
66 |
67 | },
68 |
69 |
70 | }
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/donate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/donate.jpg
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/faq/db.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/faq/db.png
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/faq/db2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/faq/db2.png
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/faq/db3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/faq/db3.png
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/faq/db4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/faq/db4.png
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/favicon.ico
--------------------------------------------------------------------------------
/Docs/docs/.vuepress/public/img/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Docs/docs/.vuepress/public/img/logo.jpg
--------------------------------------------------------------------------------
/Docs/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /img/logo.jpg
4 | heroText: LPOJ 使用与开发文档
5 | tagline: 帮助你快速的了解LPOJ
6 | actionText: 快速了解
7 | actionLink: /faq/
8 | features:
9 | - title: 开源
10 | details: 一个开源的程序在线评测系统。
11 | - title: 高效
12 | details: 采用前后端分离,开发迅速。
13 | - title: 轻量级
14 | details: 使用最简单的技术开发,方便自定义修改
15 | footer: MIT Licensed | Copyright © 2020.05.13 Linzecong QQ群:875136693
16 | ---
--------------------------------------------------------------------------------
/Docs/docs/deploy/README.md:
--------------------------------------------------------------------------------
1 | # 环境说明
2 |
3 | 判题机需部署在Linux环境下!
4 |
5 | 我使用的环境是:
6 |
7 | + 前端: Ubuntu 18.10 + Nginx
8 | + 后端: Ubuntu 18.10 + Python 3.7
9 | + 判题服务器: Ubuntu 18.10 + Python 3.7
10 | + 判题机: Ubuntu 18.10 + Python 3.7 (必须Linux系统)
11 | + 爬虫部分: Ubuntu 18.10 + Python 3.7
12 |
13 | 整个OJ对系统要求不高。1G内存 1核的机器足以。但是部分题目需要大内存,所以推荐使用2G内存 1核的服务器。
14 |
15 | ## 准备部署
16 |
17 | 接下来所有操作,均在Ubuntu系统下进行,如果是其他系统,请自行百度对应的命令行语句
18 |
19 | 首先我们把代码clone下来,或者直接在Github上[下载](https://github.com/Linzecong/LPOJ/archive/master.zip)下来。
20 | 首先我们将代码解压到一个文件夹中(就用LPOJ作为名字吧!)
21 |
22 | ```
23 | mkdir LPOJ
24 | cd LPOJ
25 | git clone https://github.com/Linzecong/LPOJ.git
26 | ```
27 |
28 | 然后你就成功的把所有所需的文件下载下来了,接下来开始部署,具体看后面的教程。
29 |
30 | ## 使用Docker部署
31 |
32 | ### 环境准备
33 |
34 | ### 1. 安装必要的依赖
35 | ```
36 | sudo apt-get update
37 | sudo apt-get install -y git
38 | sudo apt install docker.io -y
39 | sudo apt install docker-compose -y
40 | ```
41 | ### 2. 开始安装
42 |
43 | ```
44 | git clone https://github.com/Linzecong/LPOJ.git && cd LPOJ
45 | ```
46 |
47 | **请修改docker-compose.yml中的数据库密码(所有的 DB_PASSWORD,MYSQL_ROOT_PASSWORD 字段)和一些你认为必要的设置**
48 |
49 |
50 | ```
51 | sudo docker-compose up -d --scale judger=3
52 | ```
53 |
54 | 以上命令默认开启3个判题机,可以自行修改数量
55 |
56 |
57 | 根据网速和配置情况,大约10到20分钟就可以自动搭建完成,全程无需人工干预。
58 |
59 | 等命令执行完成,然后运行 **sudo docker ps -a** 当看到所有的容器的状态均为 Up 就代表 OJ 已经启动成功。
60 |
61 | ### 3. 准备工作
62 |
63 | 1. 安装成功后,先通过IP:8080访问OJ,注册一个用户
64 |
65 | 2. 然后进入 IP:8000/admin 以用户名admin 密码admin 登录后台(请及时修改后台密码,这个后台作用仅用于修改管理员权限,因此没有样式)
66 |
67 | 3. 修改User表中,你注册的超级用户的type为3,使得你注册的用户变为超级管理员
68 |
69 | 4. 以管理员登录,右上角进入管理员页面,然后在网站设置标签,提交一次设置
70 |
71 | ### 4. 更新OJ
72 |
73 | 如要更新OJ只需在LPOJ目录下执行如下步骤
74 | ```
75 | git pull # 如果你修改了代码,自行解决merge得到情况
76 | sudo docker-compose stop
77 | sudo docker-compose pull
78 | sudo docker-compose up -d --scale judger=3
79 | ```
80 |
81 | **容器运行时产生的数据会保存在对应的文件夹中,如数据库文件,题目数据等**
82 |
83 | ## 一般安装
84 |
85 | 如果你想用传统的方法,感受自己一步步搭起一个OJ的快感,你可以阅读后面的教程。
86 | 但是相信我,你会回来用一键部署的。
87 |
88 | # 部署HTTPS
89 |
90 | [https://blog.csdn.net/lzc504603913/article/details/101357133](https://blog.csdn.net/lzc504603913/article/details/101357133)
91 |
--------------------------------------------------------------------------------
/Docs/docs/deploy/backend.md:
--------------------------------------------------------------------------------
1 | # 后端与数据库部署
2 |
3 |
4 | ### 部署数据库
5 |
6 | 首先安装Mysql数据库
7 |
8 | > 如果自己已经安装了数据库的,可以跳过本步骤
9 |
10 | ```
11 | sudo apt-get install mysql-server
12 | ```
13 | 然后新建数据库
14 | ```
15 | CREATE DATABASE LPOJ DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
16 | ```
17 | 如果要公网访问,可以执行以下数据库语句
18 | ```
19 | mysql -uroot -p
20 | mysql > USE mysql
21 | mysql > GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your_password' WITH GRANT OPTION;
22 | mysql > ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password by 'your_password';
23 | mysql > flush privileges;
24 | 然后修改配置文件(不同系统可能在不同地方)
25 | sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
26 | 修改bind-address 为 0.0.0.0
27 | ```
28 |
29 | ### 部署后端
30 |
31 | 按顺序安装Django,如已安装,可跳过
32 |
33 | 1. 首先安装Django
34 | ```
35 | pip install django
36 |
37 | pip install djangorestframework
38 |
39 | pip install django-filter
40 |
41 | sudo apt-get install python-django
42 |
43 | pip install django-cors-headers
44 | ```
45 | 2. 安装python数据库操作类
46 | ```
47 | pip install mysqlclient
48 | ```
49 |
50 | 3. 部署后端
51 | ```
52 | cd Backend
53 |
54 | cd Backend
55 |
56 | sudo nano setting.py
57 | ```
58 |
59 | **修改数据库配置为你自己的数据库IP端口和用户名密码**
60 |
61 | ```
62 | cd ..
63 |
64 | python manage.py makemigrations
65 |
66 | python manage.py makemigrations judgestatus item problem user contest board blog wiki classes &&
67 |
68 | python manage.py migrate
69 |
70 | echo "from django.contrib.auth.models import User; User.objects.filter(email=\"admin@example.com\").delete(); User.objects.create_superuser(\"admin\", \"admin@example.com\", \"admin\")" | python manage.py shell
71 |
72 | python manage.py runserver 0.0.0.0:8000
73 | ```
74 |
75 | ### 添加管理员
76 | > 安装成功后,先通过IP:80访问OJ,注册一个用户
77 | >
78 | > 然后进入 IP:8000/admin 以用户名admin 密码admin 登录后台(请及时修改后台密码)
79 | >
80 | > 修改User表中,你注册的超级用户的type为3,使得你注册的用户变为超级管理员
81 |
82 | ## Docker 部署
83 | 非专业用户不推荐使用Docker单独部署
84 | 修改Dockerfile中的ENV为你的数据库地址和密码等
85 | ```
86 | docker build -t lpojbackend .
87 | docker run -d -p 8000:8000 lpojbackend
88 | ```
--------------------------------------------------------------------------------
/Docs/docs/deploy/crawlingserver.md:
--------------------------------------------------------------------------------
1 | # 爬虫机器人部署
2 |
3 | 主要用于爬取学生的博客和大OJ的做题数
4 |
5 | ## 一般部署
6 |
7 | ```
8 | cd CrawlingServer
9 | nano setting.json
10 | # 修改对应的数据库IP和端口保存退出
11 | pip install feedparser
12 | pip install mysqlclient
13 | sudo python main.py
14 | ```
15 |
16 |
17 | ## Docker部署
18 |
19 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
20 | ```
21 | cd CrawlingServer
22 | nano setting.json
23 | ```
24 | 接着运行容器
25 | ```
26 | docker build -t lpojcrawlingserver .
27 | docker run -d lpojcrawlingserver
--------------------------------------------------------------------------------
/Docs/docs/deploy/frontend.md:
--------------------------------------------------------------------------------
1 | # 前端部署
2 |
3 | ## 一般部署
4 |
5 | 首先要先安装 npm ,具体安装教程,自行百度(要先安装node.js)
6 |
7 | 安装完毕后,依次执行以下命令(以LPOJ文件夹为根目录)
8 | 由于需要安装依赖,可能会话比较多的时间。
9 |
10 | ```
11 | cd Frontend
12 | npm install
13 | npm run build
14 | ```
15 |
16 | 等待npm编译前端,编译成功后可以在前端中的dist文件夹找到编译成功后的静态文件。接下来我们只要把那些文件,扔到Web服务器中即可。Web服务器随意,我这里使用的是Nginx,也推荐使用Nginx。首先让我们先安装Nginx
17 |
18 | ```
19 | sudo apt-get install nginx
20 | ```
21 | 这样就安装成功了
22 | 我们将编译成功的dist文件夹下的所有内容,拖到Nginx的默认网站根目录中(通常是/var/www/html)
23 |
24 | Win下推荐使用WinSCP进行拖放操作!
25 |
26 | 接下来我们要修改Nginx的配置文件(不同版本可能在不同的地方)
27 | ```
28 | sudo nano /etc/nginx/nginx.conf
29 | ```
30 |
31 | 主要修改如下几个配置
32 |
33 | 1. 路由重定向
34 | 2. API重定向
35 |
36 |
37 | 将如下配置复制到 **http{}** 中
38 | ```
39 | server{
40 | listen 80;
41 | server_name www.lpoj.cn; # 此处填写你的域名或IP
42 | root /var/www/html; # 此处填写你的网页根目录
43 | location /api { # 将API重定向到后台服务器(如果你修改了前端中的代理配置,这里需要对应的修改)
44 | rewrite ^.*api/?(.*)$ /$1 break;
45 | proxy_pass http://localhost:8000; # 填写你的后端地址和端口
46 | }
47 | location / { # 路由重定向以适应Vue中的路由
48 | index index.html;
49 | try_files $uri $uri/ /index.html;
50 | }
51 | }
52 | ```
53 |
54 | Nginx的配置多种多样,比如说开启Gzip支持等等,这些东西大家随意配置就好,具体的配置可以自行百度。
55 |
56 | 修改完后记得重启服务
57 | ```
58 | sudo systemctl restart nginx
59 | ```
60 |
61 | 如无意外,可以在浏览器中访问你的前端了。试一试localhost~
62 |
63 | ## Docker 部署
64 |
65 | 非专业用户不推荐使用Docker单独部署
66 | 首先修改default.conf中proxy_pass的地址为你的后端地址,如有需要,可以修改其他配置
67 |
68 | ```
69 | docker build -t lpojfrontend .
70 | docker run -d -p 80:80 lpojfrontend
71 | ```
--------------------------------------------------------------------------------
/Docs/docs/deploy/judger.md:
--------------------------------------------------------------------------------
1 | # 部署判题机
2 |
3 | 判题机支持多个且异地部署
4 |
5 | ## 一般部署
6 | 修改配置文件
7 | ```
8 | cd Judger
9 | nano setting.json
10 | ```
11 | 修改对应的数据库IP和端口,用户名和密码
12 |
13 | 修改server_ip为你的判题服务器的IP地址
14 |
15 | 如果你需要Python判题,那么请注意修改python_path
16 |
17 | 你可以使用 whereis python 命名查看python路径
18 |
19 | 需要数据库模块支持!如已安装可跳过
20 |
21 | ```
22 | pip install mysqlclient
23 | ```
24 | 安装依赖库
25 | ```
26 | sudo apt-get install libseccomp-dev
27 | mkdir build && cd build && cmake .. && make && sudo make install
28 | cd ..
29 | cd JudgerCore
30 | sudo python setup.py install
31 | cd ..
32 | pip install paramiko
33 | sudo apt install time
34 | ```
35 |
36 | 安装Java环境
37 | ```
38 | sudo apt install openjdk-8-jdk
39 | ```
40 |
41 |
42 | 最后运行
43 | ```
44 | sudo python main.py
45 | ```
46 |
47 | ## Docker 部署
48 |
49 | 非专业用户不推荐使用Docker单独部署
50 |
51 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
52 |
53 | ```
54 | cd Judger
55 | nano setting.json
56 | ```
57 | 接着运行容器
58 | ```
59 | docker build -t lpojjudger .
60 | docker run -d lpojjudger
61 | ```
--------------------------------------------------------------------------------
/Docs/docs/deploy/judgeserver.md:
--------------------------------------------------------------------------------
1 | # 部署判题服务器
2 |
3 | ## 一般部署
4 | 首先修改配置文件
5 | ```
6 | cd JudgeServer
7 | nano setting.json
8 | ```
9 | 修改对应的数据库IP和端口,用户名和密码保存退出
10 |
11 | 需要数据库模块支持!如已安装可跳过
12 |
13 | ```
14 | sudo apt-get install libmysqlclient-dev
15 |
16 | pip install mysqlclient
17 | ```
18 | 最后运行
19 | ```
20 | sudo python main.py
21 | ```
22 |
23 | ## Docker 部署
24 |
25 | 非专业用户不推荐使用Docker单独部署
26 |
27 | 首先修改配置文件,setting.json
28 | ```
29 | cd JudgerServer
30 | nano setting.json
31 | ```
32 | 接着运行容器
33 | ```
34 | docker build -t lpojjudgerserver .
35 | docker run -d -p 9906:9906 lpojjudgerserver
36 | ```
--------------------------------------------------------------------------------
/Docs/docs/dev/README.md:
--------------------------------------------------------------------------------
1 | # 开发入门
2 |
3 | 这个章节将会介绍整个OJ是如何开发起来的,方便大家二次开发
4 |
5 | 整个章节分为如下几个部分:
6 |
7 | + 前端开发
8 | + 后端开发
9 | + 判题服务器原理
10 | + 判题机原理
11 |
12 |
13 | 首先我们要做一下准备工作!下载源码和切换工作目录
14 |
15 | ```
16 | git clone https://github.com/Linzecong/LPOJ.git
17 | cd LPOJ
18 | ```
19 |
20 |
--------------------------------------------------------------------------------
/Docs/docs/dev/judgerserver.md:
--------------------------------------------------------------------------------
1 | # 判题服务器开发
2 |
3 | 判题服务器非常的简单,几乎无需做任何修改。采用TCP技术来通知判题机。
4 |
5 | ## 架构详解
6 | 测评模块仅提供了安全稳定的程序运行稳定,但是并不能判断程序是否通过,因此还要自己完成许多的逻辑工作。本系统的测评模块分为两部分,一部分是测评服务器,负责分发测评任务,另一部分是测评机,负责运行程序和提交测评结果。程序在运行过程中难免会消耗系统资源,如果只有一个判题程序在判题,如果判题时间较长,会导致后面的题目无法得到及时的反馈,但是如果太多判题程序同时运行,会导致系统资源消耗过大,导致前端和后台系统可能无法正确运行,所以要设计一个能够在多个机器上运行的判题程序,实现均衡负载功能,因此本OJ测评模块示意图如下:
7 |
8 | 
9 |
10 | 利用了数据库的事务管理,可使得高并发得以实现。用户相当于生产者,不断地向数据库提交待测评列表,测评服务器相当于一个消费者,不断的从数据库中获取未判提交列表,然后将这些题目分发到准备就绪的判题机,判题机收到判题任务后会进入忙状态,此时判题服务器不再向该判题机发送判题任务。当判题机判题完毕,会告诉服务器,可以继续判题。服务器再将该判题机纳入空闲列表。这样我们就能实现多个判题机同时运行,且这些判题机可以在任意的机器上运行,只需要通过TCP协议,链接到服务器上即可。同时服务器被设计成多线程的形式,在通过资源锁去控制并发的资源访问,使得多个判题程序能同时判题。 测评服务器,测评服务器使用Python开发,运行时会循环监听9906端口,一旦有测评机连上服务器,会新建一个线程,专门处理该测评机的消息。该线程首先会向测评机发送getstatus信息,测评机收到消息后会向服务器发送ok信号,代表已准备好判题。此时服务器会将该测评机纳入空闲列表。然后不断地循环发送getstatus信号,如果是not ok,代表非空闲状态,会将该测评机纳入非空闲列表。同时会有一个线程专门负责向数据库获取未判题列表,然后将未判题发放给空闲的判题机进行判题。
11 |
12 |
13 | ## 额外功能
14 |
15 | 由于历史原因和出于安全性的考虑,需要通过额外的程序来实现将比赛中的题目的权限设置为**可访问**,即将比赛中的题目访问权限设置为**私密**,这里将这个功能集成到了判题服务器的代码里。实际上这一部分可以独立出来运行。
16 |
17 |
18 | ## 源码解析
19 |
20 | 大概原理是这样的,这个判题服务器充当一个网关的功能,由他来拉取需要判题的列表,然后发送给各个服务器。这个判题服务器直接跟数据库进行通讯(直接把数据库当做中间件来用,比较方便)。用轮训的方式,不断地从数据库获取未判题列表,然后发送给各个判题机。当有判题机连入时,自动起一个线程来处理判题机的消息。判题机会不断地发送心跳包给判题服务器。
21 |
22 | 我真的写不动注释了!!!
23 |
24 | [main.py](https://github.com/Linzecong/LPOJ/blob/master/JudgerServer/main.py)
25 |
26 | [HDUVjudge.py](https://github.com/Linzecong/LPOJ/blob/master/Judger/VJudge/HDUVjudge.py)
--------------------------------------------------------------------------------
/Docs/docs/doc/README.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 本章只要介绍整个OJ的使用,和一些常见问题!
4 |
5 | 很多东西可能说不清楚,有问题可以在群里问!
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Docs/docs/doc/faq.md:
--------------------------------------------------------------------------------
1 |
2 | # OJ常见问题
3 |
4 | ## 不想使用HTTP下载文件
5 |
6 | 如果你不想使用HTTP咋办?
7 |
8 | 因为有的服务器不支持或者觉得不安全!
9 |
10 | 那么你可以修改docker-comopse.yml中的 NO_DOWNLOAD 为yes,
11 |
12 | yes则不使用HTTP
13 |
14 |
15 | 但是你就需要手动将数据压缩包放到Judger/ProblemData中
16 |
17 | 注意!!每一个判题机所以在的服务器都要放!这样就不能分布式判题了~!因为每次更改数据文件,都需要对每一个判题机的数据进行更新。当然,如果你只有一个判题机,那还是很方便的
18 |
19 | 这里可用Rsync服务优化!但是作者真的太懒了!
20 |
21 | ## OJ判题安全吗?
22 |
23 | 使用的都是青岛大学提供的沙箱!这个要问他们了~!
24 |
25 | ## 添加题目失败
26 |
27 | 可能是数据库不一致导致的!自行进入数据库,检查problem_problem表和problem_peoblemdata表的题目数据是否一致!
28 |
29 | 目前这个bug已经修复,但是仍有触发的可能~
30 |
31 | 如果真的遇到,可以加群咨询
32 |
33 | ## 注册提示已注册,但是登录不了
34 |
35 | 可能是数据库不一致导致的!自行进入数据库,检查user_user表和user_userdata表的用户数据是否一致!
36 |
37 | 目前这个bug已经修复,但是仍有触发的可能~
38 |
39 | 如果真的遇到,可以加群咨询
40 |
41 |
42 | ## 支持封榜吗?
43 |
44 | 准备支持了!!
45 |
46 |
47 | ## 提交数据卡住怎么办
48 |
49 | 在浏览器按F12,刷新页面,然后重新提交,看看报什么错误
50 |
51 | 一般来说不会卡住,如果一直上传失败,可以自行把数据文件放到后台的数据文件夹中
52 |
53 | /Backend/ProblemData 中
54 |
55 | 限500M大小,太大了请减少体积
56 |
57 | ## 测评机卡住了怎么办
58 |
59 | 一般不会卡住!
60 |
61 | 检查是不是数据太多的原因!
62 |
63 | 如果开启了OI模式,会对所有样例都判一次。假如你设置5S超时,刚好有个人提交一份超时的代码。假设你有100组数据。那么你就要跑500S!!!!所以要精简数据量,或者在比赛中关闭OI模式
64 |
65 | 如果使用Docker部署的话,崩了会自动重启的
66 |
67 | ## OJ太慢了怎么办?
68 |
69 | 后台是异步多进程多线程的!如果是数据库太慢,请使用自己的数据库,自行修改数据库地址等!
70 |
71 | 或者加大设备!在不同设备上跑Judger
72 |
73 | ## 我想独立部署多个Judger怎么办
74 |
75 | 把docker-compose.yml文件中除judger以外的内容全部删除。
76 |
77 | 然后修改各种参数即可
78 |
79 | 如可参考如下
80 |
81 | ```yml
82 | version: '2'
83 | services:
84 |
85 | judger:
86 | image: ccr.ccs.tencentyun.com/lpoj/judger
87 | command: >
88 | /bin/bash -c '
89 | sleep 65 ;
90 | python3 main.py
91 | '
92 |
93 | environment:
94 | DB_PASSWORD: "123456" # 必须修改!!
95 | DB_HOST: "111.111.111.111" # 必须修改!!
96 | DB_USER: 'root' # 必须修改!!
97 | DB_PORT: 3306 # 必须修改!!
98 |
99 | SERVER_IP: "111.111.111.112" # 必须修改!!
100 | BACKEND_PORT: 8000
101 | BACKEND_IP: "localhost" # 必须修改,不能写127.0.0.1或localhost,必须写你的局域网地址或者公网地址
102 | BACKEND_HEAD: 'http' # 如果你用了https,请改为https
103 |
104 | NO_DOWNLOAD: "no" # 设为yes,则不使用http,需要手动将数据压缩包放到Judger/ProblemData中
105 |
106 | restart: always
107 | volumes:
108 | - "./Judger/ProblemData:/Judger/ProblemData"
109 |
110 | ```
111 |
112 |
113 | ## 前端加载太慢怎么办
114 |
115 | 自行优化!我已经优化不动了!
116 |
117 | 或者使用CDN
118 |
119 | 自己申请域名
120 |
121 | 自己做个代理转发
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/Docs/docs/doc/utils.md:
--------------------------------------------------------------------------------
1 | # 其他工具
2 |
3 | ## CrawlingServer
4 |
5 | 在管理员页面设置好爬虫信息后,可以启动爬虫机器人进行爬虫。
6 | 主要可以爬取的信息是 各OJ做题数,博客,和近期比赛列表
7 |
8 | ### 启动
9 |
10 | ```bash
11 | python main.py
12 | ```
13 | ### 源码解析
14 |
15 | [main.py](https://github.com/Linzecong/LPOJ/blob/master/CrawlingServer/main.py)
16 |
17 |
18 | ## Tools
19 |
20 | 这个文件夹中,包含了各种实用的工具!
21 |
22 |
23 | ### 查重脚本 duplication_checking.py
24 |
25 | 此脚本基于SIM工具查重
26 |
27 |
28 | 自行查看攻略! https://dickgrune.com/Programs/similarity_tester/
29 |
30 | 修改其中的数据库信息
31 | ```py
32 | db = MySQLdb.connect(
33 | host="localhost", # 主机名
34 | user="root", # 数据库用户名
35 | passwd="", # 数据库密码
36 | db="LPOJ") # 数据库名称
37 | ```
38 | 用法
39 | ```py
40 | sudo python duplication_checking.py
41 | ```
42 | 脚本将会在脚本所在的目录下生成一个contest_duplication_checking的文件夹用于存放AC代码,子文件夹为contest_i分别存放了每一场比赛的AC代码,AC代码按用户名存放
43 |
44 |
45 | ### HDUSpider.py
46 |
47 | 用于爬取杭电题目数据并保存到数据库中!
48 |
49 | 你需要这只你的管理员的用户名和密码来登录!
50 |
51 | 运行时,记得正确设置题目的编号和杭电上题目的编号,看清楚源码再运行!
52 |
53 | ### RaiseCheck.py
54 |
55 | 这个脚本用于检查用户的代码有多少个raise
56 |
57 | 因为Python的话,可以用过爆破数据库来找到正确答案
58 |
59 | 通过这个脚本我们能找到爆破的用户,当然你也可以检查其他东西。代码很简单
60 |
61 | ### RatingCalculator.py
62 |
63 | 用于计算rated的比赛的rating 变化!
64 |
65 | 就是每次Rated比赛完毕后,需要手动的更新所有参加比赛的用户的Rating!
66 |
67 | 就要运行这个脚本!具体规则请看LPOJ首页的规则说明
68 |
69 | 你可以自己修改代码,来改变Rating的计算规则!
70 |
71 | ### RecoverBoard.py
72 |
73 | 排行榜恢复器!有时候由于网络原因,排行榜可能会记录失败!(低概率事件)
74 |
75 | 排查后,如果的确有用户的排行榜错了,可以用这个脚本重新生成整个排行榜
76 |
77 | 修改source_contest为你的比赛ID
78 |
79 | 然后运行~
80 |
81 | ### SubmitExport.py
82 |
83 | 这个脚本可以把用户提交的代码导出
84 |
85 | 由于数据量太大!因此直接通过读取文件的方式
86 |
87 | 在运行前,你需要将judgestatus_judgestatus表中的数据导出!(如果只导出某个比赛的,请自行筛选!)
88 |
89 | 导出成JSON格式!网上很多教程
90 |
91 | 然后保存为data.json文件。然后运行即可!
92 |
93 | 详见代码!
94 |
95 | ### UserImporter.py
96 |
97 | 代码原理很简单!就是自动提交api。自己看代码!
98 |
99 |
--------------------------------------------------------------------------------
/Docs/docs/faq/README.md:
--------------------------------------------------------------------------------
1 | # 引言
2 |
3 | ## 什么是LPOJ?
4 |
5 | LPOJ是一个由在校学生(现在已毕业)的学生自主开发的一个程序在线评测系统。
6 |
7 | ## 为什么要开发?
8 |
9 | 因为不开发,他毕不了业了。这是他的毕业设计。
10 |
11 | ## 你为什么要选择LPOJ
12 |
13 | 因为它使用的是最简单的技术。一天速成的Vue.js技术,和一天速成的Django REST framework技术。
14 |
15 | 理论上你只需要花两天时间,就能过看懂本OJ是怎么写出来的
16 |
17 | 使用的都是最简单的实现方法!没有高深的前后端知识!
18 |
19 | ## 文档最后更新于 **2020-5-13**
20 |
21 | 写文档太累了!!
22 |
23 | ## 打赏一下会写的更快吗?
24 |
25 | 那肯定了!赶紧微信赞赏一下吧!顺便备注里写一下鼓励语吧!个人开发实属不易!您的打赏将用于日常服务器的开支!服务器真的贵啊!
26 |
27 | 
28 |
29 |
30 | # 打赏人员名单
31 |
32 | **更新于2020-5-26**
33 |
34 | 感谢GWT20.00元
35 |
36 | 感谢Kurisu5.00元
37 |
38 | 感谢04G赞赏的20.00元
39 |
40 | 感谢0字节赞赏的20.00元
41 |
42 | 感谢Daniel赞赏的10.00元
43 |
44 | 感谢张顺赞赏的0.66元
45 |
46 | 感谢家煜赞赏的0.10元
47 |
48 | 感谢哈哈赞赏的5.00元
49 |
50 | 感谢陆嘉俊赞赏的6.66元
51 |
52 | 感谢膜大佬赞赏的10.00元
53 |
54 | 感谢甄英明赞赏的9.99元
55 |
56 | 感谢维度旅客赞赏的1.00元
57 |
58 | 感谢马涛赞赏的10.00元
59 |
60 | 感谢你的鼓励是我最大的动力!的10.00元
61 |
62 | 感谢Sebastian Lin赞赏的10.00元
63 |
64 | 感谢在下大名风大船赞赏的20.00元
65 |
66 | 感谢残阳赞赏的5.00元
67 |
68 | 感谢坚持.赞赏的5.20元
69 |
70 | 感谢曹岩奇赞赏的8.88元
71 |
72 | 感谢lww小粉丝赞赏的15.00元
73 |
74 | 感谢cineny赞赏的15.00元
75 |
76 | 感谢Hongrock赞赏的10.00元
77 |
--------------------------------------------------------------------------------
/Docs/docs/faq/whatisoj.md:
--------------------------------------------------------------------------------
1 | # 什么是OJ
2 |
3 | 以下摘自我的毕业论文
4 |
5 | ## 背景及研究意义
6 | 随着信息技术的发展,人们越来越注重基础的算法知识教学。现代企业中,人工智能无处不在,而人工智能又离不开算法,对于未来人才的培养,基础算法显得尤为重要。因此各大高校也越来越重视算法人才的培养。现在许多高校都有一套成熟的培养系统,比如杭州电子科技大学,北京大学,清华大学都有自己的判题系统。所谓判题系统,就是一个能对学生提交的程序进行自动判断的系统,这样不仅能省下老师许多时间,学生还能够自行的进行更多的训练,并从中学到更多的算法。一个好的判题系统不仅能进行判题,还能让学生随时随地的学习,即让判题程序以网页的形式呈现,只需要一个浏览器即可访问。同时还配套有一系列功能,如学生能迅速定位到自己的错误,并且能动态的看到自己的学习与锻炼情况等等。
7 |
8 | 上述判题系统我们称之为OJ,即Online Judge,中文名叫在线评测系统,目前在国内比较出名的在线评测系统有学校运营着的杭州电子科技大学的HDOJ,有北大的POJ,有浙江大学的ZOJ等等,同时也有企业运营着的PTA系统,计蒜客的判题系统,和企业面试常用的牛客网。这些均是国内出名的判题系统。在国外也有在全球出名的LeetCode网站,许多程序员在面试前都会上这个网站进行学习,同时还有由俄罗斯高校运营着的一个算法竞赛的做题网站Codeforces,还有日本的AtCoder等等。
9 |
10 |
11 | 虽然市面上有许许多多的OJ,但是OJ之间的题目数据并不共享,这就使得这些学习资源被垄断,因此一个属于学校本身的OJ就显得尤为重要。虽然在Github上有许多开源的OJ,最出名的如华中科技大学主持开源的HustOJ,有青岛大学主持的QDUOJ,但是要理解且修改当中的源码或者定制自己的功能显得尤为困难。所以学校要有自己的一个判题系统去培养算法人才。
12 |
13 | ## 算法竞赛介绍与OJ介绍
14 | 现代科技企业为了招到算法人才,会举办各种各样的算法竞赛去吸引人才。如百度每年都会举办百度之星,美团也会举办算法竞赛,同时在国际上,有由美国计算机协会(现在由JetBrain公司)支持举办的国际大学生程序设计竞赛,每年都会举办各国区域赛选拔顶尖算法人才去参加全球总决赛。在国内,也有中国大学生程序设计赛,也有各省的省赛。这些竞赛的目的都是为了培养各种各样的算法人才。
15 |
16 |
17 | 算法竞赛的形式非常简单,通常是在比赛的时候,每人或每只队伍使用一台电脑,然后需要在有限的5个小时内使用自己熟悉的编程语言写程序解决七个以上的问题。程序提交之后会给裁判或者在线的测评系统进行编译,然后运行,运行的结果会判定为正确或错误两种并及时通知各个参赛队。比赛形式非常的简单,但是却很非常紧张且具有挑战性。这些题目涵盖的领域非常广,包括数据结构,动态规划,图论,数论,运筹学,博弈论,概率论等等,而且通常需要学生编写非常严谨的程序,不容得一丝错误。
18 |
19 | 在实际工作当中,一个小小的漏洞都会给企业带来非常大的损失,所以一个长期参加算法竞赛的学生在工作中会展现出自身的优势,因此各大高校和企业也都非常重视算法竞赛的发展。但是要判断学生写的程序是否正确就需要一个能自动对学生程序进行判题的系统。这个系统会在数据库中存放各种题目数据,然后通过前端展示给学生,通常题目由:题目描述、输入描述、输出描述组成。学生需要编写一个程序去接收系统提供的输入数据,然后按照题目要求,对数据进行处理后,输出一个正确的答案。系统会将这个答案与后台的答案进行比较,如果相同,则代表学生的程序是正确的,错误则代表学生的程序有漏洞。通常系统会限制学生的程序要在一定时间内运行完毕,即程序的时间复杂度要在合理的范围内,同时空间复杂度也要在限定的范围内。因为在实际工作中效率非常重要。
20 |
21 | 同时程序在运行过程中不容得出现致命的系统错误,比如数组越界,除零等等。还有在比赛过程当中,由于集中提交,会有高并发的业务,因此一个系统要对上述所有情况作出判断且稳定的运行是非常困难的,这也是一个要攻克的难点。在本文后面会有提到如何解决。
22 |
--------------------------------------------------------------------------------
/Docs/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Docs",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1
5 | }
6 |
--------------------------------------------------------------------------------
/Docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Docs",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "docs:dev": "vuepress dev docs",
8 | "docs:build": "vuepress build docs"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC"
13 | }
14 |
--------------------------------------------------------------------------------
/Frontend/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "modules": false,
7 | "useBuiltIns": "entry"
8 | }
9 | ],
10 | "stage-3"
11 | ],
12 |
13 | "plugins": [
14 | ["import", {
15 | "libraryName": "muse-ui",
16 | "libraryDirectory": "lib",
17 | "camel2DashComponentName": false
18 | }]
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/Frontend/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/Frontend/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/Frontend/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/Frontend/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:13.10-slim
2 | MAINTAINER linzecong
3 | ADD . ./Frontend
4 | WORKDIR /Frontend
5 | RUN apt-get update
6 | RUN npm install
7 | RUN npm run build
8 | RUN apt-get install nginx -y
9 |
10 | RUN rm -rf /Frontend/node_modules
11 |
12 | EXPOSE 80
13 | ADD nginx.conf /etc/nginx/nginx.conf
14 | CMD ["nginx", "-g", "daemon off;"]
--------------------------------------------------------------------------------
/Frontend/README.md:
--------------------------------------------------------------------------------
1 | # 前端部署
2 |
3 | ## Docker部署
4 | 非专业用户不推荐使用Docker单独部署
5 | 修改nginx.conf中proxy_pass的地址为你的后端地址,如有需要,可以修改其他配置
6 |
7 | ```
8 | docker build -t lpojfrontend .
9 | docker run -d -p 80:80 lpojfrontend
10 | ```
11 |
12 | ## 一般部署
13 |
14 | ```
15 | cd Frontend
16 | npm install
17 | npm run build
18 | ```
19 | 编译完毕后,网站文件保存在dist目录中,接下来部署到服务器中
20 | + 推荐使用Nginx
21 | ```
22 | sudo apt-get install nginx
23 | ```
24 | 将dist文件夹中的文件复制到Web服务器目录中(默认根目录 **/var/www/html/**)
25 | 接下来修改Nginx配置文件(不同版本可能在不同的地方)
26 | ```
27 | sudo nano /etc/nginx/nginx.conf
28 | ```
29 | 主要修改如下几个配置
30 | 1. 路由重定向
31 | 2. API重定向
32 |
33 | 将如下配置复制到http{}中
34 | ```
35 | server{
36 | listen 80;
37 | server_name www.lpoj.cn; # 此处填写你的域名或IP地址
38 | root /var/www/html; # 此处填写你的网页根目录
39 | location /api { # 将API重定向到后台服务器(如果你修改了前端中的代理配置,这里需要对应的修改)
40 | rewrite ^.*api/?(.*)$ /$1 break;
41 | proxy_pass http://localhost:8000; # 填写你的后端地址和端口
42 | }
43 | location / { # 路由重定向以适应Vue中的路由
44 | index index.html;
45 | try_files $uri $uri/ /index.html;
46 | }
47 | }
48 | ```
49 | 其他配置请自行参考Nginx配置
50 |
51 | 至此,前端部署完毕。**如要进行OJ二次开发,请参阅[文档](http://docs.lpoj.cn)**
--------------------------------------------------------------------------------
/Frontend/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/Frontend/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Frontend/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/build/logo.png
--------------------------------------------------------------------------------
/Frontend/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Frontend/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: ['babel-polyfill', './src/main.js']
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Frontend/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"',
7 | API_ROOT: '"/api"'
8 | })
9 |
--------------------------------------------------------------------------------
/Frontend/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {
14 | '/api': {
15 | target: 'https://www.lpoj.cn/api',
16 | changeOrigin: true,
17 | pathRewrite: {
18 | '^/api': '/'
19 | }
20 | }
21 | },
22 |
23 | // Various Dev Server settings
24 | host: '0.0.0.0', // can be overwritten by process.env.HOST
25 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
26 | autoOpenBrowser: false,
27 | errorOverlay: true,
28 | notifyOnErrors: true,
29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
30 |
31 |
32 | /**
33 | * Source Maps
34 | */
35 |
36 | // https://webpack.js.org/configuration/devtool/#development
37 | devtool: 'cheap-module-eval-source-map',
38 |
39 | // If you have problems debugging vue-files in devtools,
40 | // set this to false - it *may* help
41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
42 | cacheBusting: true,
43 |
44 | cssSourceMap: true
45 | },
46 |
47 | build: {
48 | // Template for index.html
49 | index: path.resolve(__dirname, '../dist/index.html'),
50 |
51 | // Paths
52 | assetsRoot: path.resolve(__dirname, '../dist'),
53 | assetsSubDirectory: 'static',
54 | assetsPublicPath: '/',
55 |
56 | /**
57 | * Source Maps
58 | */
59 |
60 | productionSourceMap: false,
61 | // https://webpack.js.org/configuration/devtool/#production
62 | devtool: '#source-map',
63 |
64 | // Gzip off by default as many popular static hosts such as
65 | // Surge or Netlify already gzip all static assets for you.
66 | // Before setting to `true`, make sure to:
67 | // npm install --save-dev compression-webpack-plugin
68 | productionGzip: true,
69 | productionGzipExtensions: ['js', 'css'],
70 |
71 | // Run the build command with an extra argument to
72 | // View the bundle analyzer report after build finishes:
73 | // `npm run build --report`
74 | // Set to `true` or `false` to always turn it on or off
75 | bundleAnalyzerReport: process.env.npm_config_report
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Frontend/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"',
4 | API_ROOT: '"/api"'
5 | }
6 |
--------------------------------------------------------------------------------
/Frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Welcome to LPOJ
10 |
19 |
20 |
31 |
32 |
33 |
34 |
35 |
36 | First time loading, please wait for a second 如果等太久,可以尝试按一下F5
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Frontend/src/components/chart/echarts.js:
--------------------------------------------------------------------------------
1 | import echarts from 'echarts/lib/echarts'
2 |
3 | // 再引入你需要使用的图表类型,标题,提示信息等
4 |
5 | import 'echarts/lib/chart/line' // 按需导入折线组件
6 | import 'echarts/lib/component/tooltip' // 提示组件
7 | import 'echarts/lib/component/legend' // 图例组件
8 | import 'echarts/lib/component/visualMap'
9 |
10 | export default echarts
--------------------------------------------------------------------------------
/Frontend/src/components/contest/contestannounce.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
15 | {{label.send}}
16 |
17 |
18 |
19 |
20 |
77 |
78 |
79 |
81 |
--------------------------------------------------------------------------------
/Frontend/src/components/contest/contestsubmit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
26 |
27 |
28 |
33 |
--------------------------------------------------------------------------------
/Frontend/src/components/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
88 |
89 |
95 |
--------------------------------------------------------------------------------
/Frontend/src/components/mainpage/homework.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
9 |
12 |
14 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
71 |
72 |
73 |
75 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/blogmini.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 最新博客
5 | 查看全部
11 |
12 |
13 |
14 |
15 |
16 |
17 | 摘要: {{ scope.row.summary }}
18 |
19 | {{ scope.row.title }}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
67 |
68 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/contestmini.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Calendar of All Competitions
5 |
6 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
59 |
60 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/description.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 欢迎来到本OJ
6 |
7 | 这是一个基于Vue.js和Django的轻量级在线评测系统
8 | 有任何好的意见可以在左下角留言板留言
9 |
10 |
11 |
12 |
13 |
14 | FAQ:
15 | 判题机使用Linux系统
16 | Java: 主类名字请写更改为Main后再提交。Java提供3倍的时限
17 | Python: Python不提供编译过程, 所以一切因为Python代码编写错误引发的错误, 均判为Runtime Error
18 | C++:支持__int128
19 | 判题机会自动的去掉行末空格(不会去掉换行)
20 |
21 | 编译参数:
22 | C++: g++ -O2 -std=c++14
23 | C: g++ -O2 -std=c11
24 | Java: JDK-8
25 |
26 |
27 |
28 |
29 |
30 |
43 |
44 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/languageselect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
44 |
45 |
46 |
48 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/soulrow.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Get into Valley of Trials
7 |
8 |
9 | Start trial
10 |
11 |
12 |
13 |
14 |
15 |
16 | Fast search algorithm
17 |
18 |
19 | Search algorithm
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
68 |
69 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/topuser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Top User
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
56 |
57 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/welcomemessage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Welcome to {{school}}
5 |
6 | Version:3.4
7 |
8 |
9 |
10 |
11 |
12 |
13 |
48 |
49 |
--------------------------------------------------------------------------------
/Frontend/src/components/utils/wikidetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 | Thanks for the mirror provided by Netease
17 |
18 |
19 |
20 |
21 |
22 |
58 |
59 |
60 |
62 |
--------------------------------------------------------------------------------
/Frontend/src/components/wiki/algorithm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
77 |
78 |
79 |
81 |
--------------------------------------------------------------------------------
/Frontend/src/components/wiki/code.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 欢迎来到代码库
5 | 你可以选择你要查看的代码库或者编辑自己的代码库
6 |
7 |
8 | 选择一个版本 或
9 | 编辑自己的代码
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
59 |
60 |
61 |
63 |
--------------------------------------------------------------------------------
/Frontend/src/components/wiki/newalgorithm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Thanks for the mirror provided by Netease
6 |
7 |
8 |
9 |
10 |
26 |
27 |
28 |
30 |
--------------------------------------------------------------------------------
/Frontend/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/.gitkeep
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_AMS-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_AMS-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Bold.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Caligraphic-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Bold.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Fraktur-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Bold.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Italic.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Main-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-BoldItalic.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-Italic.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Math-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Bold.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Italic.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_SansSerif-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Script-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Script-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size1-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size1-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size2-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size3-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Size4-Regular.woff
--------------------------------------------------------------------------------
/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Typewriter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Frontend/static/js/fonts/HTML-CSS/TeX/woff/MathJax_Typewriter-Regular.woff
--------------------------------------------------------------------------------
/FrontendMobile/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "modules": false,
7 | "useBuiltIns": "entry"
8 | }
9 | ],
10 | "stage-3"
11 | ]
12 | }
--------------------------------------------------------------------------------
/FrontendMobile/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/FrontendMobile/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/FrontendMobile/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/FrontendMobile/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FrontendMobile/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:13.10-slim
2 | MAINTAINER linzecong
3 | ADD . ./FrontendMobile
4 | WORKDIR /FrontendMobile
5 | RUN apt-get update
6 | RUN npm install
7 | RUN npm run build
8 | RUN apt-get install nginx -y
9 | RUN rm -rf /Frontend/node_modules
10 |
11 | EXPOSE 8081
12 | ADD nginx.conf /etc/nginx/nginx.conf
13 | CMD ["nginx", "-g", "daemon off;"]
--------------------------------------------------------------------------------
/FrontendMobile/README.md:
--------------------------------------------------------------------------------
1 | # 手机前端部署
2 |
3 | # 2019-08-01 后不再维护!
4 |
5 | ## Docker部署
6 | 非专业用户不推荐使用Docker单独部署
7 | 修改nginx.conf中proxy_pass的地址为你的后端地址,如有需要,可以修改其他配置
8 |
9 | ```
10 | docker build -t lpojfrontendmobile .
11 | docker run -d -p 80:80 lpojfrontendmobile
12 | ```
13 |
14 | ## 一般部署
15 |
16 | ```
17 | cd FrontendMobile
18 | npm install
19 | npm run build
20 | ```
21 | 编译完毕后,网站文件保存在dist目录中,接下来部署到服务器中
22 | + 推荐使用Nginx
23 | ```
24 | sudo apt-get install nginx
25 | ```
26 | 将dist文件夹中的文件复制到Web服务器目录中(默认根目录 **/var/www/html/**)
27 | 接下来修改Nginx配置文件(不同版本可能在不同的地方)
28 | ```
29 | sudo nano /etc/nginx/nginx.conf
30 | ```
31 | 主要修改如下几个配置
32 | 1. 路由重定向
33 | 2. API重定向
34 |
35 | 将如下配置复制到http{}中
36 | ```
37 | server{
38 | listen 80;
39 | server_name m.lpoj.cn; # 此处填写你的域名或IP地址
40 | root /var/www/html; # 此处填写你的网页根目录
41 | location /api { # 将API重定向到后台服务器(如果你修改了前端中的代理配置,这里需要对应的修改)
42 | rewrite ^.*api/?(.*)$ /$1 break;
43 | proxy_pass http://localhost:8000; # 填写你的后端地址和端口
44 | }
45 | location / { # 路由重定向以适应Vue中的路由
46 | index index.html;
47 | try_files $uri $uri/ /index.html;
48 | }
49 | }
50 | ```
51 | 其他配置请自行参考Nginx配置
52 |
53 | 至此,手机前端部署完毕。**如要进行OJ二次开发,请参阅[文档](http://docs.lpoj.cn)**
--------------------------------------------------------------------------------
/FrontendMobile/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/FrontendMobile/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/FrontendMobile/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/FrontendMobile/build/logo.png
--------------------------------------------------------------------------------
/FrontendMobile/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/FrontendMobile/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: ['babel-polyfill', './src/main.js']
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/FrontendMobile/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"',
7 | API_ROOT: '"/api"'
8 | })
9 |
--------------------------------------------------------------------------------
/FrontendMobile/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {
14 | '/api': {
15 | target: 'https://www.lpoj.cn/api',
16 | changeOrigin: true,
17 | pathRewrite:{
18 | '^/api':'/'
19 | }
20 | }
21 | },
22 |
23 | // Various Dev Server settings
24 | host: '0.0.0.0', // can be overwritten by process.env.HOST
25 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
26 | autoOpenBrowser: false,
27 | errorOverlay: true,
28 | notifyOnErrors: true,
29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
30 |
31 |
32 | /**
33 | * Source Maps
34 | */
35 |
36 | // https://webpack.js.org/configuration/devtool/#development
37 | devtool: 'cheap-module-eval-source-map',
38 |
39 | // If you have problems debugging vue-files in devtools,
40 | // set this to false - it *may* help
41 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
42 | cacheBusting: true,
43 |
44 | cssSourceMap: true
45 | },
46 |
47 | build: {
48 | // Template for index.html
49 | index: path.resolve(__dirname, '../dist/index.html'),
50 |
51 | // Paths
52 | assetsRoot: path.resolve(__dirname, '../dist'),
53 | assetsSubDirectory: 'static',
54 | assetsPublicPath: '/',
55 |
56 | /**
57 | * Source Maps
58 | */
59 |
60 | productionSourceMap: false,
61 | // https://webpack.js.org/configuration/devtool/#production
62 | devtool: '#source-map',
63 |
64 | // Gzip off by default as many popular static hosts such as
65 | // Surge or Netlify already gzip all static assets for you.
66 | // Before setting to `true`, make sure to:
67 | // npm install --save-dev compression-webpack-plugin
68 | productionGzip: true,
69 | productionGzipExtensions: ['js', 'css'],
70 |
71 | // Run the build command with an extra argument to
72 | // View the bundle analyzer report after build finishes:
73 | // `npm run build --report`
74 | // Set to `true` or `false` to always turn it on or off
75 | bundleAnalyzerReport: process.env.npm_config_report
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/FrontendMobile/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"',
4 | API_ROOT: '"/api"'
5 | }
6 |
--------------------------------------------------------------------------------
/FrontendMobile/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Welcome to LPOJ
12 |
21 |
22 |
23 |
24 |
25 |
28 |
31 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/contest/contestsubmit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
26 |
27 |
32 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/main.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Go to Wiki
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
47 |
48 |
49 |
52 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/mainpage/wiki.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 欢迎来到某大型在线游戏攻略网站LPOJ Wiki
7 | 在这里你可以找到算法竞赛的学习教程,代码模板,和算法试炼
8 | 现在让我们开始吧!
9 |
10 |
11 |
12 |
13 |
14 | 算法教程
15 |
16 | 在这里你可以找到最全的算法攻略
17 | 在这里你可以编写自己的攻略
18 | 在这里你可以查看别人编写的攻略
19 |
20 | 查看攻略
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | LPOJ试炼谷
29 |
30 | 在这里你可以找到ACM的入门方法
31 | 在这里你可以得到完整的历练
32 | 在这里你可以看到自己变成大神的轨迹
33 |
34 | 开始试炼
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
74 |
75 |
76 |
78 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/utils/contestmini.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{scope.row.contestName}} |
8 | {{scope.row.startTime}} |
9 | {{scope.row.endTime}} |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
66 |
67 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/utils/topuser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 | {{scope.row.username}} |
14 | {{scope.row.rating}} |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
67 |
68 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/utils/welcomemessage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Mobile Version:1.1
6 |
7 |
14 |
21 |
22 |
23 |
24 |
25 |
48 |
49 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/utils/wikidetail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Thanks for the mirror provided by Netease
15 |
16 |
17 |
18 |
19 |
55 |
56 |
57 |
59 |
--------------------------------------------------------------------------------
/FrontendMobile/src/components/wiki/newalgorithm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Thanks for the mirror provided by Netease
7 |
8 |
9 |
10 |
11 |
27 |
28 |
29 |
31 |
--------------------------------------------------------------------------------
/FrontendMobile/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/FrontendMobile/static/.gitkeep
--------------------------------------------------------------------------------
/HomePage/assets/css/owl.theme.default.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791}
--------------------------------------------------------------------------------
/HomePage/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/HomePage/assets/img/about/about-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/about/about-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/about/shape-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/about/shape-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/about/shape-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/about/shape-2.png
--------------------------------------------------------------------------------
/HomePage/assets/img/about/shape-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/about/shape-3.png
--------------------------------------------------------------------------------
/HomePage/assets/img/about/shape-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/about/shape-4.png
--------------------------------------------------------------------------------
/HomePage/assets/img/breadcrumb/breadcrumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/breadcrumb/breadcrumb.png
--------------------------------------------------------------------------------
/HomePage/assets/img/cta/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/cta/2.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/cta/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/cta/5.png
--------------------------------------------------------------------------------
/HomePage/assets/img/cta/cta-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/cta/cta-bg.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/cta/cta-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/cta/cta-bg.png
--------------------------------------------------------------------------------
/HomePage/assets/img/faqs/faqs-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/faqs/faqs-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/footer/foot-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/footer/foot-bg.png
--------------------------------------------------------------------------------
/HomePage/assets/img/hero/hero-bg-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/hero/hero-bg-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/logo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/logo-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/logo-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/logo-2.png
--------------------------------------------------------------------------------
/HomePage/assets/img/screen/screen-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/screen/screen-1.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/screen/screen-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/screen/screen-2.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/screen/screen-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/screen/screen-3.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/screen/screen-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/screen/screen-4.jpg
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-1-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-1-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-1-2.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-1-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-1-3.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-2.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/icon-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/icon-3.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/shape-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/shape-1.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/shape-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/shape-2.png
--------------------------------------------------------------------------------
/HomePage/assets/img/services/shape-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/HomePage/assets/img/services/shape-3.png
--------------------------------------------------------------------------------
/HomePage/assets/img/top-arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/HomePage/assets/js/ajax-form.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // Get the form.
4 | var form = $('#ajax-contact');
5 |
6 | // Get the messages div.
7 | var formMessages = $('.form-message');
8 |
9 | // Set up an event listener for the contact form.
10 | $(form).submit(function(e) {
11 | // Stop the browser from submitting the form.
12 | e.preventDefault();
13 |
14 | // Serialize the form data.
15 | var formData = $(form).serialize();
16 |
17 | // Submit the form using AJAX.
18 | $.ajax({
19 | type: 'POST',
20 | url: $(form).attr('action'),
21 | data: formData
22 | })
23 | .done(function(response) {
24 | // Make sure that the formMessages div has the 'success' class.
25 | $(formMessages).removeClass('error');
26 | $(formMessages).addClass('success');
27 |
28 | // Set the message text.
29 | $(formMessages).text(response);
30 |
31 | // Clear the form.
32 | $('#name').val('');
33 | $('#email').val('');
34 | $('#message').val('');
35 | })
36 | .fail(function(data) {
37 | // Make sure that the formMessages div has the 'error' class.
38 | $(formMessages).removeClass('success');
39 | $(formMessages).addClass('error');
40 |
41 | // Set the message text.
42 | if (data.responseText !== '') {
43 | $(formMessages).text(data.responseText);
44 | } else {
45 | $(formMessages).text('*Oops! An error occured and your message could not be sent.');
46 | }
47 | });
48 |
49 | });
50 |
51 | });
--------------------------------------------------------------------------------
/HomePage/assets/js/counterup.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jquery.counterup.js 1.0
3 | *
4 | * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
5 | * Released under the GPL v2 License
6 | *
7 | * Date: Nov 26, 2013
8 | */(function(e){"use strict";e.fn.counterUp=function(t){var n=e.extend({time:400,delay:10},t);return this.each(function(){var t=e(this),r=n,i=function(){var e=[],n=r.time/r.delay,i=t.text(),s=/[0-9]+,[0-9]+/.test(i);i=i.replace(/,/g,"");var o=/^[0-9]+$/.test(i),u=/^[0-9]+\.[0-9]+$/.test(i),a=u?(i.split(".")[1]||[]).length:0;for(var f=n;f>=1;f--){var l=parseInt(i/n*f);u&&(l=parseFloat(i/n*f).toFixed(a));if(s)while(/(\d+)(\d{3})/.test(l.toString()))l=l.toString().replace(/(\d+)(\d{3})/,"$1,$2");e.unshift(l)}t.data("counterup-nums",e);t.text("0");var c=function(){t.text(t.data("counterup-nums").shift());if(t.data("counterup-nums").length)setTimeout(t.data("counterup-func"),r.delay);else{delete t.data("counterup-nums");t.data("counterup-nums",null);t.data("counterup-func",null)}};t.data("counterup-func",c);setTimeout(t.data("counterup-func"),r.delay)};t.waypoint(i,{offset:"100%",triggerOnce:!0})})}})(jQuery);
--------------------------------------------------------------------------------
/HomePage/assets/js/plugins.js:
--------------------------------------------------------------------------------
1 | // Avoid `console` errors in browsers that lack a console.
2 | (function() {
3 | var method;
4 | var noop = function () {};
5 | var methods = [
6 | 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
7 | 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
8 | 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
9 | 'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
10 | ];
11 | var length = methods.length;
12 | var console = (window.console = window.console || {});
13 |
14 | while (length--) {
15 | method = methods[length];
16 |
17 | // Only stub undefined methods.
18 | if (!console[method]) {
19 | console[method] = noop;
20 | }
21 | }
22 | }());
23 |
24 | // Place any jQuery/helper plugins in here.
25 |
--------------------------------------------------------------------------------
/Judger/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.5)
2 | project(judger C)
3 |
4 | #set(CMAKE_VERBOSE_MAKEFILE ON)
5 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output)
6 |
7 | set(CMAKE_C_FLAGS "-g -Wall -Werror -O3 -std=c99 -pie -fPIC")
8 |
9 | # make judger lib
10 | file(GLOB SOURCE "src/*.c" "src/rules/*.c")
11 | add_executable(libjudger.so ${SOURCE})
12 | target_link_libraries(libjudger.so pthread seccomp)
13 |
14 |
15 | install(FILES output/libjudger.so
16 | PERMISSIONS OWNER_EXECUTE OWNER_READ
17 | DESTINATION /usr/lib/judger)
18 |
--------------------------------------------------------------------------------
/Judger/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM swift:5.1
2 | MAINTAINER linzecong
3 | ADD . ./Judger
4 | WORKDIR /Judger
5 | RUN apt-get update
6 | RUN mv /usr/lib/python2.7/site-packages /usr/lib/python2.7/dist-packages
7 | RUN ln -s dist-packages /usr/lib/python2.7/site-packages
8 | RUN apt-get install python2.7 -y
9 | RUN apt-get install python3 -y
10 | RUN apt-get install python3-pip -y
11 | # RUN ln -s /usr/bin/python3 /usr/bin/python
12 | # RUN ln -s /usr/bin/pip3 /usr/bin/pip
13 | RUN apt-get install mysql-server -y
14 | RUN apt-get install mysql-client -y
15 | RUN apt-get install libatomic1 -y
16 | RUN apt-get install libssl-dev -y
17 | RUN apt-get install libz-dev -y
18 | RUN apt install pkg-config -y
19 | RUN apt install net-tools -y
20 | RUN apt install nano -y
21 | RUN apt-get install iputils-ping -y
22 | RUN apt-get install libmysqlclient-dev -y
23 | RUN pip3 install -r requirements.txt
24 | RUN apt-get install time -y
25 | RUN apt-get install cmake -y
26 | RUN apt-get install openjdk-8-jdk -y
27 | RUN apt-get install libseccomp-dev -y && mkdir build && cd build && cmake /Judger && make && make install && cd .. && cd JudgerCore && python3 setup.py install
28 | CMD ["python3", "main.py"]
29 |
--------------------------------------------------------------------------------
/Judger/JudgerCore/_judger/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Judger/JudgerCore/_judger/__init__.pyc
--------------------------------------------------------------------------------
/Judger/JudgerCore/setup.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | from distutils.core import setup, Extension
3 |
4 | setup(name='_judger',
5 | version='2.1',
6 | packages=["_judger"])
--------------------------------------------------------------------------------
/Judger/ProblemData/README.md:
--------------------------------------------------------------------------------
1 | # 数据文件夹
2 |
3 | 判题机会自动通过HTTP从后端服务器下载数据并自动解压保存在ProblemData文件夹中,因此不要删除本目录
--------------------------------------------------------------------------------
/Judger/README.md:
--------------------------------------------------------------------------------
1 |
2 | # 感谢 QingdaoU/Judger
3 |
4 | # 原项目链接 https://github.com/QingdaoU/Judger
5 |
6 |
7 | ## Docker部署
8 | 非专业用户不推荐使用Docker单独部署
9 |
10 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
11 | ```
12 | cd Judger
13 | nano setting.json
14 | ```
15 | 接着运行容器
16 | ```
17 | docker build -t lpojjudger .
18 | docker run -d lpojjudger
19 | ```
20 |
21 | ## 一般部署
22 |
23 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
24 |
25 | 如果你需要Python判题,那么请注意修改python_path
26 |
27 | 你可以使用 whereis python 命名查看python路径
28 |
29 |
30 | ```
31 | cd Judger
32 | nano setting.json
33 | ```
34 |
35 | ##### 安装步骤
36 | 1. sudo apt-get install libseccomp-dev
37 | 2. mkdir build && cd build && cmake .. && make && sudo make install
38 | 3. cd ..
39 | 4. cd JudgerCore
40 | 5. sudo python setup.py install
41 | 6. pip install paramiko
42 | 7. pip install mysqlclient
43 |
44 | ###### 运行
45 | 1. sudo python main.py
46 |
47 | # 详细测试
48 | 参考 https://github.com/QingdaoU/Judger 中的 unittest
49 |
50 | # 参数解释
51 |
52 | ## result
53 | WAITING = -6
54 | PRESENTATION_ERROR = -5
55 | COMPILE_ERROR = -4
56 | WRONG_ANSWER = -3
57 | PENDING = -1
58 | JUDGINNG = -2
59 | CPU_TIME_LIMIT_EXCEEDED = 1
60 | REAL_TIME_LIMIT_EXCEEDED = 2
61 | MEMORY_LIMIT_EXCEEDED = 3
62 | RUNTIME_ERROR = 4
63 | SYSTEM_ERROR = 5
64 |
65 | ## error
66 | SUCCESS = 0
67 | INVALID_CONFIG = -1
68 | FORK_FAILED = -2
69 | PTHREAD_FAILED = -3
70 | WAIT_FAILED = -4
71 | ROOT_REQUIRED = -5
72 | LOAD_SECCOMP_FAILED = -6
73 | SETRLIMIT_FAILED = -7
74 | DUP2_FAILED = -8
75 | SETUID_FAILED = -9
76 | EXECVE_FAILED = -10
77 | SPJ_ERROR = -11 (judger module will never return this value, it's used for awswer checker)
--------------------------------------------------------------------------------
/Judger/datatime.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
--------------------------------------------------------------------------------
/Judger/output/libjudger.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Linzecong/LPOJ/2f7ce194f1d510d8d006c2a35fdaa272f20ef1f3/Judger/output/libjudger.so
--------------------------------------------------------------------------------
/Judger/requirements.txt:
--------------------------------------------------------------------------------
1 | paramiko==2.4.2
2 | mysqlclient==1.4.2.post1
3 | requests==2.20.0
--------------------------------------------------------------------------------
/Judger/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_user":"root",
3 | "db_pass":"504603913",
4 | "db_ip":"localhost",
5 | "db_port":"3306",
6 | "db_database":"LPOJ",
7 | "server_ip":"localhost",
8 | "server_port":9906,
9 | "backend_ip":"localhost",
10 | "backend_port":8000,
11 | "backend_head":"http",
12 | "python3_path": "/usr/bin/python3",
13 | "python2_path": "/usr/bin/python2.7",
14 | "nodownload":"no"
15 | }
--------------------------------------------------------------------------------
/Judger/src/child.h:
--------------------------------------------------------------------------------
1 | #ifndef JUDGER_CHILD_H
2 | #define JUDGER_CHILD_H
3 |
4 | #include
5 | #include "runner.h"
6 |
7 | #define CHILD_ERROR_EXIT(error_code)\
8 | {\
9 | LOG_FATAL(log_fp, "Error: System errno: %s; Internal errno: "#error_code, strerror(errno)); \
10 | close_file(input_file); \
11 | if (output_file == error_file) { \
12 | close_file(output_file); \
13 | } else { \
14 | close_file(output_file); \
15 | close_file(error_file); \
16 | } \
17 | raise(SIGUSR1); \
18 | exit(EXIT_FAILURE); \
19 | }
20 |
21 |
22 | void child_process(FILE *log_fp, struct config *_config);
23 |
24 | #endif //JUDGER_CHILD_H
25 |
--------------------------------------------------------------------------------
/Judger/src/killer.c:
--------------------------------------------------------------------------------
1 | #define _POSIX_SOURCE
2 | #include
3 | #include
4 | #include
5 |
6 | #include "killer.h"
7 |
8 |
9 | int kill_pid(pid_t pid) {
10 | return kill(pid, SIGKILL);
11 | }
12 |
13 |
14 | void *timeout_killer(void *timeout_killer_args) {
15 | // this is a new thread, kill the process if timeout
16 | pid_t pid = ((struct timeout_killer_args *)timeout_killer_args)->pid;
17 | int timeout = ((struct timeout_killer_args *)timeout_killer_args)->timeout;
18 | // On success, pthread_detach() returns 0; on error, it returns an error number.
19 | if (pthread_detach(pthread_self()) != 0) {
20 | kill_pid(pid);
21 | return NULL;
22 | }
23 | // usleep can't be used, for time args must < 1000ms
24 | // this may sleep longer that expected, but we will have a check at the end
25 | if (sleep((unsigned int)((timeout + 1000) / 1000)) != 0) {
26 | kill_pid(pid);
27 | return NULL;
28 | }
29 | if (kill_pid(pid) != 0) {
30 | return NULL;
31 | }
32 | return NULL;
33 | }
--------------------------------------------------------------------------------
/Judger/src/killer.h:
--------------------------------------------------------------------------------
1 | #ifndef JUDGER_KILLER_H
2 | #define JUDGER_KILLER_H
3 |
4 | struct timeout_killer_args {
5 | int pid;
6 | int timeout;
7 | };
8 |
9 | int kill_pid(pid_t pid);
10 |
11 | void *timeout_killer(void *timeout_killer_args);
12 |
13 | #endif //JUDGER_KILLER_H
14 |
--------------------------------------------------------------------------------
/Judger/src/logger.c:
--------------------------------------------------------------------------------
1 | #define _POSIX_SOURCE
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "logger.h"
10 |
11 | #define log_buffer_size 8192
12 |
13 |
14 | FILE *log_open(const char *filename) {
15 | FILE *log_fp = fopen(filename, "a");
16 | if (log_fp == NULL) {
17 | fprintf(stderr, "can not open log file %s", filename);
18 | }
19 | return log_fp;
20 | }
21 |
22 |
23 | void log_close(FILE *log_fp) {
24 | if (log_fp != NULL) {
25 | fclose(log_fp);
26 | }
27 | }
28 |
29 |
30 | void log_write(int level, const char *source_filename, const int line, const FILE *log_fp, const char *fmt, ...) {
31 | char LOG_LEVEL_NOTE[][10] = {"FATAL", "WARNING", "INFO", "DEBUG"};
32 | if (log_fp == NULL) {
33 | fprintf(stderr, "can not open log file");
34 | return;
35 | }
36 | static char buffer[log_buffer_size];
37 | static char log_buffer[log_buffer_size];
38 | static char datetime[100];
39 | static char line_str[20];
40 | static time_t now;
41 | now = time(NULL);
42 |
43 | strftime(datetime, 99, "%Y-%m-%d %H:%M:%S", localtime(&now));
44 | snprintf(line_str, 19, "%d", line);
45 | va_list ap;
46 | va_start(ap, fmt);
47 | vsnprintf(log_buffer, log_buffer_size, fmt, ap);
48 | va_end(ap);
49 |
50 | int count = snprintf(buffer, log_buffer_size,
51 | "%s [%s] [%s:%s]%s\n",
52 | LOG_LEVEL_NOTE[level], datetime, source_filename, line_str, log_buffer);
53 | // fprintf(stderr, "%s", buffer);
54 | int log_fd = fileno((FILE *) log_fp);
55 | if (flock(log_fd, LOCK_EX) == 0) {
56 | if (write(log_fd, buffer, (size_t) count) < 0) {
57 | fprintf(stderr, "write error");
58 | return;
59 | }
60 | flock(log_fd, LOCK_UN);
61 | }
62 | else {
63 | fprintf(stderr, "flock error");
64 | return;
65 | }
66 | }
--------------------------------------------------------------------------------
/Judger/src/logger.h:
--------------------------------------------------------------------------------
1 | #ifndef JUDGER_LOGGER_H
2 | #define JUDGER_LOGGER_H
3 |
4 | #define LOG_LEVEL_FATAL 0
5 | #define LOG_LEVEL_WARNING 1
6 | #define LOG_LEVEL_INFO 2
7 | #define LOG_LEVEL_DEBUG 3
8 |
9 |
10 | FILE *log_open(const char *);
11 |
12 | void log_close(FILE *);
13 |
14 | void log_write(int level, const char *source_filename, const int line_number, const FILE *log_fp, const char *, ...);
15 |
16 | #ifdef JUDGER_DEBUG
17 | #define LOG_DEBUG(log_fp, x...) log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, log_fp, ##x)
18 | #else
19 | #define LOG_DEBUG(log_fp, x...)
20 | #endif
21 |
22 | #define LOG_INFO(log_fp, x...) log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, log_fp, ##x)
23 | #define LOG_WARNING(log_fp, x...) log_write(LOG_LEVEL_WARNING, __FILE__, __LINE__, log_fp, ##x)
24 | #define LOG_FATAL(log_fp, x...) log_write(LOG_LEVEL_FATAL, __FILE__, __LINE__, log_fp, ##x)
25 |
26 | #endif //JUDGER_LOGGER_H
27 |
--------------------------------------------------------------------------------
/Judger/src/rules/c_cpp.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../runner.h"
8 |
9 |
10 | int c_cpp_seccomp_rules(struct config *_config) {
11 | int syscalls_whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat),
12 | SCMP_SYS(mmap), SCMP_SYS(mprotect),
13 | SCMP_SYS(munmap), SCMP_SYS(uname),
14 | SCMP_SYS(arch_prctl), SCMP_SYS(brk),
15 | SCMP_SYS(access), SCMP_SYS(exit_group),
16 | SCMP_SYS(close), SCMP_SYS(readlink),
17 | SCMP_SYS(sysinfo), SCMP_SYS(write),
18 | SCMP_SYS(writev), SCMP_SYS(lseek)};
19 |
20 | int syscalls_whitelist_length = sizeof(syscalls_whitelist) / sizeof(int);
21 | scmp_filter_ctx ctx = NULL;
22 | // load seccomp rules
23 | ctx = seccomp_init(SCMP_ACT_KILL);
24 | if (!ctx) {
25 | return LOAD_SECCOMP_FAILED;
26 | }
27 | for (int i = 0; i < syscalls_whitelist_length; i++) {
28 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls_whitelist[i], 0) != 0) {
29 | return LOAD_SECCOMP_FAILED;
30 | }
31 | }
32 | // add extra rule for execve
33 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)(_config->exe_path))) != 0) {
34 | return LOAD_SECCOMP_FAILED;
35 | }
36 | // do not allow "w" and "rw"
37 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) {
38 | return LOAD_SECCOMP_FAILED;
39 | }
40 | if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) != 0) {
41 | return LOAD_SECCOMP_FAILED;
42 | }
43 | if (seccomp_load(ctx) != 0) {
44 | return LOAD_SECCOMP_FAILED;
45 | }
46 | seccomp_release(ctx);
47 | return 0;
48 | }
--------------------------------------------------------------------------------
/Judger/src/rules/general.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "../runner.h"
9 |
10 |
11 | int general_seccomp_rules(struct config *_config) {
12 | int syscalls_blacklist[] = {//SCMP_SYS(clone),
13 | SCMP_SYS(fork), SCMP_SYS(vfork),
14 | SCMP_SYS(kill),
15 | #ifdef __NR_execveat
16 | SCMP_SYS(execveat)
17 | #endif
18 | };
19 | int syscalls_blacklist_length = sizeof(syscalls_blacklist) / sizeof(int);
20 | scmp_filter_ctx ctx = NULL;
21 | // load seccomp rules
22 | ctx = seccomp_init(SCMP_ACT_ALLOW);
23 | if (!ctx) {
24 | return LOAD_SECCOMP_FAILED;
25 | }
26 | for (int i = 0; i < syscalls_blacklist_length; i++) {
27 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, syscalls_blacklist[i], 0) != 0) {
28 | return LOAD_SECCOMP_FAILED;
29 | }
30 | }
31 | // use SCMP_ACT_KILL for socket, python will be killed immediately
32 | // if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 0) != 0) {
33 | // return LOAD_SECCOMP_FAILED;
34 | // }
35 | // add extra rule for execve
36 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_NE, (scmp_datum_t)(_config->exe_path))) != 0) {
37 | return LOAD_SECCOMP_FAILED;
38 | }
39 | // do not allow "w" and "rw" using open
40 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) {
41 | return LOAD_SECCOMP_FAILED;
42 | }
43 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) {
44 | return LOAD_SECCOMP_FAILED;
45 | }
46 | // do not allow "w" and "rw" using openat
47 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) {
48 | return LOAD_SECCOMP_FAILED;
49 | }
50 | if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) {
51 | return LOAD_SECCOMP_FAILED;
52 | }
53 |
54 | if (seccomp_load(ctx) != 0) {
55 | return LOAD_SECCOMP_FAILED;
56 | }
57 | seccomp_release(ctx);
58 | return 0;
59 | }
--------------------------------------------------------------------------------
/Judger/src/rules/seccomp_rules.h:
--------------------------------------------------------------------------------
1 | #ifndef JUDGER_SECCOMP_RULES_H
2 | #define JUDGER_SECCOMP_RULES_H
3 | #include "../runner.h"
4 |
5 | int c_cpp_seccomp_rules(struct config *_config);
6 | int general_seccomp_rules(struct config *_config);
7 |
8 | #endif //JUDGER_SECCOMP_RULES_H
9 |
--------------------------------------------------------------------------------
/Judger/src/runner.h:
--------------------------------------------------------------------------------
1 | #ifndef JUDGER_RUNNER_H
2 | #define JUDGER_RUNNER_H
3 |
4 | #include
5 | #include
6 |
7 | // (ver >> 16) & 0xff, (ver >> 8) & 0xff, ver & 0xff -> real version
8 | #define VERSION 0x020101
9 |
10 | #define UNLIMITED -1
11 |
12 | #define LOG_ERROR(error_code) LOG_FATAL(log_fp, "Error: "#error_code);
13 |
14 | #define ERROR_EXIT(error_code)\
15 | {\
16 | LOG_ERROR(error_code); \
17 | _result->error = error_code; \
18 | log_close(log_fp); \
19 | return; \
20 | }
21 |
22 | #define ARGS_MAX_NUMBER 256
23 | #define ENV_MAX_NUMBER 256
24 |
25 |
26 | enum {
27 | SUCCESS = 0,
28 | INVALID_CONFIG = -1,
29 | FORK_FAILED = -2,
30 | PTHREAD_FAILED = -3,
31 | WAIT_FAILED = -4,
32 | ROOT_REQUIRED = -5,
33 | LOAD_SECCOMP_FAILED = -6,
34 | SETRLIMIT_FAILED = -7,
35 | DUP2_FAILED = -8,
36 | SETUID_FAILED = -9,
37 | EXECVE_FAILED = -10,
38 | SPJ_ERROR = -11
39 | };
40 |
41 |
42 | struct config {
43 | int max_cpu_time;
44 | int max_real_time;
45 | long max_memory;
46 | long max_stack;
47 | int max_process_number;
48 | long max_output_size;
49 | int memory_limit_check_only;
50 | char *exe_path;
51 | char *input_path;
52 | char *output_path;
53 | char *error_path;
54 | char *args[ARGS_MAX_NUMBER];
55 | char *env[ENV_MAX_NUMBER];
56 | char *log_path;
57 | char *seccomp_rule_name;
58 | uid_t uid;
59 | gid_t gid;
60 | };
61 |
62 |
63 | enum {
64 | WRONG_ANSWER = -1,
65 | CPU_TIME_LIMIT_EXCEEDED = 1,
66 | REAL_TIME_LIMIT_EXCEEDED = 2,
67 | MEMORY_LIMIT_EXCEEDED = 3,
68 | RUNTIME_ERROR = 4,
69 | SYSTEM_ERROR = 5
70 | };
71 |
72 |
73 | struct result {
74 | int cpu_time;
75 | int real_time;
76 | long memory;
77 | int signal;
78 | int exit_code;
79 | int error;
80 | int result;
81 | };
82 |
83 |
84 | void run(struct config *, struct result *);
85 | #endif //JUDGER_RUNNER_H
86 |
--------------------------------------------------------------------------------
/JudgerServer/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.7.2
2 | MAINTAINER linzecong
3 | ADD . ./JudgerServer
4 | WORKDIR /JudgerServer
5 | RUN pip install -r requirements.txt
6 | EXPOSE 9906
7 | CMD ["python", "main.py"]
8 |
9 |
--------------------------------------------------------------------------------
/JudgerServer/README.md:
--------------------------------------------------------------------------------
1 | # 判题服务器部署
2 |
3 | ## Docker部署
4 | 非专业用户不推荐使用Docker单独部署
5 |
6 | 首先修改配置文件,setting.json里的东西都要修改为你的ip
7 | ```
8 | cd JudgerServer
9 | nano setting.json
10 | ```
11 | 接着运行容器
12 | ```
13 | docker build -t lpojjudgerserver .
14 | docker run -d -p 9906:9906 lpojjudgerserver
15 | ```
16 |
17 | ## 一般部署
18 | 首先修改配置文件
19 | ```
20 | cd JudgeServer
21 | nano setting.json
22 | ```
23 | 修改对应的数据库IP和端口保存退出
24 | ```
25 | pip install mysqlclient
26 | sudo python main.py
27 | ```
--------------------------------------------------------------------------------
/JudgerServer/requirements.txt:
--------------------------------------------------------------------------------
1 | mysqlclient==1.4.2.post1
--------------------------------------------------------------------------------
/JudgerServer/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_user":"root",
3 | "db_pass":"504603913",
4 | "db_ip":"localhost",
5 | "db_port":"3306",
6 | "db_database":"LPOJ",
7 | "server_port":9906
8 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017-present OnineJudge
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Tools/README.md:
--------------------------------------------------------------------------------
1 | # 这是各种工具文件夹,使用方法详见 [docs.lpoj.cn](https://docs.lpoj.cn)
--------------------------------------------------------------------------------
/Tools/RaiseCheck.py:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | import MySQLdb
6 | from queue import Queue
7 | import socket
8 | import json
9 | from time import sleep
10 | import threading
11 | import os
12 |
13 |
14 | queue = Queue() # 全局判题列表
15 | myjsonfile = open("./setting.json", 'r')
16 | judgerjson = json.loads(myjsonfile.read())
17 |
18 | if os.environ.get("DB_USER"):
19 | judgerjson["db_ip"] = os.environ.get("DB_HOST")
20 | judgerjson["db_pass"] = os.environ.get("DB_PASSWORD")
21 | judgerjson["db_user"] = os.environ.get("DB_USER")
22 | judgerjson["db_port"] = os.environ.get("DB_PORT")
23 |
24 | try:
25 | db = MySQLdb.connect(judgerjson["db_ip"], judgerjson["db_user"], judgerjson["db_pass"],
26 | judgerjson["db_database"], int(judgerjson["db_port"]), charset='utf8')
27 | except Exception as e:
28 | print(e)
29 | exit(1)
30 |
31 |
32 | cursor = db.cursor()
33 |
34 | cursor.execute("SELECT user, code from judgestatus_judgestatus")
35 | data = cursor.fetchall()
36 |
37 | raisenum = {}
38 |
39 | for d in data:
40 | id = str(d[0])
41 | code = str(d[1])
42 | raisenum[id] = 0
43 |
44 | for d in data:
45 | id = str(d[0])
46 | code = str(d[1])
47 | raisenum[id] = max(raisenum[id], code.count("raise"))
48 |
49 | li = sorted(raisenum.items(), key=lambda item:item[1],reverse=True)
50 |
51 | file = open("raisenum.txt", "w")
52 |
53 | for l in li:
54 | file.write(l[0]+" "+str(l[1])+'\n')
55 | print(l[0]+" "+str(l[1]))
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Tools/RecoverBoard.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 |
3 | import MySQLdb
4 | import socket
5 | import json
6 | import time
7 | import os
8 | from time import sleep
9 | import datetime
10 |
11 | myjsonfile = open("./setting.json", 'r')
12 | judgerjson = json.loads(myjsonfile.read())
13 |
14 | try:
15 | db = MySQLdb.connect(judgerjson["db_ip"], judgerjson["db_user"], judgerjson["db_pass"],
16 | judgerjson["db_database"], int(judgerjson["db_port"]), charset='utf8')
17 | except Exception as e:
18 | print(e)
19 | exit(1)
20 |
21 |
22 | source_conntest = 100 # 比赛ID
23 | des_conntest = 101 # 复制到哪个比赛
24 |
25 | cursor = db.cursor()
26 | cursor.execute("SELECT * from judgestatus_judgestatus where contest = %d "%source_conntest) # contest
27 |
28 | datas = cursor.fetchall()
29 |
30 | for data in datas:
31 |
32 | id = data[0]
33 | username = data[1]
34 | cursor.execute("SELECT * from user_user where username=%s",(username,))
35 | name = cursor.fetchone()[2]
36 |
37 | rank = ord(data[16]) - 65
38 | contestid = des_conntest
39 |
40 | result = data[4]
41 | type = -1
42 | if result == 0:
43 | type = 1
44 | elif type != -4 and type != -1 and type != -6 and type != -2 and type != 5:
45 | type = 0
46 |
47 |
48 | subtime = data[9]
49 |
50 | subtime = int(subtime.timestamp() * 1000)
51 |
52 | print(contestid,username,name,rank,type,subtime,id,1500) # contest
53 |
54 |
55 | #cursor.execute("INSERT INTO contest_contestboard(contestid,username,user,problemrank,type,submittime,submitid,rating) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)",(contestid,username,name,rank,type,subtime,id,1500))
56 | # (username, totleac, today, username, today))
57 |
58 |
59 | #db.commit()
--------------------------------------------------------------------------------
/Tools/UserImporter.py:
--------------------------------------------------------------------------------
1 | # coding=utf-8
2 | import requests
3 | from time import sleep
4 | import sys
5 | import hashlib
6 | # 暂时做成txt中导入,后面再加入从表格中读取
7 |
8 | def insertUser(username, password, name, school="unknow", course="unknow", classes="unknow", number="unknow", realname="unknow", qq="unknow", email="unknow", type=1):
9 |
10 | # 待加密信息
11 | # 创建md5对象
12 | hl = hashlib.md5()
13 | hl.update(password.encode(encoding='utf-8'))
14 | password = hl.hexdigest()
15 | print(password)
16 |
17 | userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
18 | header = {
19 | 'User-Agent': userAgent,
20 | }
21 |
22 | mafengwoSession = requests.session()
23 |
24 | password2 = '123456'
25 | # 创建md5对象
26 | h2 = hashlib.md5()
27 | h2.update(password2.encode(encoding='utf-8'))
28 | password2 = h2.hexdigest()
29 |
30 | loginUrl = "https://www.lpoj.cn/api/login" # 登录 url
31 | loginData = {
32 | "username": "admin", # 管理员用户名和密码
33 | "password": password2,
34 | }
35 | responseRes = mafengwoSession.post(
36 | loginUrl, data=loginData, headers=header, allow_redirects=True)
37 | print(responseRes.text)
38 |
39 | postUrl = "https://www.lpoj.cn/api/register" # 注册 url
40 | postData = {
41 | "username": username,
42 | "password": password,
43 | "name" :name,
44 | "school" : school,
45 | "course" : course,
46 | "classes" : classes,
47 | "number" : number,
48 | "realname" : realname,
49 | "qq" : qq,
50 | "email" :email,
51 | "type" :1
52 | }
53 | responseRes = mafengwoSession.post(postUrl, data=postData, headers=header)
54 | print(responseRes.text)
55 |
56 | if __name__ == "__main__":
57 | file = open(sys.argv[1],"r",encoding='utf-8')
58 | lines = file.readlines()
59 | for line in lines:
60 | items = line.split(" ")
61 | print(items)
62 | insertUser(items[0], items[1], items[2])
63 | sleep(0.3)
64 |
--------------------------------------------------------------------------------
/Tools/setting.json:
--------------------------------------------------------------------------------
1 | {
2 | "db_user":"root",
3 | "db_pass":"504603913",
4 | "db_ip":"localhost",
5 | "db_port":"3306",
6 | "db_database":"LPOJ"
7 | }
--------------------------------------------------------------------------------
|