fix judge.

This commit is contained in:
2023-12-19 16:02:19 +08:00
parent ea2adbe978
commit 47afc84096
12 changed files with 1126 additions and 441 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
.DS_Store .DS_Store
node_modules node_modules
docs/.vitepress/cache docs/.vitepress/cache
docs/.vitepress/temp
docs/.vitepress/dist docs/.vitepress/dist
# local env files # local env files

122
docs/.vitepress/api.ts Normal file
View File

@@ -0,0 +1,122 @@
import axios from "axios"
interface Code {
language: "C" | "Python3"
value: string
}
const DEAD_RESULTS = {
C: {
encoded:
"I2luY2x1ZGU8c3RkaW8uaD4NCg0KaW50IG1haW4oKQ0Kew0KICAgIHByaW50Zigi6buE5bKp5LiA6IGMIik7DQogICAgcmV0dXJuIDA7DQp9",
result: {
status: 3,
output: "黄岩一职",
},
},
"C++": {
encoded:
"I2luY2x1ZGU8aW9zdHJlYW0+DQoNCnVzaW5nIG5hbWVzcGFjZSBzdGQ7DQoNCmludCBtYWluKCkNCnsNCiAgICBjb3V0PDwi6buE5bKp5LiA6IGMIjw8ZW5kbDsNCiAgICByZXR1cm4gMDsNCn0=",
result: {
status: 3,
output: "黄岩一职",
},
},
Java: {
encoded:
"cHVibGljIGNsYXNzIE1haW4gew0KICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsNCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCLpu4TlsqnkuIDogYwiKTsNCiAgICB9DQp9",
result: {
status: 3,
output: "黄岩一职",
},
},
Python3: {
encoded: "cHJpbnQoIum7hOWyqeS4gOiBjCIp",
result: {
status: 3,
output: "黄岩一职",
},
},
Python2: {
encoded: "",
result: {
status: 3,
output: "黄岩一职",
},
},
Golang: {
encoded: "",
result: {
status: 3,
output: "黄岩一职",
},
},
JavaScript: {
encoded: "",
result: {
status: 3,
output: "黄岩一职",
},
},
}
function getChromeVersion() {
var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)
return raw ? parseInt(raw[2], 10) : 0
}
const isLowVersion = getChromeVersion() < 80
const protocol = isLowVersion ? "http" : "https"
const http = axios.create({ baseURL: `${protocol}://judge0api.xuyue.cc` })
function encode(string?: string) {
return btoa(String.fromCharCode(...new TextEncoder().encode(string ?? "")))
}
function decode(bytes?: string) {
const latin = atob(bytes ?? "")
return new TextDecoder("utf-8").decode(
Uint8Array.from({ length: latin.length }, (_, index) =>
latin.charCodeAt(index),
),
)
}
export async function createSubmission(code: Code, input: string) {
const encodedCode = encode(code.value)
if (encodedCode === DEAD_RESULTS[code.language].encoded) {
return DEAD_RESULTS[code.language].result
} else {
const id = {
C: 50,
"C++": 54,
Java: 62,
Golang: 60,
JavaScript: 63,
Python2: 70,
Python3: 71,
}[code.language]
let compilerOptions = ""
if (id === 50) compilerOptions = "-lm" // 解决 GCC 的链接问题
const payload = {
source_code: encodedCode,
language_id: id,
stdin: encode(input),
redirect_stderr_to_stdout: true,
compiler_options: compilerOptions,
}
const response = await http.post("/submissions", payload, {
params: { base64_encoded: true, wait: true },
})
const data = response.data
return {
status: data.status && data.status.id,
output: [decode(data.compile_output), decode(data.stdout)]
.join("\n")
.trim(),
}
}
}

View File

@@ -1,24 +1,24 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from "vue" import { computed, ref } from "vue"
import { useData } from "vitepress" import { useData } from "vitepress"
import { Codemirror } from "vue-codemirror" import { VPButton } from "vitepress/theme"
import CodeMirror from "vue-codemirror6"
import { cpp } from "@codemirror/lang-cpp" import { cpp } from "@codemirror/lang-cpp"
import { python } from "@codemirror/lang-python" import { python } from "@codemirror/lang-python"
import { EditorView } from "@codemirror/view" import { EditorView } from "@codemirror/view"
import { VPButton } from "vitepress/theme" import { createSubmission } from "../../api"
import { oneDark } from "../codemirror/oneDark" import { smoothy } from "../cm-themes/smoothy"
import { smoothy } from "../codemirror/smoothy" import { oneDark } from "../cm-themes/oneDark"
import { asyncRun } from "./py"
interface Props { interface Props {
modelValue: string code: string
readonly: boolean readonly?: boolean
lang?: "python" | "c" lang?: "python" | "c"
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
lang: "python", lang: "python",
readonly: false readonly: false,
}) })
const { isDark } = useData() const { isDark } = useData()
@@ -40,45 +40,44 @@ const styleTheme = EditorView.baseTheme({
}) })
const input = ref("") const input = ref("")
const output = ref<string[]>([]) const output = ref("")
const error = ref("") const code = ref(props.code.trim())
const code = ref(props.modelValue.trim())
async function run() { async function run() {
const ev = await asyncRun(code.value, input.value) const result = await createSubmission(
output.value = ev.results { value: code.value, language: props.lang === "python" ? "Python3" : "C" },
error.value = ev.error input.value,
)
output.value = result.output
} }
function reset() { function reset() {
code.value = props.modelValue.trim() code.value = props.code.trim()
error.value = "" output.value = ""
output.value = []
} }
</script> </script>
<template> <template>
<p>代码编辑区</p> <ClientOnly>
<Codemirror <p>代码编辑区</p>
:disabled="props.readonly" <CodeMirror
v-model="code" v-model="code"
indentWithTab :lang="lang"
:extensions="[styleTheme, lang, isDark ? oneDark : smoothy]" :tab-size="4"
:tabSize="4" :readonly="props.readonly"
/> :extensions="[styleTheme, isDark ? oneDark : smoothy]"
<p>输入框</p> wrap
<Codemirror basic
v-model="input" tab
indentWithTab />
:extensions="[styleTheme, isDark ? oneDark : smoothy]" <p>输入框</p>
:tabSize="4" <CodeMirror v-model="input" :extensions="[styleTheme]" />
/> <div :class="$style.actions">
<div :class="$style.actions"> <VPButton :class="$style.run" @click="run" text="运行"></VPButton>
<VPButton :class="$style.run" @click="run" text="运行"></VPButton> <VPButton @click="reset" theme="alt" text="重置"></VPButton>
<VPButton @click="reset" theme="alt" text="重置"></VPButton> </div>
</div> <p v-if="output.length">运行结果</p>
<p v-if="output.length || error">运行结果</p> <pre>{{ output }}</pre>
<pre v-for="(it, index) in output" :key="index">{{ it }}</pre> </ClientOnly>
<pre>{{ error }}</pre>
</template> </template>
<style module> <style module>
.actions { .actions {

View File

@@ -1,24 +0,0 @@
const worker = new Worker("/worker.js")
const callbacks = {}
worker.onmessage = (event) => {
const { id, ...data } = event.data
const onSuccess = callbacks[id]
delete callbacks[id]
onSuccess(data)
}
const asyncRun = (() => {
let id = 0 // identify a Promise
return (python: string, input: string) => {
// the id could be generated more carefully
id = (id + 1) % Number.MAX_SAFE_INTEGER
return new Promise<{ results: string[]; error: string }>((onSuccess) => {
callbacks[id] = onSuccess
worker.postMessage({ python, input, id })
})
}
})()
export { asyncRun }

View File

@@ -2,13 +2,13 @@ import type { Theme } from "vitepress"
import DefaultTheme from "vitepress/theme" import DefaultTheme from "vitepress/theme"
import BVideo from "./components/BVideo.vue" import BVideo from "./components/BVideo.vue"
import Author from "./components/Author.vue" import Author from "./components/Author.vue"
// import CodeEditor from "./components/CodeEditor.vue" import CodeEditor from "./components/CodeEditor.vue"
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
async enhanceApp({ app }) { async enhanceApp({ app }) {
app.component("bvideo", BVideo) app.component("bvideo", BVideo)
app.component("author", Author) app.component("author", Author)
// app.component("code-editor", CodeEditor) app.component("code-editor", CodeEditor)
}, },
} satisfies Theme } satisfies Theme

View File

@@ -1,29 +0,0 @@
// webworker.js
// Setup your project to serve `py-worker.js`. You should also serve
// `pyodide.js`, and all its associated `.asm.js`, `.json`,
// and `.wasm` files as well:
importScripts("https://cdn.jsdelivr.net/pyodide/v0.24.1/full/pyodide.js")
async function loadPyodideAndPackages() {
self.pyodide = await loadPyodide()
}
const pyodideReadyPromise = loadPyodideAndPackages()
self.onmessage = async (event) => {
// make sure loading is done
await pyodideReadyPromise
// Don't bother yet with this line, suppose our API is built in such a way:
const { id, python, input } = event.data
// Now is the easy part, the one that is similar to working in the main thread:
try {
let results = []
self.pyodide.setStdin({ stdin: () => input })
self.pyodide.setStdout({ batched: (str) => results.push(str) })
await self.pyodide.runPythonAsync(python)
self.postMessage({ results, error: "", id })
} catch (error) {
self.postMessage({ results: [], error: error.message, id })
}
}

View File

@@ -1,3 +1,15 @@
# 如何使用本网站 # 如何使用本网站
本站是用于 本站是用于
<script lang="ts" setup>
const code = `
n = input()
print(n*3)
if n == "3":
print("哈哈哈")
`
</script>
<code-editor :code="code"></code-editor>

1289
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,13 +13,14 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"prettier": "^3.1.0", "prettier": "^3.1.1",
"vitepress": "1.0.0-rc.25" "vitepress": "1.0.0-rc.32"
}, },
"dependencies": { "dependencies": {
"@codemirror/lang-cpp": "^6.0.2", "@codemirror/lang-cpp": "^6.0.2",
"@codemirror/lang-python": "^6.1.3", "@codemirror/lang-python": "^6.1.3",
"axios": "^1.6.2",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"vue-codemirror": "^6.1.1" "vue-codemirror6": "^1.1.32"
} }
} }