Browse Source

Add code format

pull/6/head
Menci 6 years ago
parent
commit
d8be150fc6
  1. BIN
      bin/jcf
  2. 180
      bin/jcf.xml
  3. 36
      language-config.json
  4. 54
      libs/code_formatter.js
  5. 31
      models/formatted_code.js
  6. 1
      models/user.js
  7. 23
      modules/problem.js
  8. 16
      modules/submission.js
  9. 2
      modules/user.js
  10. 2
      package.json
  11. 6
      utility.js
  12. 32
      views/submission.ejs
  13. 7
      views/user_edit.ejs

BIN
bin/jcf

Binary file not shown.

180
bin/jcf.xml

@ -0,0 +1,180 @@
<?xml version="1.0" ?>
<JediCodeFormatSettings>
<WriteVersion> 2.44 </WriteVersion>
<WriteDateTime> 39387.7118126273 </WriteDateTime>
<Description> JEDI Code Format Settings </Description>
<Obfuscate>
<Enabled> False </Enabled>
<Caps> 1 </Caps>
<RemoveComments> True </RemoveComments>
<RemoveWhiteSpace> True </RemoveWhiteSpace>
<RemoveIndent> True </RemoveIndent>
<RebreakLines> True </RebreakLines>
</Obfuscate>
<Clarify>
<OnceOffs> 0 </OnceOffs>
<Warnings> True </Warnings>
<WarnUnusedParams> True </WarnUnusedParams>
<IgnoreUnusedParams> Sender </IgnoreUnusedParams>
<FileExtensions> dpr, pas, pp </FileExtensions>
</Clarify>
<Indent>
<IndentationSpaces> 2 </IndentationSpaces>
<FirstLevelIndent> 2 </FirstLevelIndent>
<HasFirstLevelIndent> False </HasFirstLevelIndent>
<IndentGlobals> True </IndentGlobals>
<IndentClasses> True </IndentClasses>
<IndentProcedures> False </IndentProcedures>
<KeepCommentsWithCodeInGlobals> True </KeepCommentsWithCodeInGlobals>
<KeepCommentsWithCodeInProcs> True </KeepCommentsWithCodeInProcs>
<KeepCommentsWithCodeInClassDef> True </KeepCommentsWithCodeInClassDef>
<KeepCommentsWithCodeElsewhere> True </KeepCommentsWithCodeElsewhere>
<IndentBeginEnd> False </IndentBeginEnd>
<IndentbeginEndSpaces> 2 </IndentbeginEndSpaces>
<IndentElse> False </IndentElse>
<IndentCaseElse> True </IndentCaseElse>
</Indent>
<Spaces>
<TabsToSpaces> True </TabsToSpaces>
<SpacesToTabs> False </SpacesToTabs>
<SpacesPerTab> 2 </SpacesPerTab>
<SpacesForTab> 2 </SpacesForTab>
<FixSpacing> True </FixSpacing>
<SpaceBeforeClassHeritage> False </SpaceBeforeClassHeritage>
<SpacesBeforeColonVar> 0 </SpacesBeforeColonVar>
<SpacesBeforeColonConst> 0 </SpacesBeforeColonConst>
<SpacesBeforeColonParam> 0 </SpacesBeforeColonParam>
<SpacesBeforeColonFn> 0 </SpacesBeforeColonFn>
<SpacesBeforeColonClassVar> 0 </SpacesBeforeColonClassVar>
<SpacesBeforeColonRecordField> 0 </SpacesBeforeColonRecordField>
<SpacesBeforeColonCaseLabel> 0 </SpacesBeforeColonCaseLabel>
<SpacesBeforeColonLabel> 0 </SpacesBeforeColonLabel>
<MaxSpacesInCode> 2 </MaxSpacesInCode>
<UseMaxSpacesInCode> True </UseMaxSpacesInCode>
<SpaceForOperator> 0 </SpaceForOperator>
<SpaceBeforeOpenBracketsInFunctionDeclaration> False </SpaceBeforeOpenBracketsInFunctionDeclaration>
<SpaceBeforeOpenBracketsInFunctionCall> False </SpaceBeforeOpenBracketsInFunctionCall>
<SpaceBeforeOpenSquareBracketsInExpression> False </SpaceBeforeOpenSquareBracketsInExpression>
<SpaceAfterOpenBrackets> False </SpaceAfterOpenBrackets>
<SpaceBeforeCloseBrackets> False </SpaceBeforeCloseBrackets>
</Spaces>
<Returns>
<WhenRebreakLines> 2 </WhenRebreakLines>
<MaxLineLength> 90 </MaxLineLength>
<NumReturnsAfterFinalEnd> 1 </NumReturnsAfterFinalEnd>
<RemoveBadReturns> True </RemoveBadReturns>
<AddGoodReturns> True </AddGoodReturns>
<UsesOnePerLine> False </UsesOnePerLine>
<RemoveExpressionReturns> True </RemoveExpressionReturns>
<RemoveVarReturns> True </RemoveVarReturns>
<NoReturnsInProperty> True </NoReturnsInProperty>
<RemoveProcedureDefReturns> True </RemoveProcedureDefReturns>
<RemoveReturns> True </RemoveReturns>
<RemoveVarBlankLines> True </RemoveVarBlankLines>
<RemoveProcHeaderBlankLines> True </RemoveProcHeaderBlankLines>
<Block> 1 </Block>
<BlockBegin> 1 </BlockBegin>
<Label> 1 </Label>
<LabelBegin> 1 </LabelBegin>
<CaseLabel> 1 </CaseLabel>
<CaseBegin> 1 </CaseBegin>
<CaseElse> 0 </CaseElse>
<CaseElseBegin> 0 </CaseElseBegin>
<EndElse> 1 </EndElse>
<ElseIf> 1 </ElseIf>
<ElseBegin> 0 </ElseBegin>
<BeforeCompilerDirectUses> 1 </BeforeCompilerDirectUses>
<BeforeCompilerDirectStatements> 0 </BeforeCompilerDirectStatements>
<BeforeCompilerDirectGeneral> 1 </BeforeCompilerDirectGeneral>
<AfterCompilerDirectUses> 1 </AfterCompilerDirectUses>
<AfterCompilerDirectStatements> 0 </AfterCompilerDirectStatements>
<AfterCompilerDirectGeneral> 1 </AfterCompilerDirectGeneral>
<ReturnChars> 0 </ReturnChars>
<RemoveConsecutiveBlankLines> True </RemoveConsecutiveBlankLines>
<MaxConsecutiveBlankLines> 4 </MaxConsecutiveBlankLines>
<MaxBlankLinesInSection> 1 </MaxBlankLinesInSection>
<LinesBeforeProcedure> 1 </LinesBeforeProcedure>
</Returns>
<Comments>
<RemoveEmptyDoubleSlashComments> True </RemoveEmptyDoubleSlashComments>
<RemoveEmptyCurlyBraceComments> True </RemoveEmptyCurlyBraceComments>
</Comments>
<Capitalisation>
<Enabled> True </Enabled>
<ReservedWords> 1 </ReservedWords>
<Operators> 1 </Operators>
<Directives> 1 </Directives>
<Constants> 1 </Constants>
<Types> 1 </Types>
</Capitalisation>
<SpecificWordCaps>
<Enabled> True </Enabled>
<Words> </Words>
</SpecificWordCaps>
<Identifiers>
<Enabled> True </Enabled>
<Words> ActivePage, AnsiCompareStr, AnsiCompareText, AnsiUpperCase, AsBoolean, AsDateTime, AsFloat, AsInteger, Assign, AsString, AsVariant, BeginDrag, Buttons, Caption, Checked, Classes, ClassName, Clear, Close, Components, Controls, Count, Create, Data, Dec, Delete, Destroy, Dialogs, Enabled, EndDrag, EOF, Exception, Execute, False, FieldByName, First, Forms, Free, FreeAndNil, GetFirstChild, Graphics, Height, idAbort, idCancel, idIgnore, IDispatch, idNo, idOk, idRetry, idYes, Inc, Initialize, IntToStr, ItemIndex, IUnknown, Lines, Math, MaxValue, mbAbort, mbAll, mbCancel, mbHelp, mbIgnore, mbNo, mbOK, mbRetry, mbYes, mbYesToAll, Messages, MinValue, mnNoToAll, mrAbort, mrAll, mrCancel, mrIgnore, mrNo, mrNone, mrNoToAll, mrOk, mrRetry, mrYes, mrYesToAll, mtConfirmation, mtCustom, mtError, mtInformation, mtWarning, Name, Next, Open, Ord, ParamStr, PChar, Perform, ProcessMessages, Read, ReadOnly, RecordCount, Register, Release, Result, Sender, SetFocus, Show, ShowMessage, Source, StdCtrls, StrToInt, SysUtils, TAutoObject, TButton, TComponent, TDataModule, Text, TForm, TFrame, TList, TNotifyEvent, TObject, TObjectList, TPageControl, TPersistent, True, TStringList, TStrings, TTabSheet, Unassigned, Value, Visible, WideString, Width, Windows, Write </Words>
</Identifiers>
<NotIdent>
<Enabled> True </Enabled>
<Words> False, Name, nil, PChar, Read, ReadOnly, True, WideString, Write </Words>
</NotIdent>
<UnitNameCaps>
<Enabled> True </Enabled>
<Words> ActnColorMaps, ActnCtrls, ActnList, ActnMan, ActnMenus, ActnPopup, ActnRes, ADOConst, ADODB, ADOInt, AppEvnts, AxCtrls, BandActn, bdeconst, bdemts, Buttons, CheckLst, Classes, Clipbrd.pas, CmAdmCtl, ComCtrls, ComStrs, Consts, Controls, CtlConsts, CtlPanel, CustomizeDlg, DataBkr, DB, DBActns, dbcgrids, DBClient, DBClientActnRes, DBClientActns, DBCommon, DBConnAdmin, DBConsts, DBCtrls, DbExcept, DBGrids, DBLocal, DBLocalI, DBLogDlg, dblookup, DBOleCtl, DBPWDlg, DBTables, DBXpress, DdeMan, Dialogs, DrTable, DSIntf, ExtActns, ExtCtrls, ExtDlgs, FileCtrl, FMTBcd, Forms, Graphics, GraphUtil, Grids, HTTPIntr, IB, IBBlob, IBCustomDataSet, IBDatabase, IBDatabaseInfo, IBDCLConst, IBErrorCodes, IBEvents, IBExternals, IBExtract, IBGeneratorEditor, IBHeader, IBIntf, IBQuery, IBRestoreEditor, IBSecurityEditor, IBServiceEditor, IBSQL, IBSQLMonitor, IBStoredProc, IBTable, IBUpdateSQL, IBUtils, IBXConst, ImgList, Jcl8087, JclAbstractContainers, JclAlgorithms, JclAnsiStrings, JclAppInst, JclArrayLists, JclArraySets, JclBase, JclBinaryTrees, JclBorlandTools, JclCIL, JclCLR, JclCOM, JclComplex, JclCompression, JclConsole, JclContainerIntf, JclCounter, JclDateTime, JclDebug, JclDotNet, JclEDI, JclEDI_ANSIX12, JclEDI_ANSIX12_Ext, JclEDI_UNEDIFACT, JclEDI_UNEDIFACT_Ext, JclEDISEF, JclEDITranslators, JclEDIXML, JclExprEval, JclFileUtils, JclFont, JclGraphics, JclGraphUtils, JclHashMaps, JclHashSets, JclHookExcept, JclIniFiles, JclLANMan, JclLinkedLists, JclLocales, JclLogic, JclMapi, JclMath, JclMetadata, JclMIDI, JclMime, JclMiscel, JclMsdosSys, JclMultimedia, JclNTFS, JclPCRE, JclPeImage, JclPrint, JclQGraphics, JclQGraphUtils, JclQueues, JclRegistry, JclResources, JclRTTI, JclSchedule, JclSecurity, JclShell, JclSimpleXml, JclStacks, JclStatistics, JclStreams, JclStrHashMap, JclStringLists, JclStrings, JclStructStorage, JclSvcCtrl, JclSynch, JclSysInfo, JclSysUtils, JclTask, JclTD32, JclUnicode, JclUnitConv, JclUnitVersioning, JclUnitVersioningProviders, JclValidation, JclVectors, JclWideFormat, JclWideStrings, JclWin32, JclWin32Ex, JclWinMIDI, ListActns, Mask, MConnect, Menus, Midas, MidasCon, MidConst, MPlayer, MtsRdm, Mxconsts, ObjBrkr, OleAuto, OleConst, OleCtnrs, OleCtrls, OleDB, OleServer, Outline, Printers, Provider, recerror, ScktCnst, ScktComp, ScktMain, SConnect, ShadowWnd, SimpleDS, SMINTF, SqlConst, SqlExpr, SqlTimSt, StdActnMenus, StdActns, StdCtrls, StdStyleActnCtrls, SvcMgr, SysUtils, TabNotBk, Tabs, TConnect, Themes, ToolWin, ValEdit, VDBConsts, WinHelpViewer, XPActnCtrls, XPMan, XPStyleActnCtrls </Words>
</UnitNameCaps>
<Asm>
<Caps> 0 </Caps>
<BreaksAfterLabel> 0 </BreaksAfterLabel>
<BreaksAfterLabelEnabled> False </BreaksAfterLabelEnabled>
<StatementIndentEnabled> False </StatementIndentEnabled>
<StatementIndent> 0 </StatementIndent>
<ParamsIndentEnabled> False </ParamsIndentEnabled>
<ParamsIndent> 0 </ParamsIndent>
</Asm>
<PreProcessor>
<Enabled> True </Enabled>
<DefinedSymbols> DELPHI5_UP, MSWINDOWS </DefinedSymbols>
<DefinedOptions> </DefinedOptions>
</PreProcessor>
<Align>
<AlignAssign> True </AlignAssign>
<AlignConst> True </AlignConst>
<AlignTypedef> True </AlignTypedef>
<AlignVars> True </AlignVars>
<AlignComment> True </AlignComment>
<AlignFields> True </AlignFields>
<InterfaceOnly> False </InterfaceOnly>
<MinColumn> 2 </MinColumn>
<MaxColumn> 60 </MaxColumn>
<MaxVariance> 1 </MaxVariance>
<MaxVarianceInterface> 10 </MaxVarianceInterface>
<MaxUnalignedStatements> 0 </MaxUnalignedStatements>
</Align>
<Replace>
<Enabled> False </Enabled>
<Words> </Words>
</Replace>
<Uses>
<RemoveEnabled> False </RemoveEnabled>
<InsertInterfaceEnabled> False </InsertInterfaceEnabled>
<InsertImplementationEnabled> False </InsertImplementationEnabled>
<FindReplaceEnabled> False </FindReplaceEnabled>
<Remove> </Remove>
<InsertInterface> </InsertInterface>
<InsertImplementation> </InsertImplementation>
<Find> </Find>
<Replace> </Replace>
</Uses>
<Transform>
<BeginEndStyle> 1 </BeginEndStyle>
<AddBlockEndSemicolon> True </AddBlockEndSemicolon>
<SortUsesInterface> False </SortUsesInterface>
<SortUsesImplmentation> False </SortUsesImplmentation>
<SortUsesProgram> False </SortUsesProgram>
<SortUsesBreakOnReturn> False </SortUsesBreakOnReturn>
<SortUsesBreakOnComment> True </SortUsesBreakOnComment>
<SortUsesSortOrder> 0 </SortUsesSortOrder>
<SortUsesNoComments> False </SortUsesNoComments>
</Transform>
</JediCodeFormatSettings>

36
language-config.json

@ -3,55 +3,64 @@
"show": "C++", "show": "C++",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp11": { "cpp11": {
"show": "C++ 11", "show": "C++ 11",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp17": { "cpp17": {
"show": "C++ 17", "show": "C++ 17",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 8.2.0", "version": "GCC 8.2.0",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp-noilinux": { "cpp-noilinux": {
"show": "C++ (NOI)", "show": "C++ (NOI)",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp11-noilinux": { "cpp11-noilinux": {
"show": "C++ 11 (NOI)", "show": "C++ 11 (NOI)",
"highlight": "cpp", "highlight": "cpp",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp11-clang": { "cpp11-clang": {
"show": "C++ 11 (Clang)", "show": "C++ 11 (Clang)",
"highlight": "cpp", "highlight": "cpp",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"cpp17-clang": { "cpp17-clang": {
"show": "C++ 17 (Clang)", "show": "C++ 17 (Clang)",
"highlight": "cpp", "highlight": "cpp",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp" "editor": "c_cpp",
"format": "cpp"
}, },
"c": { "c": {
"show": "C", "show": "C",
"highlight": "c", "highlight": "c",
"version": "Clang 7.0.1", "version": "Clang 7.0.1",
"editor": "c_cpp" "editor": "c_cpp",
"format": "c"
}, },
"c-noilinux": { "c-noilinux": {
"show": "C (NOI)", "show": "C (NOI)",
"highlight": "c", "highlight": "c",
"version": "GCC 4.8.4 (NOILinux 1.4.1)", "version": "GCC 4.8.4 (NOILinux 1.4.1)",
"editor": "c_cpp" "editor": "c_cpp",
"format": "c"
}, },
"csharp": { "csharp": {
"show": "C#", "show": "C#",
@ -69,13 +78,15 @@
"show": "Java", "show": "Java",
"highlight": "java", "highlight": "java",
"version": "OpenJDK 10.0.2", "version": "OpenJDK 10.0.2",
"editor": "java" "editor": "java",
"format": "java"
}, },
"pascal": { "pascal": {
"show": "Pascal", "show": "Pascal",
"highlight": "pascal", "highlight": "pascal",
"version": "Free Pascal 3.0.4", "version": "Free Pascal 3.0.4",
"editor": "pascal" "editor": "pascal",
"format": "pas"
}, },
"lua": { "lua": {
"show": "Lua", "show": "Lua",
@ -105,7 +116,8 @@
"show": "Node.js", "show": "Node.js",
"highlight": "js", "highlight": "js",
"version": "10.14.0", "version": "10.14.0",
"editor": "javascript" "editor": "javascript",
"format": "js"
}, },
"ruby": { "ruby": {
"show": "Ruby", "show": "Ruby",

54
libs/code_formatter.js

@ -0,0 +1,54 @@
let child_process = require('child_process');
let streamToString = require('stream-to-string');
let tempfile = require('tempfile');
let fs = require('fs-extra');
module.exports = async (code, lang) => {
let timer, result, tempFile;
try {
let process, pascalAddProgram;
if (lang === 'pas') {
tempFile = tempfile('.pas');
if (code.indexOf('program') === -1) {
code = 'program format\n' + code;
pascalAddProgram = true;
}
await fs.writeFile(tempFile, code);
process = child_process.spawn(`${__dirname}/../bin/jcf`, [tempFile, '-inplace']);
} else {
process = child_process.spawn(`clang-format -style="{BasedOnStyle: Google, IndentWidth: 4, AccessModifierOffset: -4, SortIncludes: false, AllowShortIfStatementsOnASingleLine: true, ColumnLimit: 110, Cpp11BracedListStyle: false }" -assume-filename="a.${lang}"`, { shell: true });
process.stdin.setEncoding('utf-8');
process.stdin.write(code);
process.stdin.end();
}
timer = setTimeout(() => process.kill(), 5000);
if (lang === 'pas') {
await streamToString(process.stdout);
result = await fs.readFile(tempFile, 'utf-8');
if (pascalAddProgram) result = result.replace('program format\n', '');
} else {
result = await streamToString(process.stdout);
}
await new Promise((resolve, reject) => {
let exit = code => {
if (code === 0) resolve();
else reject(code);
}
if (process.exitCode !== null) exit(process.exitCode);
else process.on('close', exit);
});
} catch (e) {
console.log(e.stack);
result = null;
}
clearTimeout(timer);
try { if (tempFile) await fs.delete(tempFile); } catch (e) {}
return result;
}

31
models/formatted_code.js

@ -0,0 +1,31 @@
let Sequelize = require('sequelize');
let db = syzoj.db;
let model = db.define('formatted_code', {
key: { type: Sequelize.STRING(50), primaryKey: true },
code: { type: Sequelize.TEXT('medium') }
}, {
timestamps: false,
tableName: 'formatted_code',
indexes: [
{
fields: ['key']
}
]
});
let Model = require('./common');
class FormattedCode extends Model {
static async create(val) {
return FormattedCode.fromRecord(FormattedCode.model.build(Object.assign({
key: "",
code: ""
}, val)));
}
getModel() { return model; }
}
FormattedCode.model = model;
module.exports = FormattedCode;

1
models/user.js

@ -17,6 +17,7 @@ let model = db.define('user', {
is_admin: { type: Sequelize.BOOLEAN }, is_admin: { type: Sequelize.BOOLEAN },
is_show: { type: Sequelize.BOOLEAN }, is_show: { type: Sequelize.BOOLEAN },
public_email: { type: Sequelize.BOOLEAN }, public_email: { type: Sequelize.BOOLEAN },
prefer_formatted_code: { type: Sequelize.BOOLEAN },
sex: { type: Sequelize.INTEGER }, sex: { type: Sequelize.INTEGER },
rating: { type: Sequelize.INTEGER }, rating: { type: Sequelize.INTEGER },

23
modules/problem.js

@ -1,5 +1,6 @@
let Problem = syzoj.model('problem'); let Problem = syzoj.model('problem');
let JudgeState = syzoj.model('judge_state'); let JudgeState = syzoj.model('judge_state');
let FormattedCode = syzoj.model('formatted_code');
let CustomTest = syzoj.model('custom_test'); let CustomTest = syzoj.model('custom_test');
let WaitingJudge = syzoj.model('waiting_judge'); let WaitingJudge = syzoj.model('waiting_judge');
let Contest = syzoj.model('contest'); let Contest = syzoj.model('contest');
@ -9,6 +10,7 @@ let Article = syzoj.model('article');
const Sequelize = require('sequelize'); const Sequelize = require('sequelize');
let Judger = syzoj.lib('judger'); let Judger = syzoj.lib('judger');
let CodeFormatter = syzoj.lib('code_formatter');
app.get('/problems', async (req, res) => { app.get('/problems', async (req, res) => {
try { try {
@ -665,6 +667,27 @@ app.post('/problem/:id/submit', app.multer.fields([{ name: 'answer', maxCount: 1
} }
await judge_state.updateRelatedInfo(true); await judge_state.updateRelatedInfo(true);
if (problem.type !== 'submit-answer' && syzoj.languages[req.body.language].format) {
let key = syzoj.utils.getFormattedCodeKey(judge_state.code, req.body.language);
let formattedCode = await FormattedCode.findOne({
where: {
key: key
}
});
if (!formattedCode) {
let formatted = await CodeFormatter(judge_state.code, syzoj.languages[req.body.language].format);
if (formatted) {
formattedCode = await FormattedCode.create({
key: key,
code: formatted
});
await formattedCode.save();
}
}
}
try { try {
await Judger.judge(judge_state, problem, contest_id ? 3 : 2); await Judger.judge(judge_state, problem, contest_id ? 3 : 2);
judge_state.pending = true; judge_state.pending = true;

16
modules/submission.js

@ -1,4 +1,5 @@
let JudgeState = syzoj.model('judge_state'); let JudgeState = syzoj.model('judge_state');
let FormattedCode = syzoj.model('formatted_code');
let User = syzoj.model('user'); let User = syzoj.model('user');
let Contest = syzoj.model('contest'); let Contest = syzoj.model('contest');
let Problem = syzoj.model('problem'); let Problem = syzoj.model('problem');
@ -147,6 +148,19 @@ app.get('/submission/:id', async (req, res) => {
if (judge.problem.type !== 'submit-answer') { if (judge.problem.type !== 'submit-answer') {
judge.codeLength = judge.code.length; judge.codeLength = judge.code.length;
let key = syzoj.utils.getFormattedCodeKey(judge.code, judge.language);
if (key) {
let formattedCode = await FormattedCode.findOne({
where: {
key: key
}
});
if (formattedCode) {
judge.formattedCode = await syzoj.utils.highlight(formattedCode.code, syzoj.languages[judge.language].highlight);
}
}
judge.code = await syzoj.utils.highlight(judge.code, syzoj.languages[judge.language].highlight); judge.code = await syzoj.utils.highlight(judge.code, syzoj.languages[judge.language].highlight);
} }
@ -155,6 +169,8 @@ app.get('/submission/:id', async (req, res) => {
info: getSubmissionInfo(judge, displayConfig), info: getSubmissionInfo(judge, displayConfig),
roughResult: getRoughResult(judge, displayConfig), roughResult: getRoughResult(judge, displayConfig),
code: (judge.problem.type !== 'submit-answer') ? judge.code.toString("utf8") : '', code: (judge.problem.type !== 'submit-answer') ? judge.code.toString("utf8") : '',
formattedCode: judge.formattedCode ? judge.formattedCode.toString("utf8") : null,
preferFormattedCode: res.locals.user ? res.locals.user.prefer_formatted_code : false,
detailResult: processOverallResult(judge.result, displayConfig), detailResult: processOverallResult(judge.result, displayConfig),
socketToken: (judge.pending && judge.task_id != null) ? jwt.sign({ socketToken: (judge.pending && judge.task_id != null) ? jwt.sign({
taskId: judge.task_id, taskId: judge.task_id,

2
modules/user.js

@ -187,6 +187,8 @@ app.post('/user/:id/edit', async (req, res) => {
user.information = req.body.information; user.information = req.body.information;
user.sex = req.body.sex; user.sex = req.body.sex;
user.public_email = (req.body.public_email === 'on'); user.public_email = (req.body.public_email === 'on');
console.log(req.body);
user.prefer_formatted_code = (req.body.prefer_formatted_code === 'on');
await user.save(); await user.save();

2
package.json

@ -60,7 +60,9 @@
"sequelize": "^4.41.2", "sequelize": "^4.41.2",
"session-file-store": "^1.0.0", "session-file-store": "^1.0.0",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
"stream-to-string": "^1.1.0",
"syzoj-divine": "^1.0.2", "syzoj-divine": "^1.0.2",
"tempfile": "^2.0.0",
"tmp-promise": "^1.0.3", "tmp-promise": "^1.0.3",
"waliyun": "^3.1.1", "waliyun": "^3.1.1",
"winston": "^3.1.0", "winston": "^3.1.0",

6
utility.js

@ -98,6 +98,12 @@ module.exports = {
else res.suffix = res.suffix.replace('iB', ''); else res.suffix = res.suffix.replace('iB', '');
return res.fixed + ' ' + res.suffix; return res.fixed + ' ' + res.suffix;
}, },
getFormattedCodeKey(code, lang) {
if (syzoj.languages[lang].format) {
return syzoj.languages[lang].format + '\n' + syzoj.utils.md5(code);
}
return null;
},
judgeServer(suffix) { judgeServer(suffix) {
return JSON.stringify(url.resolve(syzoj.config.judge_server_addr, suffix)); return JSON.stringify(url.resolve(syzoj.config.judge_server_addr, suffix));
}, },

32
views/submission.ejs

@ -51,7 +51,18 @@
</tbody> </tbody>
</table> </table>
<code-box :escape="false" v-bind:content="code"></code-box> <code-box :escape="false" v-bind:content="code">
<% if (formattedCode !== null) { %>
<a onclick="toggleFormattedCode()" class="ui button" style="position: absolute; top: 0px; right: -4px; border-top-left-radius: 0; border-bottom-right-radius: 0; ">
<template v-if="currentFormatted">
显示原始代码
</template>
<template v-if="!currentFormatted">
格式化代码
</template>
</a>
<% } %>
</code-box>
<code-box v-if="detailResult && detailResult.compile" :escape="false" title="编译信息" v-bind:content="detailResult.compile.message"></code-box> <code-box v-if="detailResult && detailResult.compile" :escape="false" title="编译信息" v-bind:content="detailResult.compile.message"></code-box>
<code-box v-if="detailResult" title="系统信息" :escape="true" v-bind:content="detailResult.systemMessage"></code-box> <code-box v-if="detailResult" title="系统信息" :escape="true" v-bind:content="detailResult.systemMessage"></code-box>
@ -125,6 +136,7 @@
<strong v-html="title"></strong> <strong v-html="title"></strong>
</p> </p>
<div class="ui existing segment"> <div class="ui existing segment">
<slot></slot>
<pre v-if="escape" style="margin-top: 0; margin-bottom: 0; "><code>{{ content }}</code></pre> <pre v-if="escape" style="margin-top: 0; margin-bottom: 0; "><code>{{ content }}</code></pre>
<pre v-if="!escape" style="margin-top: 0; margin-bottom: 0; "><code v-html="content"></code></pre> <pre v-if="!escape" style="margin-top: 0; margin-bottom: 0; "><code v-html="content"></code></pre>
</div> </div>
@ -134,7 +146,7 @@
<script> <script>
Vue.component("code-box", { Vue.component("code-box", {
template: "#codeBoxTemplate", template: "#codeBoxTemplate",
props: ['title', 'content', 'escape'], props: ['title', 'content', 'escape']
}); });
const socketUrl = "/detail"; const socketUrl = "/detail";
const displayConfig = <%- JSON.stringify(displayConfig) %>; const displayConfig = <%- JSON.stringify(displayConfig) %>;
@ -175,6 +187,19 @@ const TaskStatus = {};
TaskStatus[TaskStatus["Skipped"] = 4] = "Skipped"; TaskStatus[TaskStatus["Skipped"] = 4] = "Skipped";
})(TaskStatus); })(TaskStatus);
const unformattedCode = <%- JSON.stringify(code) %>;
const formattedCode = <%- JSON.stringify(formattedCode) %>;
function toggleFormattedCode() {
if (vueApp.currentFormatted) {
vueApp.currentFormatted = false;
vueApp.code = unformattedCode;
} else {
vueApp.currentFormatted = true;
vueApp.code = formattedCode;
}
}
const vueApp = new Vue({ const vueApp = new Vue({
el: '#vueAppFuckSafari', el: '#vueAppFuckSafari',
data: { data: {
@ -184,7 +209,8 @@ const vueApp = new Vue({
running: false, running: false,
displayConfig: displayConfig displayConfig: displayConfig
}, },
code: <%- JSON.stringify(code) %>, code: <%- JSON.stringify(preferFormattedCode && formattedCode !== null) -%> ? formattedCode : unformattedCode,
currentFormatted: <%- JSON.stringify(preferFormattedCode && formattedCode !== null) -%>,
detailResult: <%- JSON.stringify(detailResult) %>, detailResult: <%- JSON.stringify(detailResult) %>,
displayConfig: displayConfig, displayConfig: displayConfig,
}, },

7
views/user_edit.ejs

@ -30,6 +30,13 @@
<div class="ui toggle checkbox"> <div class="ui toggle checkbox">
<input id="public_email" name="public_email" type="checkbox" <% if (edited_user.public_email) { %> checked<% } %>> <input id="public_email" name="public_email" type="checkbox" <% if (edited_user.public_email) { %> checked<% } %>>
<label> </label> <label> </label>
</div>
</div>
<div class="inline field">
<label class="ui header">默认显示格式化后的代码(如果可用)</label>
<div class="ui toggle checkbox">
<input id="prefer_formatted_code" name="prefer_formatted_code" type="checkbox" <% if (edited_user.prefer_formatted_code) { %> checked<% } %>>
<label> </label>
</div> </div>
</div> </div>
<div class="field"> <div class="field">

Loading…
Cancel
Save