Skip to content

Commit 39e22d0

Browse files
author
CodeJudge
committed
feat: 添加C++支持 + 默认账号
1 parent 24ad83f commit 39e22d0

7 files changed

Lines changed: 78 additions & 13 deletions

File tree

backend/src/controllers/problemController.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,31 @@ function getRandomUnsolved(req, res) {
232232
res.json({ problem });
233233
}
234234

235+
function getSimilarProblems(req, res) {
236+
const { id } = req.params;
237+
const problem = queryOne('SELECT * FROM problems WHERE id = ?', [id]);
238+
if (!problem) return res.status(404).json({ error: '题目不存在' });
239+
const tags = (problem.tags || '').split(',').map(t => t.trim()).filter(Boolean);
240+
let similar = [];
241+
if (tags.length > 0) {
242+
const likeClauses = tags.map(() => "tags LIKE ?");
243+
const tagParams = tags.map(t => `%${t}%`);
244+
similar = queryAll(
245+
`SELECT id, title, type, difficulty, tags, accepted_count, submission_count
246+
FROM problems WHERE id != ? AND (${likeClauses.join(' OR ')})
247+
ORDER BY accepted_count DESC LIMIT 5`,
248+
[id, ...tagParams]
249+
);
250+
}
251+
if (similar.length === 0) {
252+
similar = queryAll(
253+
`SELECT id, title, type, difficulty, tags, accepted_count, submission_count
254+
FROM problems WHERE id != ? AND difficulty = ?
255+
ORDER BY accepted_count DESC LIMIT 5`,
256+
[id, problem.difficulty]
257+
);
258+
}
259+
res.json(similar);
260+
}
261+
235262
module.exports = { listProblems, getProblem, createProblem, updateProblem, deleteProblem, getProblemStats, getAdminStats, getTagsCloud, exportProblems, importProblems, optimizeDatabase, getSimilarProblems, getRandomUnsolved };

backend/src/routes/problems.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,6 @@ router.get('/random-unsolved', authenticate, getRandomUnsolved);
5454
router.get('/admin/stats', adminOnly, getAdminStats);
5555
router.get('/export', adminOnly, exportProblems);
5656
router.post('/import', adminOnly, importProblems);
57-
router.get('/:id', optionalAuth, getProblem);
58-
router.get('/:id/similar', optionalAuth, getSimilarProblems);
59-
router.post('/', adminOnly, createProblem);
60-
router.post('/admin/optimize', adminOnly, optimizeDatabase);
61-
router.put('/:id', adminOnly, updateProblem);
62-
router.delete('/:id', adminOnly, deleteProblem);
63-
6457
router.get('/docs', (req, res) => {
6558
res.json({
6659
name: 'CodeJudge API',
@@ -94,5 +87,6 @@ router.get('/docs', (req, res) => {
9487
],
9588
});
9689
});
90+
router.get('/:id', optionalAuth, getProblem);
9791

9892
module.exports = router;

backend/src/services/judgeService.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ data = sys.stdin.read().strip().split('\\n')
2525
# 示例:读取第一行作为数组
2626
# nums = list(map(int, data[0].split()))
2727
# print(sum(nums))
28+
`,
29+
30+
cpp: `// 读取标准输入
31+
#include <iostream>
32+
#include <vector>
33+
#include <string>
34+
#include <sstream>
35+
using namespace std;
36+
37+
int main() {
38+
// 在这里处理数据
39+
// 使用 cout 输出结果
40+
41+
// 示例:读取一行整数
42+
// int n;
43+
// cin >> n;
44+
// cout << n << endl;
45+
return 0;
46+
}
2847
`,
2948
};
3049

@@ -113,6 +132,16 @@ function runCode(code, language, input) {
113132
cmd = `python "${filename}"`;
114133
break;
115134
}
135+
case 'c':
136+
case 'cpp':
137+
case 'c++': {
138+
filename = path.join(tmpDir, 'main.cpp');
139+
fs.writeFileSync(filename, code);
140+
const binary = path.join(tmpDir, 'main.exe');
141+
execSync(`g++ "${filename}" -o "${binary}" -std=c++17 -O2`, { timeout: TIMEOUT_MS, windowsHide: true });
142+
cmd = `"${binary}"`;
143+
break;
144+
}
116145
default:
117146
throw new Error(`不支持的语言: ${language}`);
118147
}

backend/src/utils/initDb.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ async function initDb() {
104104
}
105105
}
106106

107+
// Add default users if not exist
108+
const adminExists = queryOne("SELECT id FROM users WHERE email = 'admin@oj.com'");
109+
if (!adminExists) {
110+
const hash = bcrypt.hashSync('admin123', 10);
111+
run("INSERT OR IGNORE INTO users (username, email, password, role, last_login) VALUES (?, ?, ?, 'admin', ?)",
112+
['admin', 'admin@oj.com', hash, new Date().toISOString()]);
113+
}
114+
const testExists = queryOne("SELECT id FROM users WHERE email = 'test@oj.com'");
115+
if (!testExists) {
116+
const hash = bcrypt.hashSync('test123', 10);
117+
run("INSERT OR IGNORE INTO users (username, email, password, role, last_login) VALUES (?, ?, ?, 'user', ?)",
118+
['test', 'test@oj.com', hash, new Date().toISOString()]);
119+
}
120+
107121
console.log('Database initialized successfully');
108122
}
109123

frontend/src/components/CodeEditor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ export default function CodeEditor({ code, language, onChange, readOnly = false
1515
<div className="flex-1 border-b border-dark-700" />
1616
<span className="flex items-center gap-1.5 px-3 py-1.5 text-xs text-dark-400">
1717
<Code2 className="w-3.5 h-3.5" />
18-
{language === 'python' ? 'Python' : 'JavaScript'}
18+
{language === 'python' ? 'Python' : language === 'cpp' ? 'C++' : 'JavaScript'}
1919
</span>
2020
</div>
2121

2222
<div className="rounded-lg border border-dark-700 overflow-hidden">
2323
<Editor
2424
height="400px"
25-
language={language === 'python' ? 'python' : 'javascript'}
25+
language={language === 'python' ? 'python' : language === 'cpp' ? 'cpp' : 'javascript'}
2626
value={code}
2727
onChange={(value) => onChange(value || '')}
2828
theme="vs-dark"

frontend/src/pages/ProblemDetail.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default function ProblemDetail() {
6767

6868
// Programming
6969
const [code, setCode] = useState('');
70-
const [language, setLanguage] = useState<'javascript' | 'python'>('javascript');
70+
const [language, setLanguage] = useState<'javascript' | 'python' | 'cpp'>('javascript');
7171

7272
// Choice
7373
const [selectedAnswer, setSelectedAnswer] = useState<number | null>(null);
@@ -640,7 +640,7 @@ export default function ProblemDetail() {
640640
{problem.type === 'programming' && (
641641
<>
642642
<div className="flex gap-2 mb-3">
643-
{(['javascript', 'python'] as const).map((lang) => (
643+
{(['javascript', 'python', 'cpp'] as const).map((lang) => (
644644
<button
645645
key={lang}
646646
onClick={() => setLanguage(lang)}
@@ -650,7 +650,7 @@ export default function ProblemDetail() {
650650
: 'bg-dark-800 text-gray-300 hover:bg-dark-700'
651651
}`}
652652
>
653-
{lang === 'javascript' ? 'JavaScript' : 'Python'}
653+
{lang === 'javascript' ? 'JavaScript' : lang === 'python' ? 'Python' : 'C++'}
654654
</button>
655655
))}
656656
<span className={`ml-auto text-[10px] self-center transition-opacity ${saved ? 'text-emerald-500/70' : 'text-yellow-500/70 opacity-0'}`}>
@@ -765,7 +765,7 @@ export default function ProblemDetail() {
765765

766766
<CodeEditor
767767
code={code}
768-
language={language === 'javascript' ? 'javascript' : 'python'}
768+
language={language === 'javascript' ? 'javascript' : language === 'python' ? 'python' : 'cpp'}
769769
onChange={setCode}
770770
/>
771771
</>

frontend/src/pages/Submissions.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const LANGUAGE_FILTERS = [
3333
{ label: '全部语言', value: '' },
3434
{ label: 'JavaScript', value: 'javascript' },
3535
{ label: 'Python', value: 'python' },
36+
{ label: 'C++', value: 'cpp' },
3637
];
3738

3839
const PAGE_SIZE = 15;

0 commit comments

Comments
 (0)