remove contest type
This commit is contained in:
@@ -56,9 +56,7 @@ const contest = reactive<BlankContest & { id: number }>({
|
|||||||
tag: "练习",
|
tag: "练习",
|
||||||
start_time: "",
|
start_time: "",
|
||||||
end_time: "",
|
end_time: "",
|
||||||
rule_type: "ACM",
|
|
||||||
password: "",
|
password: "",
|
||||||
real_time_rank: true,
|
|
||||||
visible: false,
|
visible: false,
|
||||||
allowed_ip_ranges: [],
|
allowed_ip_ranges: [],
|
||||||
})
|
})
|
||||||
@@ -79,9 +77,7 @@ async function getContestDetail() {
|
|||||||
contest.tag = data.tag
|
contest.tag = data.tag
|
||||||
contest.start_time = data.start_time
|
contest.start_time = data.start_time
|
||||||
contest.end_time = data.end_time
|
contest.end_time = data.end_time
|
||||||
contest.rule_type = "ACM"
|
|
||||||
contest.password = data.password
|
contest.password = data.password
|
||||||
contest.real_time_rank = true
|
|
||||||
contest.visible = data.visible
|
contest.visible = data.visible
|
||||||
contest.allowed_ip_ranges = []
|
contest.allowed_ip_ranges = []
|
||||||
|
|
||||||
|
|||||||
@@ -24,23 +24,41 @@ const emit = defineEmits<{
|
|||||||
const activeTab = ref(props.languages[0] || "Python3")
|
const activeTab = ref(props.languages[0] || "Python3")
|
||||||
|
|
||||||
const ENGINE_OPTIONS: SelectOption[] = [
|
const ENGINE_OPTIONS: SelectOption[] = [
|
||||||
{ label: "节点检查", type: "group", key: "node_group", children: [
|
{
|
||||||
{ label: "必须存在", value: "must_exist_node" },
|
label: "节点检查",
|
||||||
{ label: "不能存在", value: "must_not_exist_node" },
|
type: "group",
|
||||||
{ label: "出现次数", value: "count_node" },
|
key: "node_group",
|
||||||
]},
|
children: [
|
||||||
{ label: "函数调用", type: "group", key: "func_group", children: [
|
{ label: "必须存在", value: "must_exist_node" },
|
||||||
{ label: "必须调用函数", value: "must_call_function" },
|
{ label: "不能存在", value: "must_not_exist_node" },
|
||||||
{ label: "不能调用函数", value: "must_not_call_function" },
|
{ label: "出现次数", value: "count_node" },
|
||||||
{ label: "函数调用次数", value: "count_function_call" },
|
],
|
||||||
]},
|
},
|
||||||
{ label: "方法调用", type: "group", key: "method_group", children: [
|
{
|
||||||
{ label: "必须调用方法", value: "must_call_method" },
|
label: "函数调用",
|
||||||
{ label: "不能调用方法", value: "must_not_call_method" },
|
type: "group",
|
||||||
]},
|
key: "func_group",
|
||||||
{ label: "运算符", type: "group", key: "op_group", children: [
|
children: [
|
||||||
{ label: "必须使用运算符", value: "must_use_operator" },
|
{ label: "必须调用函数", value: "must_call_function" },
|
||||||
]},
|
{ label: "不能调用函数", value: "must_not_call_function" },
|
||||||
|
{ label: "函数调用次数", value: "count_function_call" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "方法调用",
|
||||||
|
type: "group",
|
||||||
|
key: "method_group",
|
||||||
|
children: [
|
||||||
|
{ label: "必须调用方法", value: "must_call_method" },
|
||||||
|
{ label: "不能调用方法", value: "must_not_call_method" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "运算符",
|
||||||
|
type: "group",
|
||||||
|
key: "op_group",
|
||||||
|
children: [{ label: "必须使用运算符", value: "must_use_operator" }],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const NODE_TARGET_OPTIONS: SelectOption[] = [
|
const NODE_TARGET_OPTIONS: SelectOption[] = [
|
||||||
@@ -83,16 +101,30 @@ const OPERATOR_TARGET_OPTIONS: SelectOption[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const NODE_ENGINES = ["must_exist_node", "must_not_exist_node", "count_node"]
|
const NODE_ENGINES = ["must_exist_node", "must_not_exist_node", "count_node"]
|
||||||
const FUNCTION_ENGINES = ["must_call_function", "must_not_call_function", "count_function_call"]
|
const FUNCTION_ENGINES = [
|
||||||
|
"must_call_function",
|
||||||
|
"must_not_call_function",
|
||||||
|
"count_function_call",
|
||||||
|
]
|
||||||
const METHOD_ENGINES = ["must_call_method", "must_not_call_method"]
|
const METHOD_ENGINES = ["must_call_method", "must_not_call_method"]
|
||||||
const OPERATOR_ENGINES = ["must_use_operator"]
|
const OPERATOR_ENGINES = ["must_use_operator"]
|
||||||
const COUNT_ENGINES = ["count_node", "count_function_call"]
|
const COUNT_ENGINES = ["count_node", "count_function_call"]
|
||||||
|
|
||||||
function isNodeEngine(engine: string) { return NODE_ENGINES.includes(engine) }
|
function isNodeEngine(engine: string) {
|
||||||
function isFunctionEngine(engine: string) { return FUNCTION_ENGINES.includes(engine) }
|
return NODE_ENGINES.includes(engine)
|
||||||
function isMethodEngine(engine: string) { return METHOD_ENGINES.includes(engine) }
|
}
|
||||||
function isOperatorEngine(engine: string) { return OPERATOR_ENGINES.includes(engine) }
|
function isFunctionEngine(engine: string) {
|
||||||
function isCountEngine(engine: string) { return COUNT_ENGINES.includes(engine) }
|
return FUNCTION_ENGINES.includes(engine)
|
||||||
|
}
|
||||||
|
function isMethodEngine(engine: string) {
|
||||||
|
return METHOD_ENGINES.includes(engine)
|
||||||
|
}
|
||||||
|
function isOperatorEngine(engine: string) {
|
||||||
|
return OPERATOR_ENGINES.includes(engine)
|
||||||
|
}
|
||||||
|
function isCountEngine(engine: string) {
|
||||||
|
return COUNT_ENGINES.includes(engine)
|
||||||
|
}
|
||||||
|
|
||||||
const COUNT_MODE_OPTIONS: SelectOption[] = [
|
const COUNT_MODE_OPTIONS: SelectOption[] = [
|
||||||
{ label: "精确", value: "exact" },
|
{ label: "精确", value: "exact" },
|
||||||
@@ -126,9 +158,15 @@ function updateExactCount(lang: string, index: number, v: number | null) {
|
|||||||
updateRules(lang, rules)
|
updateRules(lang, rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
function needsTargetDropdown(engine: string) { return isNodeEngine(engine) }
|
function needsTargetDropdown(engine: string) {
|
||||||
function needsTargetInput(engine: string) { return isFunctionEngine(engine) || isMethodEngine(engine) }
|
return isNodeEngine(engine)
|
||||||
function needsOperatorDropdown(engine: string) { return isOperatorEngine(engine) }
|
}
|
||||||
|
function needsTargetInput(engine: string) {
|
||||||
|
return isFunctionEngine(engine) || isMethodEngine(engine)
|
||||||
|
}
|
||||||
|
function needsOperatorDropdown(engine: string) {
|
||||||
|
return isOperatorEngine(engine)
|
||||||
|
}
|
||||||
|
|
||||||
function getRulesForLang(lang: string): AstRule[] {
|
function getRulesForLang(lang: string): AstRule[] {
|
||||||
if (!props.modelValue) return []
|
if (!props.modelValue) return []
|
||||||
@@ -149,13 +187,19 @@ function getTargetLabel(engine: string, target: string): string | undefined {
|
|||||||
if (isNodeEngine(engine))
|
if (isNodeEngine(engine))
|
||||||
return (NODE_TARGET_OPTIONS.find((o) => o.value === target) as any)?.label
|
return (NODE_TARGET_OPTIONS.find((o) => o.value === target) as any)?.label
|
||||||
if (isOperatorEngine(engine))
|
if (isOperatorEngine(engine))
|
||||||
return (OPERATOR_TARGET_OPTIONS.find((o) => o.value === target) as any)?.label
|
return (OPERATOR_TARGET_OPTIONS.find((o) => o.value === target) as any)
|
||||||
|
?.label
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRule(lang: string) {
|
function addRule(lang: string) {
|
||||||
const rules = [...getRulesForLang(lang)]
|
const rules = [...getRulesForLang(lang)]
|
||||||
rules.push({ engine: "must_exist_node", target: "for_loop", label: "for 循环", message: "" })
|
rules.push({
|
||||||
|
engine: "must_exist_node",
|
||||||
|
target: "for_loop",
|
||||||
|
label: "for 循环",
|
||||||
|
message: "",
|
||||||
|
})
|
||||||
updateRules(lang, rules)
|
updateRules(lang, rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +215,16 @@ function updateRule(lang: string, index: number, field: string, value: any) {
|
|||||||
|
|
||||||
if (field === "engine") {
|
if (field === "engine") {
|
||||||
rule.engine = value
|
rule.engine = value
|
||||||
if (isNodeEngine(value)) { rule.target = "for_loop"; rule.label = "for 循环" }
|
if (isNodeEngine(value)) {
|
||||||
else if (isOperatorEngine(value)) { rule.target = "+"; rule.label = "+" }
|
rule.target = "for_loop"
|
||||||
else { rule.target = ""; delete rule.label }
|
rule.label = "for 循环"
|
||||||
|
} else if (isOperatorEngine(value)) {
|
||||||
|
rule.target = "+"
|
||||||
|
rule.label = "+"
|
||||||
|
} else {
|
||||||
|
rule.target = ""
|
||||||
|
delete rule.label
|
||||||
|
}
|
||||||
delete rule.min
|
delete rule.min
|
||||||
delete rule.max
|
delete rule.max
|
||||||
delete rule.exact
|
delete rule.exact
|
||||||
@@ -196,25 +247,39 @@ function updateRule(lang: string, index: number, field: string, value: any) {
|
|||||||
updateRules(lang, rules)
|
updateRules(lang, rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(() => props.languages, (langs) => {
|
watch(
|
||||||
if (langs.length && !langs.includes(activeTab.value as LANGUAGE)) {
|
() => props.languages,
|
||||||
activeTab.value = langs[0]
|
(langs) => {
|
||||||
}
|
if (langs.length && !langs.includes(activeTab.value as LANGUAGE)) {
|
||||||
})
|
activeTab.value = langs[0]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-collapse>
|
<n-collapse>
|
||||||
<n-collapse-item title="代码规则检查(选填)" name="ast-rules">
|
<n-collapse-item title="代码规则检查(选填)" name="ast-rules">
|
||||||
<n-tabs v-if="languages.length" type="segment" v-model:value="activeTab">
|
<n-tabs v-if="languages.length" type="segment" v-model:value="activeTab">
|
||||||
<n-tab-pane v-for="lang in languages" :key="lang" :name="lang" :tab="lang">
|
<n-tab-pane
|
||||||
|
v-for="lang in languages"
|
||||||
|
:key="lang"
|
||||||
|
:name="lang"
|
||||||
|
:tab="lang"
|
||||||
|
>
|
||||||
<n-flex vertical>
|
<n-flex vertical>
|
||||||
<div v-for="(rule, index) in getRulesForLang(lang)" :key="index" style="margin-bottom: 8px">
|
<div
|
||||||
|
v-for="(rule, index) in getRulesForLang(lang)"
|
||||||
|
:key="index"
|
||||||
|
style="margin-bottom: 8px"
|
||||||
|
>
|
||||||
<n-flex align="center" :wrap="false">
|
<n-flex align="center" :wrap="false">
|
||||||
<n-select
|
<n-select
|
||||||
:options="ENGINE_OPTIONS"
|
:options="ENGINE_OPTIONS"
|
||||||
:value="rule.engine"
|
:value="rule.engine"
|
||||||
@update:value="(v: string) => updateRule(lang, index, 'engine', v)"
|
@update:value="
|
||||||
|
(v: string) => updateRule(lang, index, 'engine', v)
|
||||||
|
"
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
@@ -222,7 +287,9 @@ watch(() => props.languages, (langs) => {
|
|||||||
v-if="needsTargetDropdown(rule.engine)"
|
v-if="needsTargetDropdown(rule.engine)"
|
||||||
:options="NODE_TARGET_OPTIONS"
|
:options="NODE_TARGET_OPTIONS"
|
||||||
:value="rule.target"
|
:value="rule.target"
|
||||||
@update:value="(v: string) => updateRule(lang, index, 'target', v)"
|
@update:value="
|
||||||
|
(v: string) => updateRule(lang, index, 'target', v)
|
||||||
|
"
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
size="small"
|
size="small"
|
||||||
filterable
|
filterable
|
||||||
@@ -230,7 +297,9 @@ watch(() => props.languages, (langs) => {
|
|||||||
<n-input
|
<n-input
|
||||||
v-if="needsTargetInput(rule.engine)"
|
v-if="needsTargetInput(rule.engine)"
|
||||||
:value="rule.target"
|
:value="rule.target"
|
||||||
@update:value="(v: string) => updateRule(lang, index, 'target', v)"
|
@update:value="
|
||||||
|
(v: string) => updateRule(lang, index, 'target', v)
|
||||||
|
"
|
||||||
placeholder="函数/方法名"
|
placeholder="函数/方法名"
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -239,7 +308,9 @@ watch(() => props.languages, (langs) => {
|
|||||||
v-if="needsOperatorDropdown(rule.engine)"
|
v-if="needsOperatorDropdown(rule.engine)"
|
||||||
:options="OPERATOR_TARGET_OPTIONS"
|
:options="OPERATOR_TARGET_OPTIONS"
|
||||||
:value="rule.target"
|
:value="rule.target"
|
||||||
@update:value="(v: string) => updateRule(lang, index, 'target', v)"
|
@update:value="
|
||||||
|
(v: string) => updateRule(lang, index, 'target', v)
|
||||||
|
"
|
||||||
style="width: 150px"
|
style="width: 150px"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
@@ -247,14 +318,18 @@ watch(() => props.languages, (langs) => {
|
|||||||
<n-select
|
<n-select
|
||||||
:options="COUNT_MODE_OPTIONS"
|
:options="COUNT_MODE_OPTIONS"
|
||||||
:value="getCountMode(rule)"
|
:value="getCountMode(rule)"
|
||||||
@update:value="(v: 'exact' | 'range') => updateCountMode(lang, index, v)"
|
@update:value="
|
||||||
|
(v: 'exact' | 'range') => updateCountMode(lang, index, v)
|
||||||
|
"
|
||||||
style="width: 80px"
|
style="width: 80px"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
<n-input-number
|
<n-input-number
|
||||||
v-if="getCountMode(rule) === 'exact'"
|
v-if="getCountMode(rule) === 'exact'"
|
||||||
:value="rule.exact ?? null"
|
:value="rule.exact ?? null"
|
||||||
@update:value="(v: number | null) => updateExactCount(lang, index, v)"
|
@update:value="
|
||||||
|
(v: number | null) => updateExactCount(lang, index, v)
|
||||||
|
"
|
||||||
placeholder="次数"
|
placeholder="次数"
|
||||||
style="width: 100px"
|
style="width: 100px"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -264,7 +339,9 @@ watch(() => props.languages, (langs) => {
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<n-input-number
|
<n-input-number
|
||||||
:value="rule.min ?? null"
|
:value="rule.min ?? null"
|
||||||
@update:value="(v: number | null) => updateRule(lang, index, 'min', v)"
|
@update:value="
|
||||||
|
(v: number | null) => updateRule(lang, index, 'min', v)
|
||||||
|
"
|
||||||
placeholder="最少"
|
placeholder="最少"
|
||||||
style="width: 100px"
|
style="width: 100px"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -273,7 +350,9 @@ watch(() => props.languages, (langs) => {
|
|||||||
/>
|
/>
|
||||||
<n-input-number
|
<n-input-number
|
||||||
:value="rule.max ?? null"
|
:value="rule.max ?? null"
|
||||||
@update:value="(v: number | null) => updateRule(lang, index, 'max', v)"
|
@update:value="
|
||||||
|
(v: number | null) => updateRule(lang, index, 'max', v)
|
||||||
|
"
|
||||||
placeholder="最多"
|
placeholder="最多"
|
||||||
style="width: 100px"
|
style="width: 100px"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -284,17 +363,29 @@ watch(() => props.languages, (langs) => {
|
|||||||
</template>
|
</template>
|
||||||
<n-input
|
<n-input
|
||||||
:value="rule.message"
|
:value="rule.message"
|
||||||
@update:value="(v: string) => updateRule(lang, index, 'message', v)"
|
@update:value="
|
||||||
|
(v: string) => updateRule(lang, index, 'message', v)
|
||||||
|
"
|
||||||
placeholder="错误提示(选填)"
|
placeholder="错误提示(选填)"
|
||||||
style="flex: 1"
|
style="flex: 1"
|
||||||
size="small"
|
size="small"
|
||||||
/>
|
/>
|
||||||
<n-button size="small" tertiary type="error" @click="removeRule(lang, index)">
|
<n-button
|
||||||
|
size="small"
|
||||||
|
tertiary
|
||||||
|
type="error"
|
||||||
|
@click="removeRule(lang, index)"
|
||||||
|
>
|
||||||
删除
|
删除
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</div>
|
</div>
|
||||||
<n-button size="small" tertiary type="primary" @click="addRule(lang)">
|
<n-button
|
||||||
|
size="small"
|
||||||
|
tertiary
|
||||||
|
type="primary"
|
||||||
|
@click="addRule(lang)"
|
||||||
|
>
|
||||||
添加规则
|
添加规则
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
|
|||||||
@@ -87,12 +87,24 @@ const columns: DataTableColumn<AdminProblemFiltered>[] = [
|
|||||||
render: (row) =>
|
render: (row) =>
|
||||||
h(NFlex, { size: 4, align: "center" }, () => [
|
h(NFlex, { size: 4, align: "center" }, () => [
|
||||||
row.allow_flowchart
|
row.allow_flowchart
|
||||||
? h(Icon, { width: 18, icon: "vscode-icons:file-type-drawio", title: "绘图" })
|
? h(Icon, {
|
||||||
|
width: 18,
|
||||||
|
icon: "vscode-icons:file-type-drawio",
|
||||||
|
title: "绘图",
|
||||||
|
})
|
||||||
: row.show_flowchart
|
: row.show_flowchart
|
||||||
? h(Icon, { width: 18, icon: "vscode-icons:file-type-graphql", title: "流程图" })
|
? h(Icon, {
|
||||||
|
width: 18,
|
||||||
|
icon: "vscode-icons:file-type-graphql",
|
||||||
|
title: "流程图",
|
||||||
|
})
|
||||||
: null,
|
: null,
|
||||||
row.has_ast_rules
|
row.has_ast_rules
|
||||||
? h(Icon, { width: 18, icon: "vscode-icons:file-type-light-todo", title: "AST" })
|
? h(Icon, {
|
||||||
|
width: 18,
|
||||||
|
icon: "vscode-icons:file-type-light-todo",
|
||||||
|
title: "AST",
|
||||||
|
})
|
||||||
: null,
|
: null,
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ export async function getContestProblems(contestID: string) {
|
|||||||
|
|
||||||
export function getContestRank(
|
export function getContestRank(
|
||||||
contestID: string,
|
contestID: string,
|
||||||
query: { limit: number; offset: number; force_refresh: "1" | "0" },
|
query: { limit: number; offset: number },
|
||||||
) {
|
) {
|
||||||
return http.get("contest_rank", {
|
return http.get("contest_rank", {
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ async function listRanks() {
|
|||||||
const res = await getContestRank(props.contestID, {
|
const res = await getContestRank(props.contestID, {
|
||||||
limit: query.limit,
|
limit: query.limit,
|
||||||
offset: query.limit * (query.page - 1),
|
offset: query.limit * (query.page - 1),
|
||||||
force_refresh: "1",
|
|
||||||
})
|
})
|
||||||
total.value = res.data.total
|
total.value = res.data.total
|
||||||
data.value = res.data.results
|
data.value = res.data.results
|
||||||
@@ -225,7 +224,6 @@ async function downloadExcel() {
|
|||||||
const res = await getContestRank(props.contestID, {
|
const res = await getContestRank(props.contestID, {
|
||||||
limit: total.value || 10000,
|
limit: total.value || 10000,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
force_refresh: "1",
|
|
||||||
})
|
})
|
||||||
const allRanks: ContestRank[] = res.data.results
|
const allRanks: ContestRank[] = res.data.results
|
||||||
|
|
||||||
|
|||||||
@@ -119,29 +119,41 @@ function ruleDescription(rule: AstRule): string {
|
|||||||
const targetLabel = rule.label || NODE_TARGET_LABELS[target] || target
|
const targetLabel = rule.label || NODE_TARGET_LABELS[target] || target
|
||||||
const countDesc = () => {
|
const countDesc = () => {
|
||||||
if (rule.exact !== undefined) return `出现 ${rule.exact} 次`
|
if (rule.exact !== undefined) return `出现 ${rule.exact} 次`
|
||||||
if (rule.min !== undefined && rule.max !== undefined) return `出现 ${rule.min}~${rule.max} 次`
|
if (rule.min !== undefined && rule.max !== undefined)
|
||||||
|
return `出现 ${rule.min}~${rule.max} 次`
|
||||||
if (rule.min !== undefined) return `至少出现 ${rule.min} 次`
|
if (rule.min !== undefined) return `至少出现 ${rule.min} 次`
|
||||||
if (rule.max !== undefined) return `至多出现 ${rule.max} 次`
|
if (rule.max !== undefined) return `至多出现 ${rule.max} 次`
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
const callDesc = () => {
|
const callDesc = () => {
|
||||||
if (rule.exact !== undefined) return `调用 ${rule.exact} 次`
|
if (rule.exact !== undefined) return `调用 ${rule.exact} 次`
|
||||||
if (rule.min !== undefined && rule.max !== undefined) return `调用 ${rule.min}~${rule.max} 次`
|
if (rule.min !== undefined && rule.max !== undefined)
|
||||||
|
return `调用 ${rule.min}~${rule.max} 次`
|
||||||
if (rule.min !== undefined) return `至少调用 ${rule.min} 次`
|
if (rule.min !== undefined) return `至少调用 ${rule.min} 次`
|
||||||
if (rule.max !== undefined) return `至多调用 ${rule.max} 次`
|
if (rule.max !== undefined) return `至多调用 ${rule.max} 次`
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
switch (rule.engine) {
|
switch (rule.engine) {
|
||||||
case "must_exist_node": return `必须使用 ${targetLabel}`
|
case "must_exist_node":
|
||||||
case "must_not_exist_node": return `不能使用 ${targetLabel}`
|
return `必须使用 ${targetLabel}`
|
||||||
case "count_node": return `${targetLabel} ${countDesc()}`
|
case "must_not_exist_node":
|
||||||
case "must_call_function": return `必须调用 ${target}()`
|
return `不能使用 ${targetLabel}`
|
||||||
case "must_not_call_function": return `不能调用 ${target}()`
|
case "count_node":
|
||||||
case "count_function_call": return `${target}() ${callDesc()}`
|
return `${targetLabel} ${countDesc()}`
|
||||||
case "must_call_method": return `必须调用 .${target}()`
|
case "must_call_function":
|
||||||
case "must_not_call_method": return `不能调用 .${target}()`
|
return `必须调用 ${target}()`
|
||||||
case "must_use_operator": return `必须使用 ${target} 运算符`
|
case "must_not_call_function":
|
||||||
default: return rule.engine
|
return `不能调用 ${target}()`
|
||||||
|
case "count_function_call":
|
||||||
|
return `${target}() ${callDesc()}`
|
||||||
|
case "must_call_method":
|
||||||
|
return `必须调用 .${target}()`
|
||||||
|
case "must_not_call_method":
|
||||||
|
return `不能调用 .${target}()`
|
||||||
|
case "must_use_operator":
|
||||||
|
return `必须使用 ${target} 运算符`
|
||||||
|
default:
|
||||||
|
return rule.engine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +165,9 @@ function ruleTagType(engine: string): "error" | "success" | "info" {
|
|||||||
|
|
||||||
const astRulesForDisplay = computed(() => {
|
const astRulesForDisplay = computed(() => {
|
||||||
if (!problem.value?.ast_rules) return []
|
if (!problem.value?.ast_rules) return []
|
||||||
return Object.entries(problem.value.ast_rules).filter(([, rules]) => rules.length > 0)
|
return Object.entries(problem.value.ast_rules).filter(
|
||||||
|
([, rules]) => rules.length > 0,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
async function test(sample: Sample, index: number) {
|
async function test(sample: Sample, index: number) {
|
||||||
@@ -302,14 +316,18 @@ function type(status: ProblemStatus) {
|
|||||||
</n-flex>
|
</n-flex>
|
||||||
</p>
|
</p>
|
||||||
<div v-for="[lang, rules] in astRulesForDisplay" :key="lang">
|
<div v-for="[lang, rules] in astRulesForDisplay" :key="lang">
|
||||||
<p v-if="astRulesForDisplay.length > 1" class="lang-label">{{ lang }}</p>
|
<p v-if="astRulesForDisplay.length > 1" class="lang-label">
|
||||||
|
{{ lang }}
|
||||||
|
</p>
|
||||||
<n-list bordered style="margin-bottom: 8px">
|
<n-list bordered style="margin-bottom: 8px">
|
||||||
<n-list-item v-for="(rule, i) in rules" :key="i">
|
<n-list-item v-for="(rule, i) in rules" :key="i">
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<n-tag :type="ruleTagType(rule.engine)">
|
<n-tag :type="ruleTagType(rule.engine)">
|
||||||
{{ ruleDescription(rule) }}
|
{{ ruleDescription(rule) }}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
<span v-if="rule.message" class="rule-message">{{ rule.message }}</span>
|
<span v-if="rule.message" class="rule-message">{{
|
||||||
|
rule.message
|
||||||
|
}}</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-list-item>
|
</n-list-item>
|
||||||
</n-list>
|
</n-list>
|
||||||
|
|||||||
@@ -43,7 +43,10 @@ const msg = computed(() => {
|
|||||||
msg += "请仔细检查,看看代码的格式是不是写错了!\n\n"
|
msg += "请仔细检查,看看代码的格式是不是写错了!\n\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result !== SubmissionStatus.ast_check_failed && props.submission.statistic_info?.err_info) {
|
if (
|
||||||
|
result !== SubmissionStatus.ast_check_failed &&
|
||||||
|
props.submission.statistic_info?.err_info
|
||||||
|
) {
|
||||||
msg += props.submission.statistic_info.err_info
|
msg += props.submission.statistic_info.err_info
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +156,14 @@ const columns: DataTableColumn<Submission["info"]["data"][number]>[] = [
|
|||||||
:title="JUDGE_STATUS[submission.result]['title']"
|
:title="JUDGE_STATUS[submission.result]['title']"
|
||||||
class="mb-3"
|
class="mb-3"
|
||||||
/>
|
/>
|
||||||
<n-flex vertical v-if="msg || infoTable.length || submission.statistic_info?.ast_results?.length">
|
<n-flex
|
||||||
|
vertical
|
||||||
|
v-if="
|
||||||
|
msg ||
|
||||||
|
infoTable.length ||
|
||||||
|
submission.statistic_info?.ast_results?.length
|
||||||
|
"
|
||||||
|
>
|
||||||
<n-card v-if="submission.statistic_info?.ast_results?.length" embedded>
|
<n-card v-if="submission.statistic_info?.ast_results?.length" embedded>
|
||||||
<n-flex vertical :size="8">
|
<n-flex vertical :size="8">
|
||||||
<n-flex
|
<n-flex
|
||||||
@@ -162,7 +172,9 @@ const columns: DataTableColumn<Submission["info"]["data"][number]>[] = [
|
|||||||
align="center"
|
align="center"
|
||||||
:size="6"
|
:size="6"
|
||||||
>
|
>
|
||||||
<n-icon :color="rule.passed ? theme.successColor : theme.errorColor">
|
<n-icon
|
||||||
|
:color="rule.passed ? theme.successColor : theme.errorColor"
|
||||||
|
>
|
||||||
<Icon :icon="rule.passed ? 'ep:select' : 'ep:close-bold'" />
|
<Icon :icon="rule.passed ? 'ep:select' : 'ep:close-bold'" />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
<span>{{ rule.description }}</span>
|
<span>{{ rule.description }}</span>
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ watch(
|
|||||||
result === SubmissionStatus.submitting
|
result === SubmissionStatus.submitting
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if (result !== SubmissionStatus.accepted && result !== SubmissionStatus.ast_check_failed) {
|
if (
|
||||||
|
result !== SubmissionStatus.accepted &&
|
||||||
|
result !== SubmissionStatus.ast_check_failed
|
||||||
|
) {
|
||||||
problemStore.incrementFailCount()
|
problemStore.incrementFailCount()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -159,7 +162,11 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => submission.value?.result,
|
() => submission.value?.result,
|
||||||
async (result) => {
|
async (result) => {
|
||||||
if (result !== SubmissionStatus.accepted && result !== SubmissionStatus.ast_check_failed) return
|
if (
|
||||||
|
result !== SubmissionStatus.accepted &&
|
||||||
|
result !== SubmissionStatus.ast_check_failed
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
// 1. 刷新题目状态
|
// 1. 刷新题目状态
|
||||||
problem.value!.my_status = 0
|
problem.value!.my_status = 0
|
||||||
|
|||||||
@@ -267,7 +267,11 @@ watch(isMobile, (value) => {
|
|||||||
>
|
>
|
||||||
<ProblemComment />
|
<ProblemComment />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane v-if="myFlowchartStore.showing" name="my-flowchart" tab="我的流程图">
|
<n-tab-pane
|
||||||
|
v-if="myFlowchartStore.showing"
|
||||||
|
name="my-flowchart"
|
||||||
|
tab="我的流程图"
|
||||||
|
>
|
||||||
<MyFlowchartTab />
|
<MyFlowchartTab />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
<n-tab-pane name="submission" tab="提交" :disabled="!!props.problemSetId">
|
<n-tab-pane name="submission" tab="提交" :disabled="!!props.problemSetId">
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ export function secondsToDuration(seconds: number): string {
|
|||||||
start: 0,
|
start: 0,
|
||||||
end: seconds * 1000,
|
end: seconds * 1000,
|
||||||
})
|
})
|
||||||
return [
|
const hours = (duration.days ?? 0) * 24 + (duration.hours ?? 0)
|
||||||
duration.hours ?? 0,
|
const pad = (n: number) => String(n).padStart(2, "0")
|
||||||
duration.minutes ?? 0,
|
return [hours, pad(duration.minutes ?? 0), pad(duration.seconds ?? 0)].join(
|
||||||
duration.seconds ?? 0,
|
":",
|
||||||
].join(":")
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function submissionMemoryFormat(memory: number | string | undefined) {
|
export function submissionMemoryFormat(memory: number | string | undefined) {
|
||||||
|
|||||||
@@ -65,7 +65,20 @@ export type LANGUAGE =
|
|||||||
export type LANGUAGE_SHOW_LABEL =
|
export type LANGUAGE_SHOW_LABEL =
|
||||||
(typeof LANGUAGE_SHOW_VALUE)[keyof typeof LANGUAGE_SHOW_VALUE]
|
(typeof LANGUAGE_SHOW_VALUE)[keyof typeof LANGUAGE_SHOW_VALUE]
|
||||||
|
|
||||||
export type SUBMISSION_RESULT = -2 | -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
|
export type SUBMISSION_RESULT =
|
||||||
|
| -2
|
||||||
|
| -1
|
||||||
|
| 0
|
||||||
|
| 1
|
||||||
|
| 2
|
||||||
|
| 3
|
||||||
|
| 4
|
||||||
|
| 5
|
||||||
|
| 6
|
||||||
|
| 7
|
||||||
|
| 8
|
||||||
|
| 9
|
||||||
|
| 10
|
||||||
|
|
||||||
export type ProblemStatus = "passed" | "failed" | "not_test"
|
export type ProblemStatus = "passed" | "failed" | "not_test"
|
||||||
|
|
||||||
@@ -137,7 +150,15 @@ export interface Problem {
|
|||||||
flowchart_data?: Record<string, any>
|
flowchart_data?: Record<string, any>
|
||||||
flowchart_hint?: string
|
flowchart_hint?: string
|
||||||
show_flowchart?: boolean
|
show_flowchart?: boolean
|
||||||
ast_rules?: { [key: string]: { engine: string; target?: string; min?: number; max?: number; message: string }[] } | null
|
ast_rules?: {
|
||||||
|
[key: string]: {
|
||||||
|
engine: string
|
||||||
|
target?: string
|
||||||
|
min?: number
|
||||||
|
max?: number
|
||||||
|
message: string
|
||||||
|
}[]
|
||||||
|
} | null
|
||||||
has_ast_rules?: boolean
|
has_ast_rules?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +503,7 @@ export interface BlankContest {
|
|||||||
tag: string
|
tag: string
|
||||||
start_time: string
|
start_time: string
|
||||||
end_time: string
|
end_time: string
|
||||||
rule_type: "ACM" | "OI"
|
|
||||||
password: string
|
password: string
|
||||||
real_time_rank: boolean
|
|
||||||
visible: boolean
|
visible: boolean
|
||||||
allowed_ip_ranges: { value: string }[]
|
allowed_ip_ranges: { value: string }[]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user