new_bug_contest
This commit is contained in:
@@ -2,33 +2,133 @@ from django.core.management.base import BaseCommand
|
||||
|
||||
from contest.models import Contest, ContestQuestion, Question, QuestionVersion
|
||||
|
||||
import random
|
||||
|
||||
|
||||
def _generate_beginner():
|
||||
"""入门:100以内加减乘除,约 400 题。"""
|
||||
questions = []
|
||||
ops = [
|
||||
("+", lambda a, b: a + b),
|
||||
("-", lambda a, b: a - b),
|
||||
("×", lambda a, b: a * b),
|
||||
("÷", lambda a, b: a // b if b != 0 and a % b == 0 else None),
|
||||
]
|
||||
idx = 0
|
||||
for a in range(2, 100):
|
||||
for b in range(2, min(a + 1, 100)):
|
||||
for sym, fn in ops:
|
||||
if idx >= 400:
|
||||
return questions
|
||||
if sym == "÷" and (b == 0 or a % b != 0):
|
||||
continue
|
||||
if sym == "-" and a < b:
|
||||
continue
|
||||
result = fn(a, b)
|
||||
if result is None or result < 0 or result > 10000:
|
||||
continue
|
||||
slug = f"b-auto-{idx:04d}"
|
||||
prompt = f"{a} {sym} {b}"
|
||||
answer = str(result)
|
||||
if (slug, prompt, answer) not in questions:
|
||||
questions.append((slug, prompt, answer))
|
||||
idx += 1
|
||||
return questions[:400]
|
||||
|
||||
|
||||
def _generate_standard():
|
||||
"""标准:两位数乘除、大数减法、平方,约 400 题。"""
|
||||
questions = []
|
||||
idx = 0
|
||||
# 两位数乘法
|
||||
for a in range(11, 100):
|
||||
for b in range(11, min(a + 1, 100)):
|
||||
if idx >= 150:
|
||||
break
|
||||
questions.append((f"s-auto-mul-{idx:04d}", f"{a} × {b}", str(a * b)))
|
||||
idx += 1
|
||||
# 三位数除法
|
||||
for a in range(100, 1000, 7):
|
||||
for b in range(11, 50):
|
||||
if idx >= 300:
|
||||
break
|
||||
if a % b == 0:
|
||||
questions.append((f"s-auto-div-{idx:04d}", f"{a} ÷ {b}", str(a // b)))
|
||||
idx += 1
|
||||
# 大数减法
|
||||
for a in range(1000, 10000, 137):
|
||||
b = random.randint(100, a - 1)
|
||||
if idx >= 350:
|
||||
break
|
||||
questions.append((f"s-auto-sub-{idx:04d}", f"{a} - {b}", str(a - b)))
|
||||
idx += 1
|
||||
# 平方
|
||||
for a in range(11, 100):
|
||||
if idx >= 400:
|
||||
break
|
||||
questions.append((f"s-auto-sq-{idx:04d}", f"{a}²", str(a * a)))
|
||||
idx += 1
|
||||
return questions[:400]
|
||||
|
||||
|
||||
def _generate_advanced():
|
||||
"""进阶:模运算、组合数、高次幂、开方、等差数列求和,约 200 题。"""
|
||||
questions = []
|
||||
idx = 0
|
||||
# 模运算
|
||||
for base in range(2, 20):
|
||||
for exp in range(2, 13):
|
||||
for mod in range(3, 20):
|
||||
if idx >= 50:
|
||||
break
|
||||
result = pow(base, exp, mod)
|
||||
questions.append((f"a-auto-mod-{idx:04d}", f"{base}^{exp} ÷ {mod} 的余数", str(result)))
|
||||
idx += 1
|
||||
# 组合数 C(n,k)
|
||||
for n in range(5, 31):
|
||||
for k in range(2, min(n // 2 + 1, 8)):
|
||||
if idx >= 100:
|
||||
break
|
||||
from math import comb
|
||||
questions.append((f"a-auto-comb-{idx:04d}", f"C({n},{k})", str(comb(n, k))))
|
||||
idx += 1
|
||||
# 高次幂
|
||||
for base in range(2, 10):
|
||||
for exp in range(3, 10):
|
||||
if idx >= 130:
|
||||
break
|
||||
result = base ** exp
|
||||
if result > 10**8:
|
||||
continue
|
||||
questions.append((f"a-auto-pow-{idx:04d}", f"{base}^{exp}", str(result)))
|
||||
idx += 1
|
||||
# 开方(完全平方数)
|
||||
for n in range(10, 200):
|
||||
if idx >= 160:
|
||||
break
|
||||
r = int(n**0.5)
|
||||
if r * r == n:
|
||||
questions.append((f"a-auto-sqrt-{idx:04d}", f"√{n}", str(r)))
|
||||
idx += 1
|
||||
# 等差数列求和 1..n
|
||||
for n in range(10, 201, 5):
|
||||
if idx >= 200:
|
||||
break
|
||||
result = n * (n + 1) // 2
|
||||
questions.append((f"a-auto-sum-{idx:04d}", f"1 到 {n} 的整数和", str(result)))
|
||||
idx += 1
|
||||
return questions[:200]
|
||||
|
||||
|
||||
QUESTIONS = {
|
||||
Question.Track.BEGINNER: [
|
||||
("b-12-plus-19", "12 + 19", "31"),
|
||||
("b-8-times-7", "8 × 7", "56"),
|
||||
("b-90-minus-37", "90 - 37", "53"),
|
||||
("b-144-div-12", "144 ÷ 12", "12"),
|
||||
("b-25-times-4", "25 × 4", "100"),
|
||||
],
|
||||
Question.Track.STANDARD: [
|
||||
("s-17-times-23", "17 × 23", "391"),
|
||||
("s-625-div-25", "625 ÷ 25", "25"),
|
||||
("s-48-times-15", "48 × 15", "720"),
|
||||
("s-1000-minus-387", "1000 - 387", "613"),
|
||||
("s-35-squared", "35²", "1225"),
|
||||
],
|
||||
Question.Track.ADVANCED: [
|
||||
("a-mod-2pow10", "2¹⁰ 除以 7 的余数", "2"),
|
||||
("a-sum-1-50", "1 到 50 的整数和", "1275"),
|
||||
("a-15-choose-2", "C(15,2)", "105"),
|
||||
("a-sqrt-2025", "√2025", "45"),
|
||||
("a-3pow6", "3⁶", "729"),
|
||||
],
|
||||
Question.Track.BEGINNER: _generate_beginner(),
|
||||
Question.Track.STANDARD: _generate_standard(),
|
||||
Question.Track.ADVANCED: _generate_advanced(),
|
||||
}
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "创建首批分层题目、实时 1v1、每日赛和单人练习"
|
||||
help = "创建分层题库(入门/标准/进阶)和实时 1v1、每日赛、单人练习"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
versions = {}
|
||||
@@ -93,6 +193,9 @@ class Command(BaseCommand):
|
||||
},
|
||||
)
|
||||
ContestQuestion.objects.filter(contest=contest).delete()
|
||||
pool = list(versions[track])
|
||||
random.shuffle(pool)
|
||||
selected = pool[:8]
|
||||
ContestQuestion.objects.bulk_create(
|
||||
[
|
||||
ContestQuestion(
|
||||
@@ -101,11 +204,14 @@ class Command(BaseCommand):
|
||||
order=index,
|
||||
points=100,
|
||||
)
|
||||
for index, version in enumerate(versions[track], start=1)
|
||||
for index, version in enumerate(selected, start=1)
|
||||
]
|
||||
)
|
||||
total = sum(map(len, QUESTIONS.values()))
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"已创建 {sum(map(len, QUESTIONS.values()))} 道题和 {len(contest_specs)} 场比赛"
|
||||
f"已创建 {total} 道题(入门{len(QUESTIONS[Question.Track.BEGINNER])}、"
|
||||
f"标准{len(QUESTIONS[Question.Track.STANDARD])}、"
|
||||
f"进阶{len(QUESTIONS[Question.Track.ADVANCED])})和 {len(contest_specs)} 场比赛"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -83,6 +83,7 @@ function collectApiErrorMessages(value, messages = []) {
|
||||
}
|
||||
|
||||
function logApiError(error) {
|
||||
if (error.status === 401 || error.status === 403) return;
|
||||
console.error("[Hulumath API]", {
|
||||
method: error.method,
|
||||
path: error.path,
|
||||
|
||||
@@ -350,6 +350,9 @@
|
||||
result.append(outcome, score, timeLine, rating);
|
||||
root.append(result);
|
||||
|
||||
// 刷新右上角用户 Rating 显示
|
||||
if (typeof loadUser === "function") loadUser();
|
||||
|
||||
const review = document.createElement("div");
|
||||
review.className = "realtime-review";
|
||||
match.attempt.questions.forEach((question) => {
|
||||
|
||||
Reference in New Issue
Block a user