+
{data.report !== undefined && (
-
-
- {data.report}
-
+
+
+
{data.decision} FILE
)}
+
+
{data.fileName}
+
+ Sensitivity Level {data.sensitivityLevel}
+
+
+
- );
- }
-}
+ {data.report !== undefined && (
+
+
+ {data.report}
+
+
+ )}
+
+ );
+};
export default File;
diff --git a/client/src/components/exercise/lab7/components/ProgressBar.js b/client/src/components/exercise/lab7/components/ProgressBar.js
index 2c06817af..83d43922e 100644
--- a/client/src/components/exercise/lab7/components/ProgressBar.js
+++ b/client/src/components/exercise/lab7/components/ProgressBar.js
@@ -1,40 +1,32 @@
-import React, { Component } from "react";
+import React from "react";
import { READ_TIME } from "../../../../constants/lab7";
import PropTypes from "prop-types";
-class ProgressBar extends Component {
- constructor(props) {
- super(props);
- }
-
+const ProgressBar = ({ text, seconds }) => {
/**
* Calculates the width of the progress bar, utilizing the current seconds, and the starting seconds.
*
* @returns {number} width of the progress bar
*/
- calculateWidth = () => {
- const { seconds } = this.props;
+ const calculateWidth = () => {
return (((seconds - 1) * 1000) / (READ_TIME - 1000)) * 100;
};
- render() {
- const { text, seconds } = this.props;
- return (
-
-
-
+ return (
+
+ );
+};
export default ProgressBar;
diff --git a/client/src/components/exercise/lab7/components/Simulation.js b/client/src/components/exercise/lab7/components/Simulation.js
index 60d6ed3f3..d538c9da4 100644
--- a/client/src/components/exercise/lab7/components/Simulation.js
+++ b/client/src/components/exercise/lab7/components/Simulation.js
@@ -1,391 +1,392 @@
/* eslint-disable react/prop-types */
-import React, {Component} from "react";
+import React, { Component } from "react";
import UserLabService from "../../../../services/UserLabService";
import "../../../../assets/stylesheets/components/Simulation.scss";
import {
- AI_CORRECT,
- AI_INCORRECT,
- DELAY_TIME,
- FILE_INCORRECT,
- FILE_INTRUSION,
- FILE_PROTECTED,
- LAB_ID,
- LOCKED_FILE,
- MESSAGES,
- OPEN_FILE,
- READ_TIME,
- ROUND_LIMIT,
- SCORE_MAP,
- THREAT_LEVEL_TEXT,
- THREAT_MAX,
+ AI_CORRECT,
+ AI_INCORRECT,
+ DELAY_TIME,
+ FILE_INCORRECT,
+ FILE_INTRUSION,
+ FILE_PROTECTED,
+ LAB_ID,
+ LOCKED_FILE,
+ MESSAGES,
+ OPEN_FILE,
+ READ_TIME,
+ ROUND_LIMIT,
+ SCORE_MAP,
+ THREAT_LEVEL_TEXT,
+ THREAT_MAX,
} from "../../../../constants/lab7";
-import {navigate} from "@reach/router";
-import {generateList} from "./data/files";
+import { navigate } from "@reach/router";
+import { generateList } from "./data/files";
import Countdown from "react-countdown-now";
import ProgressBar from "./ProgressBar";
import File from "./File";
-import {connect} from "react-redux";
-import {bindActionCreators} from "redux";
-import {actions as exerciseActions} from "../../../../reducers/lab7/ExerciseReducer";
+import { connect } from "react-redux";
+import { bindActionCreators } from "redux";
+import { actions as exerciseActions } from "../../../../reducers/lab7/ExerciseReducer";
import RepairService from "../../../../services/lab7/RepairService";
class Simulation extends Component {
- constructor(props) {
- super(props);
- this.state = {
- files: [],
- message: "",
- countdownComponent: null,
- counter: -1,
- };
- }
+ constructor(props) {
+ super(props);
+ this.state = {
+ files: [],
+ message: "",
+ countdownComponent: null,
+ counter: -1,
+ };
+ }
- componentDidMount() {
- this.startSimulation();
- }
+ componentDidMount() {
+ this.startSimulation();
+ }
- startSimulation() {
- this.startRound();
- }
+ startSimulation() {
+ this.startRound();
+ }
- /**
- * Logic handling the transition of rounds.
- *
- * As long as we have not reached the round limit, calculate a random threat level,
- * update the round number, generate a new list of files, update the states accordingly, and
- * store them for the summary report.
- *
- * Otherwise, transition to the simulation summary.
- */
- startRound() {
- const {roundNumber, handlers, user, repairId} = this.props;
- if (roundNumber < ROUND_LIMIT) {
- const threatLvl = this.randomizeThreat();
- handlers.startNewRound();
- const files = this.generateFileList(threatLvl);
- this.setState({files, counter: 0});
- handlers.addResults({files, threatLvl});
- } else {
- UserLabService.complete_exercise(LAB_ID);
- if (user?.firstname !== null && user !== null) {
- UserLabService.user_complete_exercise(user.userid, LAB_ID);
- }
- RepairService.updateReport(repairId, this.formatReport());
- navigate("/Lab7/Exercise/SimulationSummary");
- }
+ /**
+ * Logic handling the transition of rounds.
+ *
+ * As long as we have not reached the round limit, calculate a random threat level,
+ * update the round number, generate a new list of files, update the states accordingly, and
+ * store them for the summary report.
+ *
+ * Otherwise, transition to the simulation summary.
+ */
+ startRound() {
+ const { roundNumber, handlers, user, repairId } = this.props;
+ if (roundNumber < ROUND_LIMIT) {
+ const threatLvl = this.randomizeThreat();
+ handlers.startNewRound();
+ const files = this.generateFileList(threatLvl);
+ this.setState({ files, counter: 0 });
+ handlers.addResults({ files, threatLvl });
+ } else {
+ UserLabService.complete_exercise(LAB_ID);
+ if (user?.firstname !== null && user !== null) {
+ UserLabService.user_complete_exercise(user.userid, LAB_ID);
+ }
+ if (repairId !== null)
+ RepairService.updateReport(repairId, this.formatReport());
+ navigate("/Lab7/Exercise/SimulationSummary");
}
+ }
- formatReport() {
- const {results} = this.props;
- return results.map(({threatLvl, files}) => {
- return {
- threatLvl,
- intrusions: files.filter((file) => file.result === FILE_INTRUSION)
- .length,
- protected: files.filter((file) => file.result === FILE_PROTECTED)
- .length,
- incorrect: files.filter((file) => file.result === FILE_INCORRECT)
- .length,
- };
- });
- }
+ formatReport() {
+ const { results } = this.props;
+ return results.map(({ threatLvl, files }) => {
+ return {
+ threatLvl,
+ intrusions: files.filter((file) => file.result === FILE_INTRUSION)
+ .length,
+ protected: files.filter((file) => file.result === FILE_PROTECTED)
+ .length,
+ incorrect: files.filter((file) => file.result === FILE_INCORRECT)
+ .length,
+ };
+ });
+ }
- /**
- * Calculates a random threat level for the round updates the state.
- *
- * @returns {number} random threat level
- */
- randomizeThreat() {
- const {handlers} = this.props;
- const threatLvl = Math.floor(Math.random() * THREAT_MAX) + 1;
- handlers.updateThreatLevel(threatLvl);
- return threatLvl;
- }
+ /**
+ * Calculates a random threat level for the round updates the state.
+ *
+ * @returns {number} random threat level
+ */
+ randomizeThreat() {
+ const { handlers } = this.props;
+ const threatLvl = Math.floor(Math.random() * THREAT_MAX) + 1;
+ handlers.updateThreatLevel(threatLvl);
+ return threatLvl;
+ }
- makeDecision(threatLvl, file) {
- const makeDecisionFunction =
- this.props.makeDecision ?? this.defaultMakeDecision.bind(this);
- return makeDecisionFunction(threatLvl, file);
- }
+ makeDecision(threatLvl, file) {
+ const makeDecisionFunction =
+ this.props.makeDecision ?? this.defaultMakeDecision.bind(this);
+ return makeDecisionFunction(threatLvl, file);
+ }
- defaultMakeDecision(threatLvl, file) {
- return threatLvl >= file.sensitivityLevel ? LOCKED_FILE : OPEN_FILE;
- }
+ defaultMakeDecision(threatLvl, file) {
+ return threatLvl >= file.sensitivityLevel ? LOCKED_FILE : OPEN_FILE;
+ }
- /**
- * Generate a list of random files from existing data.
- *
- * The utility and AIs decision is calculated. Results are added to the file object and the
- * file object is added to the list of files.
- *
- * @param threatLvl pre-calculated threat level of the round
- * @returns {(*&{result: string, decision: string})[]} a list of file objects
- */
- generateFileList(threatLvl) {
- return generateList().map((file) => {
- const decision = this.makeDecision(threatLvl, file);
- return {
- ...file,
- decision,
- result: this.evaluateAIDecision(file, decision, threatLvl),
- };
- });
- }
+ /**
+ * Generate a list of random files from existing data.
+ *
+ * The utility and AIs decision is calculated. Results are added to the file object and the
+ * file object is added to the list of files.
+ *
+ * @param threatLvl pre-calculated threat level of the round
+ * @returns {(*&{result: string, decision: string})[]} a list of file objects
+ */
+ generateFileList(threatLvl) {
+ return generateList().map((file) => {
+ const decision = this.makeDecision(threatLvl, file);
+ return {
+ ...file,
+ decision,
+ result: this.evaluateAIDecision(file, decision, threatLvl),
+ };
+ });
+ }
- /**
- * Evaluates the AIs decision-making based on the utility equation.
- *
- * @param file current file being evaluated
- * @param decision AIs decision based on utility
- * @param threatLvl pre-calculated threat level of the round
- * @returns {string|string} `FILE_PROTECTED` | `FILE_INCORRECT` | `FILE_INTRUSION`
- */
- evaluateAIDecision(file, decision, threatLvl) {
- const {sensitivityLevel} = file;
- let expected;
- switch (threatLvl) {
- case 1:
- expected = sensitivityLevel === 1 ? LOCKED_FILE : OPEN_FILE;
- break;
- case 2:
- expected =
- sensitivityLevel === 2 || sensitivityLevel === 3
- ? LOCKED_FILE
- : OPEN_FILE;
- break;
- case 3:
- expected =
- sensitivityLevel === 4 || sensitivityLevel === 5
- ? LOCKED_FILE
- : OPEN_FILE;
- break;
- }
- if (decision !== expected)
- return expected === OPEN_FILE && decision === LOCKED_FILE
- ? FILE_INCORRECT
- : FILE_INTRUSION;
- return FILE_PROTECTED;
+ /**
+ * Evaluates the AIs decision-making based on the utility equation.
+ *
+ * @param file current file being evaluated
+ * @param decision AIs decision based on utility
+ * @param threatLvl pre-calculated threat level of the round
+ * @returns {string|string} `FILE_PROTECTED` | `FILE_INCORRECT` | `FILE_INTRUSION`
+ */
+ evaluateAIDecision(file, decision, threatLvl) {
+ const { sensitivityLevel } = file;
+ let expected;
+ switch (threatLvl) {
+ case 1:
+ expected = sensitivityLevel === 1 ? LOCKED_FILE : OPEN_FILE;
+ break;
+ case 2:
+ expected =
+ sensitivityLevel === 2 || sensitivityLevel === 3
+ ? LOCKED_FILE
+ : OPEN_FILE;
+ break;
+ case 3:
+ expected =
+ sensitivityLevel === 4 || sensitivityLevel === 5
+ ? LOCKED_FILE
+ : OPEN_FILE;
+ break;
}
+ if (decision !== expected)
+ return expected === OPEN_FILE && decision === LOCKED_FILE
+ ? FILE_INCORRECT
+ : FILE_INTRUSION;
+ return FILE_PROTECTED;
+ }
- /**
- * React method that is invoked whenever a state/prop is updated.
- *
- * @param prevProps values of props prior to update
- * @param prevState values of states prior to update
- * @param snapshot required for method signature
- */
- // eslint-disable-next-line no-unused-vars
- componentDidUpdate(prevProps, prevState, snapshot) {
- /* Counter was incremented */
- if (prevState.counter !== this.state.counter) {
- /* Counter is within range of being incremented again */
- if (this.state.counter < this.state.files.length) {
- const {handlers} = this.props;
- const {counter, files} = this.state;
- switch (files[counter].result) {
- case FILE_PROTECTED:
- this.handleProtected();
- break;
- case FILE_INTRUSION:
- this.handleIntrusion();
- break;
- case FILE_INCORRECT:
- this.handleIncorrect();
- break;
- default:
- break;
- }
- handlers.incrementScore(SCORE_MAP[files[counter].result]);
- } else {
- /* End of round */
- const result = this.handlePerfectScore();
- setTimeout(() => this.startRound(), result ? READ_TIME : 0);
- }
+ /**
+ * React method that is invoked whenever a state/prop is updated.
+ *
+ * @param prevProps values of props prior to update
+ * @param prevState values of states prior to update
+ * @param snapshot required for method signature
+ */
+ // eslint-disable-next-line no-unused-vars
+ componentDidUpdate(prevProps, prevState, snapshot) {
+ /* Counter was incremented */
+ if (prevState.counter !== this.state.counter) {
+ /* Counter is within range of being incremented again */
+ if (this.state.counter < this.state.files.length) {
+ const { handlers } = this.props;
+ const { counter, files } = this.state;
+ switch (files[counter].result) {
+ case FILE_PROTECTED:
+ this.handleProtected();
+ break;
+ case FILE_INTRUSION:
+ this.handleIntrusion();
+ break;
+ case FILE_INCORRECT:
+ this.handleIncorrect();
+ break;
+ default:
+ break;
}
+ handlers.incrementScore(SCORE_MAP[files[counter].result]);
+ } else {
+ /* End of round */
+ const result = this.handlePerfectScore();
+ setTimeout(() => this.startRound(), result ? READ_TIME : 0);
+ }
}
+ }
- /**
- * Updates `files` and `countdownComponent` states. Invoked for when a message
- * needs to be displayed with progress bar.
- *
- * @param files array of file objects
- * @param message text to be displayed
- */
- handleCountdownComponent(files, message) {
- this.setState({
- files,
- message,
- countdownComponent: (
-
- ),
- });
- /* Unmount countdownComponent and message after read time */
- setTimeout(
- () => this.setState({countdownComponent: null, message: ""}),
- READ_TIME
- );
- }
+ /**
+ * Updates `files` and `countdownComponent` states. Invoked for when a message
+ * needs to be displayed with progress bar.
+ *
+ * @param files array of file objects
+ * @param message text to be displayed
+ */
+ handleCountdownComponent(files, message) {
+ this.setState({
+ files,
+ message,
+ countdownComponent: (
+
+ ),
+ });
+ /* Unmount countdownComponent and message after read time */
+ setTimeout(
+ () => this.setState({ countdownComponent: null, message: "" }),
+ READ_TIME
+ );
+ }
- /**
- * Logic to award bonus points if all files for a round were correctly protected.
- *
- * @returns {boolean} whether the files of a round were perfectly protected
- */
- handlePerfectScore() {
- const {files} = this.state;
- const {handlers} = this.props;
- const filteredFiles = files.filter(
- (file) => file.result === FILE_PROTECTED
- );
- if (filteredFiles.length === files.length) {
- handlers.incrementScore(SCORE_MAP.PERFECT_SCORE);
- this.handleCountdownComponent(files, MESSAGES.Perfect);
- return true;
- }
- return false;
+ /**
+ * Logic to award bonus points if all files for a round were correctly protected.
+ *
+ * @returns {boolean} whether the files of a round were perfectly protected
+ */
+ handlePerfectScore() {
+ const { files } = this.state;
+ const { handlers } = this.props;
+ const filteredFiles = files.filter(
+ (file) => file.result === FILE_PROTECTED
+ );
+ if (filteredFiles.length === files.length) {
+ handlers.incrementScore(SCORE_MAP.PERFECT_SCORE);
+ this.handleCountdownComponent(files, MESSAGES.Perfect);
+ return true;
}
+ return false;
+ }
- /**
- * Logic for when a file was correctly protected.
- */
- handleProtected() {
- const {handlers} = this.props;
- const {counter, files} = this.state;
- files[counter].report = AI_CORRECT;
- this.setState({files});
- handlers.incrementProtected();
- this.incrementCounter();
- }
+ /**
+ * Logic for when a file was correctly protected.
+ */
+ handleProtected() {
+ const { handlers } = this.props;
+ const { counter, files } = this.state;
+ files[counter].report = AI_CORRECT;
+ this.setState({ files });
+ handlers.incrementProtected();
+ this.incrementCounter();
+ }
- /**
- * Logic for when the AIs decision-making resulted in an intrusion.
- */
- handleIntrusion() {
- const {handlers} = this.props;
- const {counter, files} = this.state;
- files[counter].report = AI_INCORRECT;
- files[counter].message = MESSAGES[files[counter].content];
- handlers.incrementIntrusions();
- this.handleCountdownComponent(files, files[counter].message);
- this.incrementCounter(READ_TIME);
- }
+ /**
+ * Logic for when the AIs decision-making resulted in an intrusion.
+ */
+ handleIntrusion() {
+ const { handlers } = this.props;
+ const { counter, files } = this.state;
+ files[counter].report = AI_INCORRECT;
+ files[counter].message = MESSAGES[files[counter].content];
+ handlers.incrementIntrusions();
+ this.handleCountdownComponent(files, files[counter].message);
+ this.incrementCounter(READ_TIME);
+ }
- /**
- * Logic for when the AIs decision-making was incorrect.
- */
- handleIncorrect() {
- const {handlers} = this.props;
- const {counter, files} = this.state;
- files[counter].report = AI_INCORRECT;
- this.setState({files});
- handlers.incrementIncorrect();
- this.incrementCounter();
- }
+ /**
+ * Logic for when the AIs decision-making was incorrect.
+ */
+ handleIncorrect() {
+ const { handlers } = this.props;
+ const { counter, files } = this.state;
+ files[counter].report = AI_INCORRECT;
+ this.setState({ files });
+ handlers.incrementIncorrect();
+ this.incrementCounter();
+ }
- /**
- * Updates the pointer to the file array with a delay.
- *
- * @param delay specified ms delay for updating the counter
- */
- incrementCounter(delay = DELAY_TIME) {
- setTimeout(() => this.setState({counter: this.state.counter + 1}), delay);
- }
+ /**
+ * Updates the pointer to the file array with a delay.
+ *
+ * @param delay specified ms delay for updating the counter
+ */
+ incrementCounter(delay = DELAY_TIME) {
+ setTimeout(() => this.setState({ counter: this.state.counter + 1 }), delay);
+ }
- /**
- * Callback method for a countdown. Used for progress bar.
- *
- * @param seconds time left on the countdown
- * @param completed whether the countdown is complete
- * @returns {JSX.Element} progress bar component
- */
- countdownRenderCallback({seconds, completed}) {
- const {message} = this.state;
- if (completed) return <>>;
- else return
;
- }
+ /**
+ * Callback method for a countdown. Used for progress bar.
+ *
+ * @param seconds time left on the countdown
+ * @param completed whether the countdown is complete
+ * @returns {JSX.Element} progress bar component
+ */
+ countdownRenderCallback({ seconds, completed }) {
+ const { message } = this.state;
+ if (completed) return <>>;
+ else return ;
+ }
- render() {
- const {roundNumber, intrusions, protect, incorrect, score, threatLvl} =
- this.props;
- return (
-
- {/* Header */}
-
- {/* Round Tracker */}
-
-
- Round {roundNumber} of {ROUND_LIMIT}
-
-
- {/* Status Report */}
-
-
- Intrusions:
- Protected (TP):
- Incorrect (FP):
- Total Score:
-
-
- {intrusions}
- {protect}
- {incorrect}
- {score}
-
-
-
- {/* Body */}
-
- {/* Threat Message */}
-
-
- {THREAT_LEVEL_TEXT[threatLvl]} threat detected!
-
-
- {/* File Display */}
-
- {this.state.files.map((file, index) => (
-
- ))}
-
- {/* Countdown component w/ message */}
- {/* When countdown component is not null, it will be rendered */}
- {this.state.countdownComponent}
-
-
- );
- }
+ render() {
+ const { roundNumber, intrusions, protect, incorrect, score, threatLvl } =
+ this.props;
+ return (
+
+ {/* Header */}
+
+ {/* Round Tracker */}
+
+
+ Round {roundNumber} of {ROUND_LIMIT}
+
+
+ {/* Status Report */}
+
+
+ Intrusions:
+ Protected (TP):
+ Incorrect (FP):
+ Total Score:
+
+
+ {intrusions}
+ {protect}
+ {incorrect}
+ {score}
+
+
+
+ {/* Body */}
+
+ {/* Threat Message */}
+
+
+ {THREAT_LEVEL_TEXT[threatLvl]} threat detected!
+
+
+ {/* File Display */}
+
+ {this.state.files.map((file, index) => (
+
+ ))}
+
+ {/* Countdown component w/ message */}
+ {/* When countdown component is not null, it will be rendered */}
+ {this.state.countdownComponent}
+
+
+ );
+ }
}
const mapStateToProps = (state) => {
- const {roundNumber, intrusions, incorrect, score, threatLvl, results} =
- state.exercise7;
- const {makeDecision, repairId} = state.repair7;
- const {user} = state.main;
- return {
- makeDecision,
- repairId,
- user,
- roundNumber,
- score,
- intrusions,
- incorrect,
- threatLvl,
- results,
- protect: state.exercise7.protected,
- };
+ const { roundNumber, intrusions, incorrect, score, threatLvl, results } =
+ state.exercise7;
+ const { makeDecision, repairId } = state.repair7;
+ const { user } = state.main;
+ return {
+ makeDecision,
+ repairId,
+ user,
+ roundNumber,
+ score,
+ intrusions,
+ incorrect,
+ threatLvl,
+ results,
+ protect: state.exercise7.protected,
+ };
};
const mapDispatchToProps = (dispatch) => {
- return {
- handlers: bindActionCreators({...exerciseActions}, dispatch),
- };
+ return {
+ handlers: bindActionCreators({ ...exerciseActions }, dispatch),
+ };
};
export default connect(mapStateToProps, mapDispatchToProps)(Simulation);
diff --git a/client/src/components/exercise/lab7/components/data/files.js b/client/src/components/exercise/lab7/components/data/files.js
index 4d561a43d..058ee6c03 100644
--- a/client/src/components/exercise/lab7/components/data/files.js
+++ b/client/src/components/exercise/lab7/components/data/files.js
@@ -1,4 +1,4 @@
-import {FILE_COUNT} from "../../../../../constants/lab7";
+import { FILE_COUNT } from "../../../../../constants/lab7";
import _ from "lodash";
export const FILES = [
@@ -124,4 +124,4 @@ export const FILES = [
},
];
-export const generateList = () => _.sampleSize(FILES, FILE_COUNT);
\ No newline at end of file
+export const generateList = () => _.sampleSize(FILES, FILE_COUNT);
diff --git a/client/src/components/exercise/lab7/pages/ExerciseStart.js b/client/src/components/exercise/lab7/pages/ExerciseStart.js
index 1b745ec61..d1f6ff56f 100644
--- a/client/src/components/exercise/lab7/pages/ExerciseStart.js
+++ b/client/src/components/exercise/lab7/pages/ExerciseStart.js
@@ -33,11 +33,15 @@ class ExerciseStart extends Component {
- Five files will be displayed on the screen, each of which will have the following:
+ Five files will be displayed on the screen, each of which
+ will have the following:
A file name
Sensitive or nonsensitive content
- A level of sensitivity that is dependent on the contents of the file
+
+ A level of sensitivity that is dependent on the contents of
+ the file
+
An access status assigned by the system
@@ -45,37 +49,44 @@ class ExerciseStart extends Component {
The simulation will consist of ten rounds
- For each round, a threat level will
- be detected in the system
+ For each round, a threat level will be detected in
+ the system
- The system will restrict file access based on the threat level and
- the file‘s sensitivity level :
+ The system will restrict file access based on the{" "}
+ threat level and the{" "}
+ file‘s sensitivity level :
-
-
-
+
+
+
Threat Level
Restricted Files
-
-
-
+
+
+
High
- Sensitivity Levels 4 and 5
+
+ Sensitivity Levels 4 and 5
+
Medium
- Sensitivity Levels 2 and 3
+
+ Sensitivity Levels 2 and 3
+
Low
- Sensitivity Level 1
+
+ Sensitivity Level 1
+
-
-
-
+
+
+
The simulation will notify you of whether the autonomous
system made the correct restriction for each file by
@@ -83,8 +94,8 @@ class ExerciseStart extends Component {
"AI Incorrect" .
- The autonomous system's mistakes can be categorized into
- two types:
+ The autonomous system's mistakes can be categorized
+ into two types:
@@ -92,23 +103,24 @@ class ExerciseStart extends Component {
should have been restricted.
- An incorrect decision , or false positive (FP) ,{" "}
- occurs when a file is restricted when it should have been
- accessible.
+ An incorrect decision , or{" "}
+ false positive (FP) , occurs when a file is
+ restricted when it should have been accessible.
- At the end, a summary report containing all of the information displayed throughout the simulation
- will be displayed
+ At the end, a summary report containing all of the information
+ displayed throughout the simulation will be displayed
- Note : The simulation will be done by the
- autonomous system. You will NOT be able to interact with the simulation once it starts.
+ Note : The simulation will be done by the autonomous system.
+ You will NOT be able to interact with the simulation once it
+ starts.
diff --git a/client/src/components/exercise/lab7/pages/ImproveAICode/AICodeRepair.js b/client/src/components/exercise/lab7/pages/ImproveAICode/AICodeRepair.js
index f210b7e26..3fc882df2 100644
--- a/client/src/components/exercise/lab7/pages/ImproveAICode/AICodeRepair.js
+++ b/client/src/components/exercise/lab7/pages/ImproveAICode/AICodeRepair.js
@@ -1,148 +1,153 @@
-import React, {Component, Fragment} from "react";
+import React, { Component, Fragment } from "react";
import Popup from "../../../shared/Popup";
-import {navigate} from "@reach/router";
+import { navigate } from "@reach/router";
import Code from "../../components/Code";
-import {EXERCISE_PLAYING, LOCKED_FILE, OPEN_FILE,} from "../../../../../constants/lab7";
-import {connect} from "react-redux";
-import {bindActionCreators} from "redux";
-import {actions as repairActions} from "../../../../../reducers/lab7/RepairReducer";
-import {actions as appActions} from "../../../../../reducers/lab7/AppReducer";
-import {actions as exerciseActions} from "../../../../../reducers/lab7/ExerciseReducer";
-import {evaluate} from "mathjs";
+import {
+ EXERCISE_PLAYING,
+ LOCKED_FILE,
+ OPEN_FILE,
+} from "../../../../../constants/lab7";
+import { connect } from "react-redux";
+import { bindActionCreators } from "redux";
+import { actions as repairActions } from "../../../../../reducers/lab7/RepairReducer";
+import { actions as appActions } from "../../../../../reducers/lab7/AppReducer";
+import { actions as exerciseActions } from "../../../../../reducers/lab7/ExerciseReducer";
+import { evaluate } from "mathjs";
import PropTypes from "prop-types";
-import {MathComponent} from "mathjax-react";
+import { MathComponent } from "mathjax-react";
class AICodeRepair extends Component {
- constructor(props) {
- super(props);
- this.state = {
- componentName: "AICodeRepair",
- };
- }
+ constructor(props) {
+ super(props);
+ this.state = {
+ componentName: "AICodeRepair",
+ };
+ }
- componentDidMount() {
- const {actions} = this.props;
- actions.updateState(EXERCISE_PLAYING);
- this.reset();
- }
+ componentDidMount() {
+ const { actions } = this.props;
+ actions.updateState(EXERCISE_PLAYING);
+ this.reset();
+ }
- reset() {
- const {actions} = this.props;
- actions.resetRepair();
- actions.updatePopup("");
- }
+ reset() {
+ const { actions } = this.props;
+ actions.resetRepair();
+ actions.updatePopup("");
+ }
- handleNav() {
- const {actions} = this.props;
- actions.updateMakeDecision(this.updateMakeDecision.bind(this));
- actions.reset();
- navigate("/Lab7/Exercise/ImprovedAISimulation");
- }
+ handleNav() {
+ const { actions } = this.props;
+ actions.updateMakeDecision(this.updateMakeDecision.bind(this));
+ actions.reset();
+ navigate("/Lab7/Exercise/ImprovedAISimulation");
+ }
- updateMakeDecision(threatLvl, file) {
- const {rewardValue, costValue} = this.props;
- const utility = evaluate(`(${rewardValue}) / (${costValue})`, {
- file,
- threatLvl,
- });
- return utility >= 1 ? LOCKED_FILE : OPEN_FILE;
- }
+ updateMakeDecision(threatLvl, file) {
+ const { rewardValue, costValue } = this.props;
+ const utility = evaluate(`(${rewardValue}) / (${costValue})`, {
+ file,
+ threatLvl,
+ });
+ return utility >= 1 ? LOCKED_FILE : OPEN_FILE;
+ }
- render() {
- const {
- repairVisible,
- popupMessage,
- actions,
- repairError,
- changesApplied,
- } = this.props;
+ render() {
+ const {
+ repairVisible,
+ popupMessage,
+ actions,
+ repairError,
+ changesApplied,
+ } = this.props;
- return (
-
-
-
-
-
- We have identified the component of the AI that is
- impacting its decision-making, let‘s take a look into the
- AI and see how it can be improved.
-
-
- In this part of the exercise, you will have the opportunity to improve the accuracy of
- the autonomous file access system.
-
-
- Your goal should be to implement a utility equation into the autonomous system. The
- utility equation is calculated by weighting the reward of a decision and the cost of
- making said decision.
-
-
-
-
- Click the ‘Repair
- ‘ button to view and edit the code of the autonomous system.
-
-
-
-
-
- Repair
-
-
- Next
-
- {repairVisible &&
}
+ return (
+
+
+
+
+
+ We have identified the component of the AI that is impacting its
+ decision-making, let‘s take a look into the AI and see how
+ it can be improved.
+
+
+ In this part of the exercise, you will have the opportunity to
+ improve the accuracy of the autonomous file access system.
+
+
+ Your goal should be to implement a utility equation into the
+ autonomous system. The utility equation is calculated by
+ weighting the reward of a decision and the cost of making said
+ decision.
+
+
- );
- }
+
+ Click the ‘Repair
+ ‘ button to view and edit the code of the autonomous system.
+
+
+
+
+
+ Repair
+
+
+ Next
+
+ {repairVisible &&
}
+
+ );
+ }
}
AICodeRepair.propTypes = {
- actions: PropTypes.object,
- rewardValue: PropTypes.string,
- costValue: PropTypes.string,
- popupMessage: PropTypes.string,
- repairError: PropTypes.string,
- changesApplied: PropTypes.bool,
- repairVisible: PropTypes.bool,
+ actions: PropTypes.object,
+ rewardValue: PropTypes.string,
+ costValue: PropTypes.string,
+ popupMessage: PropTypes.string,
+ repairError: PropTypes.string,
+ changesApplied: PropTypes.bool,
+ repairVisible: PropTypes.bool,
};
const mapStateToProps = (state) => {
- const {popupMessage} = state.app7;
- const {repairError, repairVisible, rewardValue, costValue, changesApplied} =
- state.repair7;
- return {
- popupMessage,
- repairError,
- repairVisible,
- rewardValue,
- costValue,
- changesApplied,
- };
+ const { popupMessage } = state.app7;
+ const { repairError, repairVisible, rewardValue, costValue, changesApplied } =
+ state.repair7;
+ return {
+ popupMessage,
+ repairError,
+ repairVisible,
+ rewardValue,
+ costValue,
+ changesApplied,
+ };
};
const mapDispatchToProps = (dispatch) => {
- return {
- actions: bindActionCreators(
- {...repairActions, ...exerciseActions, ...appActions},
- dispatch
- ),
- };
+ return {
+ actions: bindActionCreators(
+ { ...repairActions, ...exerciseActions, ...appActions },
+ dispatch
+ ),
+ };
};
export default connect(mapStateToProps, mapDispatchToProps)(AICodeRepair);
diff --git a/client/src/components/exercise/lab7/pages/Simulation/BadAIExplanation.js b/client/src/components/exercise/lab7/pages/Simulation/BadAIExplanation.js
index 126a013a2..0b16e7e3b 100644
--- a/client/src/components/exercise/lab7/pages/Simulation/BadAIExplanation.js
+++ b/client/src/components/exercise/lab7/pages/Simulation/BadAIExplanation.js
@@ -1,63 +1,63 @@
-import React, {Component} from "react";
-import {navigate} from "@reach/router";
-import {EXERCISE_PLAYING} from "../../../../../constants/lab7";
-import {bindActionCreators} from "redux";
-import {actions as exerciseActions} from "../../../../../reducers/lab7/ExerciseReducer";
-import {connect} from "react-redux";
+import React, { Component } from "react";
+import { navigate } from "@reach/router";
+import { EXERCISE_PLAYING } from "../../../../../constants/lab7";
+import { bindActionCreators } from "redux";
+import { actions as exerciseActions } from "../../../../../reducers/lab7/ExerciseReducer";
+import { connect } from "react-redux";
import PropTypes from "prop-types";
class BadAIExplanation extends Component {
- constructor(props) {
- super(props);
- this.state = {componentName: "BadAIExplanation"};
- }
+ constructor(props) {
+ super(props);
+ this.state = { componentName: "BadAIExplanation" };
+ }
- componentDidMount() {
- const {actions} = this.props;
- actions.updateState(EXERCISE_PLAYING);
- }
+ componentDidMount() {
+ const { actions } = this.props;
+ actions.updateState(EXERCISE_PLAYING);
+ }
- handleStart() {
- const {actions} = this.props;
- actions.updateState(EXERCISE_PLAYING);
- navigate("/Lab7/Exercise/AICodeRepair");
- }
+ handleStart() {
+ const { actions } = this.props;
+ actions.updateState(EXERCISE_PLAYING);
+ navigate("/Lab7/Exercise/AICodeRepair");
+ }
- render() {
- return (
-
-
- As you can see, the AI made many mistakes when it came to managing
- file access when threats were detected in the system.
-
-
- This is due to the factors of the files that the AI is using to determine in a file‘s
- access should be restricted or not.
-
-
- The AI is currently only using one piece of sensitive information
- within the file to determine the sensitivity of the entire file.
-
-
- Start
-
-
- );
- }
+ render() {
+ return (
+
+
+ As you can see, the AI made many mistakes when it came to managing
+ file access when threats were detected in the system.
+
+
+ This is due to the factors of the files that the AI is using to
+ determine in a file‘s access should be restricted or not.
+
+
+ The AI is currently only using one piece of sensitive information
+ within the file to determine the sensitivity of the entire file.
+
+
+ Start
+
+
+ );
+ }
}
BadAIExplanation.propTypes = {
- actions: PropTypes.object,
+ actions: PropTypes.object,
};
const mapDispatchToProps = (dispatch) => {
- return {
- actions: bindActionCreators({...exerciseActions}, dispatch),
- };
+ return {
+ actions: bindActionCreators({ ...exerciseActions }, dispatch),
+ };
};
export default connect(null, mapDispatchToProps)(BadAIExplanation);
diff --git a/client/src/services/lab7/ExerciseService.js b/client/src/services/lab7/ExerciseService.js
index 5adf214e3..f70a8ea74 100644
--- a/client/src/services/lab7/ExerciseService.js
+++ b/client/src/services/lab7/ExerciseService.js
@@ -9,7 +9,7 @@ const endpoints = {
const ExerciseService = {
submitRepair: (report, userId) => {
return API.postWithBody(
- process.env.REACT_APP_SERVER_URL + endpoints.SUBMIT_REPORT,
+ `${process.env.REACT_APP_SERVER_URL}${endpoints.SUBMIT_REPORT}`,
{
report,
userId,
diff --git a/client/src/services/lab7/RepairService.js b/client/src/services/lab7/RepairService.js
index 23309b87b..b7091fc13 100644
--- a/client/src/services/lab7/RepairService.js
+++ b/client/src/services/lab7/RepairService.js
@@ -10,13 +10,13 @@ const endpoints = {
const RepairService = {
submitRepair: (activity, repair) => {
return API.postWithBody(
- process.env.REACT_APP_SERVER_URL + endpoints.SUBMIT_REPAIR,
+ `${process.env.REACT_APP_SERVER_URL}${endpoints.SUBMIT_REPAIR}`,
{ activity, repair }
);
},
updateReport: (repairId, report) => {
return API.postWithBody(
- process.env.REACT_APP_SERVER_URL + endpoints.UPDATE_REPORT,
+ `${process.env.REACT_APP_SERVER_URL}${endpoints.UPDATE_REPORT}`,
{ repairId, report }
);
},