From 8bf3bda682da447d50543bc4e18ccf0a7a47300b Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Wed, 10 Jan 2018 01:06:54 +0100
Subject: [PATCH 1/6] Add resubmit (debug mode) button to reference solution.
---
.../ReferenceSolution/ReferenceSolution.js | 22 ++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/pages/ReferenceSolution/ReferenceSolution.js b/src/pages/ReferenceSolution/ReferenceSolution.js
index 296bdb8fa..55bb64952 100644
--- a/src/pages/ReferenceSolution/ReferenceSolution.js
+++ b/src/pages/ReferenceSolution/ReferenceSolution.js
@@ -59,6 +59,7 @@ class ReferenceSolution extends Component {
params: { exerciseId, referenceSolutionId },
refreshSolutionEvaluations,
evaluateReferenceSolution,
+ evaluateReferenceSolutionInDebugMode,
intl: { formatMessage },
links: { EXERCISES_URI, EXERCISE_URI_FACTORY }
} = this.props;
@@ -166,6 +167,22 @@ class ReferenceSolution extends Component {
defaultMessage="Resubmit"
/>
}
+ {permissionHints &&
+ permissionHints.evaluate !== false &&
+ }
@@ -202,6 +219,7 @@ ReferenceSolution.propTypes = {
loadAsync: PropTypes.func.isRequired,
refreshSolutionEvaluations: PropTypes.func.isRequired,
evaluateReferenceSolution: PropTypes.func.isRequired,
+ evaluateReferenceSolutionInDebugMode: PropTypes.func.isRequired,
referenceSolutions: ImmutablePropTypes.map,
intl: intlShape.isRequired,
links: PropTypes.object.isRequired
@@ -219,7 +237,9 @@ export default withLinks(
dispatch(fetchReferenceSolutions(params.exerciseId));
},
evaluateReferenceSolution: () =>
- dispatch(evaluateReferenceSolution(params.referenceSolutionId))
+ dispatch(evaluateReferenceSolution(params.referenceSolutionId)),
+ evaluateReferenceSolutionInDebugMode: () =>
+ dispatch(evaluateReferenceSolution(params.referenceSolutionId, true))
})
)(ReferenceSolution)
)
From 9e8151c9f638c1f7bcc46b897c36da5e7fcd2410 Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Wed, 10 Jan 2018 01:32:08 +0100
Subject: [PATCH 2/6] Improving simple user container appearance.
---
.../UsersNameContainer/UsersNameContainer.css | 18 ++++++++++++++++--
.../UsersNameContainer/UsersNameContainer.js | 5 +++--
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/src/containers/UsersNameContainer/UsersNameContainer.css b/src/containers/UsersNameContainer/UsersNameContainer.css
index c28d7074b..001cc26ca 100644
--- a/src/containers/UsersNameContainer/UsersNameContainer.css
+++ b/src/containers/UsersNameContainer/UsersNameContainer.css
@@ -1,5 +1,19 @@
.simpleName {
- margin-left: 4px;
- margin-right: 4px;
white-space: nowrap;
}
+
+.simpleName:after {
+ content: ', ';
+}
+
+.simpleName:first-of-type {
+ margin-left: 2px;
+}
+
+.simpleName:last-of-type {
+ margin-right: 3px;
+}
+
+.simpleName:last-of-type:after {
+ content: '';
+}
diff --git a/src/containers/UsersNameContainer/UsersNameContainer.js b/src/containers/UsersNameContainer/UsersNameContainer.js
index 13a62e0ad..ab27d5ed1 100644
--- a/src/containers/UsersNameContainer/UsersNameContainer.js
+++ b/src/containers/UsersNameContainer/UsersNameContainer.js
@@ -11,6 +11,7 @@ import UsersName, {
LoadingUsersName,
FailedUsersName
} from '../../components/Users/UsersName';
+import { LoadingIcon, FailedIcon } from '../../components/icons';
import './UsersNameContainer.css';
@@ -35,8 +36,8 @@ class UsersNameContainer extends Component {
return (
}
- failed={}
+ loading={isSimple ? : }
+ failed={isSimple ? : }
>
{user =>
isSimple
From 76072522e6ed938b04db5a772d5da77525336cf3 Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Wed, 10 Jan 2018 01:56:19 +0100
Subject: [PATCH 3/6] Fixing minor bug on Exercises page.
---
src/pages/Exercises/Exercises.js | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/pages/Exercises/Exercises.js b/src/pages/Exercises/Exercises.js
index 05d206a76..988331d46 100644
--- a/src/pages/Exercises/Exercises.js
+++ b/src/pages/Exercises/Exercises.js
@@ -129,22 +129,22 @@ class Exercises extends Component {
/>
}
footer={
- isSuperAdmin &&
-
+ {isSuperAdmin &&
+ }
}
unlimitedHeight
From 28c844946ee7225b7d55515bee6df91e4c8651b1 Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Wed, 10 Jan 2018 15:32:36 +0100
Subject: [PATCH 4/6] Make last name in group hierarchy panel also a link
---
src/components/Groups/HierarchyLine/HierarchyLine.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/components/Groups/HierarchyLine/HierarchyLine.js b/src/components/Groups/HierarchyLine/HierarchyLine.js
index 53f70b2ef..9e5cb6eef 100644
--- a/src/components/Groups/HierarchyLine/HierarchyLine.js
+++ b/src/components/Groups/HierarchyLine/HierarchyLine.js
@@ -1,12 +1,14 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Well } from 'react-bootstrap';
+import Icon from 'react-fontawesome';
import GroupsNameContainer from '../../../containers/GroupsNameContainer';
import './HierarchyLine.css';
const HierarchyLine = ({ groupId, parentGroupsIds }) =>
+
{parentGroupsIds.map(
(groupId, i) =>
i !== 0 &&
@@ -15,7 +17,7 @@ const HierarchyLine = ({ groupId, parentGroupsIds }) =>
/
)}
-
+
;
HierarchyLine.propTypes = {
From 039816e1ce9ecaadb6c9b642092c58302279aace Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Fri, 12 Jan 2018 01:33:32 +0100
Subject: [PATCH 5/6] Fixing bud in simple config edit form. Change of
environments now correctly resubmits config form as well.
---
.../EditExerciseSimpleConfigForm.js | 96 ++++++++++---------
.../EditSimpleLimitsForm.js | 40 ++++----
src/helpers/exerciseSimpleForm.js | 72 +++++++-------
.../EditExerciseSimpleConfig.js | 70 ++++++++------
4 files changed, 154 insertions(+), 124 deletions(-)
diff --git a/src/components/forms/EditExerciseSimpleConfigForm/EditExerciseSimpleConfigForm.js b/src/components/forms/EditExerciseSimpleConfigForm/EditExerciseSimpleConfigForm.js
index 9d19c27cc..2bfa740ad 100644
--- a/src/components/forms/EditExerciseSimpleConfigForm/EditExerciseSimpleConfigForm.js
+++ b/src/components/forms/EditExerciseSimpleConfigForm/EditExerciseSimpleConfigForm.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { reduxForm, getFormValues } from 'redux-form';
import { connect } from 'react-redux';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl } from 'react-intl';
import { Alert } from 'react-bootstrap';
import FormBox from '../../widgets/FormBox';
@@ -30,7 +30,8 @@ const EditExerciseSimpleConfigForm = ({
formErrors,
supplementaryFiles,
exerciseTests,
- smartFill
+ smartFill,
+ intl: { locale }
}) =>
{(...files) =>
- {exerciseTests.map((test, idx) =>
-
- )}
+ {exerciseTests
+ .sort((a, b) => a.name.localeCompare(b.name, locale))
+ .map((test, idx) =>
+
+ )}
}
;
@@ -142,7 +145,8 @@ EditExerciseSimpleConfigForm.propTypes = {
formErrors: PropTypes.object,
supplementaryFiles: ImmutablePropTypes.map,
exerciseTests: PropTypes.array,
- smartFill: PropTypes.func.isRequired
+ smartFill: PropTypes.func.isRequired,
+ intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired
};
const FORM_NAME = 'editExerciseSimpleConfig';
@@ -193,32 +197,34 @@ const validate = formData => {
: undefined;
};
-export default connect(
- (state, { exercise }) => {
- const getSupplementaryFilesForExercise = createGetSupplementaryFiles(
- exercise.supplementaryFilesIds
- );
- return {
- supplementaryFiles: getSupplementaryFilesForExercise(state),
- formValues: getFormValues(FORM_NAME)(state),
- formErrors: exerciseConfigFormErrors(state, FORM_NAME)
- };
- },
- dispatch => ({
- smartFill: (testId, tests, files) => () =>
- dispatch(smartFillExerciseConfigForm(FORM_NAME, testId, tests, files))
- })
-)(
- reduxForm({
- form: FORM_NAME,
- enableReinitialize: true,
- keepDirtyOnReinitialize: false,
- immutableProps: [
- 'formValues',
- 'supplementaryFiles',
- 'exerciseTests',
- 'handleSubmit'
- ],
- validate
- })(EditExerciseSimpleConfigForm)
+export default injectIntl(
+ connect(
+ (state, { exercise }) => {
+ const getSupplementaryFilesForExercise = createGetSupplementaryFiles(
+ exercise.supplementaryFilesIds
+ );
+ return {
+ supplementaryFiles: getSupplementaryFilesForExercise(state),
+ formValues: getFormValues(FORM_NAME)(state),
+ formErrors: exerciseConfigFormErrors(state, FORM_NAME)
+ };
+ },
+ dispatch => ({
+ smartFill: (testId, tests, files) => () =>
+ dispatch(smartFillExerciseConfigForm(FORM_NAME, testId, tests, files))
+ })
+ )(
+ reduxForm({
+ form: FORM_NAME,
+ enableReinitialize: true,
+ keepDirtyOnReinitialize: false,
+ immutableProps: [
+ 'formValues',
+ 'supplementaryFiles',
+ 'exerciseTests',
+ 'handleSubmit'
+ ],
+ validate
+ })(EditExerciseSimpleConfigForm)
+ )
);
diff --git a/src/components/forms/EditSimpleLimitsForm/EditSimpleLimitsForm.js b/src/components/forms/EditSimpleLimitsForm/EditSimpleLimitsForm.js
index c560f8fe9..4cb229df7 100644
--- a/src/components/forms/EditSimpleLimitsForm/EditSimpleLimitsForm.js
+++ b/src/components/forms/EditSimpleLimitsForm/EditSimpleLimitsForm.js
@@ -1,7 +1,7 @@
import React from 'react';
import { Alert, Table } from 'react-bootstrap';
import PropTypes from 'prop-types';
-import { FormattedMessage } from 'react-intl';
+import { FormattedMessage, injectIntl } from 'react-intl';
import { reduxForm } from 'redux-form';
import { EditSimpleLimitsField } from '../Fields';
@@ -31,7 +31,8 @@ const EditSimpleLimitsForm = ({
submitting,
submitFailed,
submitSucceeded,
- invalid
+ invalid,
+ intl: { locale }
}) =>
- {tests.map(test =>
+ {tests.sort((a, b) => a.name.localeCompare(b.name, locale)).map(test =>
{test.name}
@@ -181,7 +182,8 @@ EditSimpleLimitsForm.propTypes = {
submitting: PropTypes.bool,
submitFailed: PropTypes.bool,
submitSucceeded: PropTypes.bool,
- invalid: PropTypes.bool
+ invalid: PropTypes.bool,
+ intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired
};
const validate = ({ limits }) => {
@@ -232,17 +234,19 @@ const validate = ({ limits }) => {
return errors;
};
-export default reduxForm({
- form: 'editSimpleLimits',
- enableReinitialize: true,
- keepDirtyOnReinitialize: false,
- immutableProps: [
- 'environments',
- 'tests',
- 'cloneHorizontally',
- 'cloneVertically',
- 'cloneAll',
- 'handleSubmit'
- ],
- validate
-})(EditSimpleLimitsForm);
+export default injectIntl(
+ reduxForm({
+ form: 'editSimpleLimits',
+ enableReinitialize: true,
+ keepDirtyOnReinitialize: false,
+ immutableProps: [
+ 'environments',
+ 'tests',
+ 'cloneHorizontally',
+ 'cloneVertically',
+ 'cloneAll',
+ 'handleSubmit'
+ ],
+ validate
+ })(EditSimpleLimitsForm)
+);
diff --git a/src/helpers/exerciseSimpleForm.js b/src/helpers/exerciseSimpleForm.js
index 23783d8cf..1a4ef97c4 100644
--- a/src/helpers/exerciseSimpleForm.js
+++ b/src/helpers/exerciseSimpleForm.js
@@ -5,35 +5,9 @@ import {
encodeEnvironmentId
} from '../redux/modules/simpleLimits';
-export const getEnvInitValues = environmentConfigs => {
- let res = {};
- for (const env of environmentConfigs) {
- res[env.runtimeEnvironmentId] = true;
- }
- return res;
-};
-
-export const transformAndSendEnvValues = (
- formData,
- environments,
- editEnvironmentConfigs,
- reloadConfigAndLimits
-) => {
- let res = [];
- for (const env in formData) {
- if (formData[env] !== true && formData[env] !== 'true') {
- continue;
- }
- let envObj = { runtimeEnvironmentId: env };
- const currentFullEnv = environments.find(e => e.id === env);
- envObj.variablesTable = currentFullEnv.defaultVariables;
- res.push(envObj);
- }
- return editEnvironmentConfigs({ environmentConfigs: res }).then(
- reloadConfigAndLimits
- );
-};
-
+/*
+ * Tests and Score
+ */
export const getTestsInitValues = (exerciseTests, scoreConfig, locale) => {
const jsonScoreConfig = yaml.safeLoad(scoreConfig);
const testWeights = jsonScoreConfig.testWeights || {};
@@ -81,7 +55,39 @@ export const transformAndSendTestsValues = (
]);
};
-export const getSimpleConfigInitValues = (config, tests, locale) => {
+/*
+ * Environments
+ */
+export const getEnvInitValues = environmentConfigs => {
+ let res = {};
+ for (const env of environmentConfigs) {
+ res[env.runtimeEnvironmentId] = true;
+ }
+ return res;
+};
+
+export const transformEnvValues = (
+ formData,
+ environments,
+ editEnvironmentConfigs
+) => {
+ let res = [];
+ for (const env in formData) {
+ if (formData[env] !== true && formData[env] !== 'true') {
+ continue;
+ }
+ let envObj = { runtimeEnvironmentId: env };
+ const currentFullEnv = environments.find(e => e.id === env);
+ envObj.variablesTable = currentFullEnv.defaultVariables;
+ res.push(envObj);
+ }
+ return res;
+};
+
+/*
+ * Configuration variables
+ */
+export const getSimpleConfigInitValues = (config, tests) => {
const confTests =
tests && config[0] && config[0].tests ? config[0].tests : [];
@@ -191,6 +197,7 @@ export const transformAndSendConfigValues = (
pipelines,
environments,
tests,
+ originalConfig,
setConfig
) => {
let testVars = [];
@@ -305,9 +312,8 @@ export const transformAndSendConfigValues = (
return setConfig({ config: envs });
};
-/**
- * Assemble data from all simpleLimits environments into one table.
- * Also ensures proper encoding for environment IDs and test names, which are used as keys.
+/*
+ * Memory and Time limits
*/
export const getLimitsInitValues = (
limits,
diff --git a/src/pages/EditExerciseSimpleConfig/EditExerciseSimpleConfig.js b/src/pages/EditExerciseSimpleConfig/EditExerciseSimpleConfig.js
index 0c537c2fb..b92da1500 100644
--- a/src/pages/EditExerciseSimpleConfig/EditExerciseSimpleConfig.js
+++ b/src/pages/EditExerciseSimpleConfig/EditExerciseSimpleConfig.js
@@ -62,7 +62,7 @@ import { pipelinesSelector } from '../../redux/selectors/pipelines';
import {
getEnvInitValues,
- transformAndSendEnvValues,
+ transformEnvValues,
getTestsInitValues,
transformAndSendTestsValues,
getSimpleConfigInitValues,
@@ -213,22 +213,42 @@ class EditExerciseSimpleConfig extends Component {
>
- {(environmentConfigs, ...environments) =>
-
- transformAndSendEnvValues(
- data,
- environments,
- editEnvironmentConfigs,
- reloadConfigAndLimits(exercise.id)
- )}
- />}
+ {(config, tests, environmentConfigs, ...pipelines) =>
+
+ {(...environments) =>
+ {
+ const newEnvironments = transformEnvValues(
+ data,
+ environments
+ );
+ return editEnvironmentConfigs({
+ environmentConfigs: newEnvironments
+ })
+ .then(() =>
+ transformAndSendConfigValues(
+ getSimpleConfigInitValues(config, tests),
+ pipelines,
+ newEnvironments,
+ tests,
+ config,
+ setConfig
+ )
+ )
+ .then(reloadConfigAndLimits(exercise.id));
+ }}
+ />}
+ }
@@ -248,25 +268,22 @@ class EditExerciseSimpleConfig extends Component {
...pipelines.toArray()
]}
>
- {(config, tests, environments, ...pipelines) => {
- const sortedTests = tests.sort((a, b) =>
- a.name.localeCompare(b.name, locale)
- );
- return tests.length > 0
+ {(config, tests, environments, ...pipelines) =>
+ tests.length > 0
?
transformAndSendConfigValues(
data,
pipelines,
environments,
- sortedTests,
+ tests,
+ config,
setConfig
)}
/>
@@ -282,8 +299,7 @@ class EditExerciseSimpleConfig extends Component {
id="app.editExerciseSimpleConfig.noTests"
defaultMessage="There are no tests yet. The form cannot be displayed until at least one test is created."
/>
- ;
- }}
+ }
@@ -309,9 +325,7 @@ class EditExerciseSimpleConfig extends Component {
editEnvironmentSimpleLimits
)}
environments={exercise.runtimeEnvironments}
- tests={tests.sort((a, b) =>
- a.name.localeCompare(b.name, locale)
- )}
+ tests={tests}
initialValues={getLimitsInitValues(
limits,
tests,
From f00e9f86c59a4203a63d0ba09f1a91ffef71c081 Mon Sep 17 00:00:00 2001
From: Martin Krulis
Date: Sat, 13 Jan 2018 01:46:18 +0100
Subject: [PATCH 6/6] Refactoring of exerciseSimpleForm functions. Making sure
that the configuration which is not handled by simple form is not lost when
form is saved.
---
src/helpers/exerciseSimpleForm.js | 333 ++++++++++++++++--------------
1 file changed, 173 insertions(+), 160 deletions(-)
diff --git a/src/helpers/exerciseSimpleForm.js b/src/helpers/exerciseSimpleForm.js
index 1a4ef97c4..ac993f830 100644
--- a/src/helpers/exerciseSimpleForm.js
+++ b/src/helpers/exerciseSimpleForm.js
@@ -87,6 +87,77 @@ export const transformEnvValues = (
/*
* Configuration variables
*/
+
+// Configure simple variables using mapping between name and testObj property.
+// Object has the same properites as testObj and values are variable names.
+const simpleConfigVariablesMapping = {
+ expectedOutput: 'expected-output',
+ runArgs: 'run-args',
+ outputFile: 'actual-output',
+ stdinFile: 'stdin-file',
+ judgeBinary: 'judge-type',
+ customJudgeBinary: 'custom-judge',
+ judgeArgs: 'judge-args'
+};
+
+// Variable types as they should be sent back to API
+const simpleConfigVariablesTypes = {
+ 'expected-output': 'remote-file',
+ 'run-args': 'string[]',
+ 'actual-output': 'file',
+ 'stdin-file': 'remote-file',
+ 'judge-type': 'string',
+ 'custom-judge': 'remote-file',
+ 'judge-args': 'string[]',
+ 'input-files': 'remote-file[]',
+ 'actual-inputs': 'file[]'
+};
+
+// Fetch one simple variable (string or array) and fill it into the testObj under selected property.
+const getSimpleConfigSimpleVariable = (
+ variables,
+ testObj,
+ variableName,
+ propertyName
+) => {
+ const variable = variables.find(variable => variable.name === variableName);
+ const isArray = variable && variable.type && variable.type.endsWith('[]');
+ if (isArray) {
+ testObj[propertyName] = []; // array needs default
+ }
+ if (variable) {
+ let value = variable.value;
+ if (isArray && !value) {
+ value = [];
+ } else if (!isArray) {
+ value = value.trim();
+ }
+ testObj[propertyName] = isArray && !Array.isArray(value) ? [value] : value;
+ }
+};
+
+// Get input files and their corresponding actual names (and fill them to testObj).
+const getSimpleConfigInputFiles = (variables, testObj) => {
+ const inputFiles = variables.find(
+ variable => variable.name === 'input-files'
+ );
+ const actualInputs = variables.find(
+ variable => variable.name === 'actual-inputs'
+ );
+ if (inputFiles) {
+ testObj.inputFiles = inputFiles.value
+ ? inputFiles.value.map((value, i) => ({
+ file: value,
+ name:
+ actualInputs && actualInputs.value && actualInputs.value[i]
+ ? actualInputs.value[i].trim()
+ : ''
+ }))
+ : [];
+ }
+};
+
+// Prepare the initial form data for configuration form ...
export const getSimpleConfigInitValues = (config, tests) => {
const confTests =
tests && config[0] && config[0].tests ? config[0].tests : [];
@@ -104,92 +175,82 @@ export const getSimpleConfigInitValues = (config, tests) => {
)
: [];
- const inputFiles = variables.find(
- variable => variable.name === 'input-files'
- );
- const actualInputs = variables.find(
- variable => variable.name === 'actual-inputs'
- );
- if (inputFiles) {
- testObj.inputFiles = inputFiles.value
- ? inputFiles.value.map((value, i) => ({
- file: value,
- name:
- actualInputs && actualInputs.value && actualInputs.value[i]
- ? actualInputs.value[i].trim()
- : ''
- }))
- : [];
- }
+ // Fetch values from variables and fill them to testObj.
+ getSimpleConfigInputFiles(variables, testObj);
- const expectedOutput = variables.find(
- variable => variable.name === 'expected-output'
- );
- if (expectedOutput) {
- testObj.expectedOutput = expectedOutput.value;
+ for (const property in simpleConfigVariablesMapping) {
+ getSimpleConfigSimpleVariable(
+ variables,
+ testObj,
+ simpleConfigVariablesMapping[property],
+ property
+ );
}
- const runArgs = variables.find(variable => variable.name === 'run-args');
- testObj.runArgs = [];
- if (runArgs && runArgs.value) {
- testObj.runArgs = Array.isArray(runArgs.value)
- ? runArgs.value
- : [runArgs.value];
+ // Additional updates after simple variables were set
+ testObj.useOutFile = testObj.outputFile !== '';
+ testObj.useCustomJudge = testObj.customJudgeBinary !== '';
+ if (testObj.useCustomJudge) {
+ testObj.judgeBinary = '';
+ } else if (!testObj.judgeBinary) {
+ testObj.judgeBinary = 'recodex-judge-normal';
}
- const actualOutput = variables.find(
- variable => variable.name === 'actual-output'
- );
- if (actualOutput && actualOutput.value && actualOutput.value.trim()) {
- testObj.useOutFile = true;
- testObj.outputFile = actualOutput.value.trim();
- } else {
- testObj.useOutFile = false;
- testObj.outputFile = '';
- }
+ res[encodeTestId(test.id)] = testObj;
+ }
- const stdinFile = variables.find(
- variable => variable.name === 'stdin-file'
- );
- if (stdinFile) {
- testObj.inputStdin = stdinFile.value;
- }
+ return { config: res };
+};
- const standardJudge = variables.find(
- variable => variable.name === 'judge-type'
- );
- const customJudge = variables.find(
- variable => variable.name === 'custom-judge'
- );
+// Prepare one variable to be sent in to the API
+const transformConfigSimpleVariable = (variables, name, value) => {
+ variables.push({ name, type: simpleConfigVariablesTypes[name], value });
+};
- testObj.useCustomJudge = false;
- testObj.customJudgeBinary = '';
- testObj.judgeBinary = '';
- if (customJudge && customJudge.value) {
- testObj.customJudgeBinary = customJudge.value;
- testObj.useCustomJudge = true;
- }
- if (!testObj.useCustomJudge) {
- testObj.judgeBinary =
- standardJudge && standardJudge.value
- ? standardJudge.value
- : 'recodex-judge-normal';
- }
+const transformConfigInputFiles = (variables, test) => {
+ let inputFiles = [];
+ let renamed = [];
+ const inFilesArr =
+ test.inputFiles && Array.isArray(test.inputFiles) ? test.inputFiles : [];
- const judgeArgs = variables.find(
- variable => variable.name === 'judge-args'
- );
- testObj.judgeArgs = [];
- if (judgeArgs && judgeArgs.value) {
- testObj.judgeArgs = Array.isArray(judgeArgs.value)
- ? judgeArgs.value
- : [judgeArgs.value];
- }
+ for (const item of inFilesArr) {
+ inputFiles.push(item.file);
+ renamed.push(item.name.trim());
+ }
- res[encodeTestId(test.id)] = testObj;
+ transformConfigSimpleVariable(variables, 'input-files', inputFiles);
+ transformConfigSimpleVariable(variables, 'actual-inputs', renamed);
+};
+
+// Prepare variables for execution pipeline of one test in one environment
+const transformConfigTestExecutionVariables = test => {
+ // Final updates ...
+ if (!test.useCustomJudge) {
+ test.customJudgeBinary = '';
+ }
+ test.outputFile = test.useOutFile ? test.outputFile.trim() : '';
+
+ // Prepare variables for the config
+ let variables = [];
+ for (const property in simpleConfigVariablesMapping) {
+ transformConfigSimpleVariable(
+ variables,
+ simpleConfigVariablesMapping[property],
+ test[property]
+ );
}
- return { config: res };
+ transformConfigInputFiles(variables, test);
+
+ return variables;
+};
+
+const mergeOriginalVariables = (newVars, origVars) => {
+ origVars.forEach(ov => {
+ if (!newVars.find(nv => nv.name === ov.name)) {
+ newVars.push(ov); // add missing variable
+ }
+ });
};
export const transformAndSendConfigValues = (
@@ -200,76 +261,6 @@ export const transformAndSendConfigValues = (
originalConfig,
setConfig
) => {
- let testVars = [];
- for (let t of tests) {
- const testName = t.id;
- const test = formData.config[encodeTestId(testName)];
- let variables = [];
-
- variables.push({
- name: 'custom-judge',
- type: 'remote-file',
- value: test.useCustomJudge ? test.customJudgeBinary : ''
- });
- variables.push({
- name: 'expected-output',
- type: 'remote-file',
- value: test.expectedOutput
- });
- variables.push({
- name: 'judge-type',
- type: 'string',
- value: test.judgeBinary
- });
- variables.push({
- name: 'stdin-file',
- type: 'remote-file',
- value: test.inputStdin
- });
- variables.push({
- name: 'judge-args',
- type: 'string[]',
- value: test.judgeArgs
- });
- variables.push({
- name: 'run-args',
- type: 'string[]',
- value: test.runArgs
- });
- if (test.useOutFile) {
- variables.push({
- name: 'actual-output',
- type: 'file',
- value: test.useOutFile ? test.outputFile.trim() : ''
- });
- }
-
- let inputFiles = [];
- let renamedNames = [];
- const inFilesArr =
- test.inputFiles && Array.isArray(test.inputFiles) ? test.inputFiles : [];
- for (const item of inFilesArr) {
- inputFiles.push(item.file);
- renamedNames.push(item.name.trim());
- }
- variables.push({
- name: 'input-files',
- type: 'remote-file[]',
- value: inputFiles
- });
- variables.push({
- name: 'actual-inputs',
- type: 'file[]',
- value: renamedNames
- });
-
- testVars.push({
- name: testName,
- variables: variables,
- producesFiles: test.useOutFile
- });
- }
-
let envs = [];
for (const environment of environments) {
const envId = environment.runtimeEnvironmentId;
@@ -277,28 +268,50 @@ export const transformAndSendConfigValues = (
pipeline => pipeline.runtimeEnvironmentIds.indexOf(envId) >= 0
);
+ // Find the right pipelines ...
+ const compilationPipeline = envPipelines.find(
+ pipeline => pipeline.parameters.isCompilationPipeline
+ );
+ const executionPipelineStdout = envPipelines.find(
+ pipeline =>
+ pipeline.parameters.isExecutionPipeline &&
+ pipeline.parameters.producesStdout
+ );
+ const executionPipelineFiles = envPipelines.find(
+ pipeline =>
+ pipeline.parameters.isExecutionPipeline &&
+ pipeline.parameters.producesFiles
+ );
+
+ // Create configuration for all tests ...
let testsCfg = [];
- for (const testVar of testVars) {
- const compilationPipelineId = envPipelines.filter(
- pipeline => pipeline.parameters.isCompilationPipeline
- )[0].id;
- const executionPipelineId = envPipelines.filter(
- pipeline =>
- pipeline.parameters.isExecutionPipeline &&
- (testVar.producesFiles
- ? pipeline.parameters.producesFiles
- : pipeline.parameters.producesStdout)
- )[0].id;
+ for (const t of tests) {
+ const testName = t.id;
+ const test = formData.config[encodeTestId(testName)];
+ const executionPipeline = test.useOutFile
+ ? executionPipelineFiles
+ : executionPipelineStdout;
+
+ const testVars = transformConfigTestExecutionVariables(test);
+
+ // Get original values so they wont get lost ...
+ const originalPipelines = originalConfig
+ .find(config => config.name === envId) // config for the right environment
+ .tests.find(test => test.name === testName).pipelines; // and the right test
+ const origCompilationVars = originalPipelines[0].variables; // the first pipeline is for compilation
+ const origExecutionVars = originalPipelines[1].variables; // the second pipeline is for execution
+ mergeOriginalVariables(testVars, origExecutionVars);
+
testsCfg.push({
- name: testVar.name,
+ name: testName,
pipelines: [
{
- name: compilationPipelineId,
- variables: []
+ name: compilationPipeline.id,
+ variables: origCompilationVars // copied from original config
},
{
- name: executionPipelineId,
- variables: testVar.variables
+ name: executionPipeline.id,
+ variables: testVars // TODO merge with original config
}
]
});
|