diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js index ca70826..93a0633 100644 --- a/src/components/Blockly/BlocklyWindow.js +++ b/src/components/Blockly/BlocklyWindow.js @@ -38,7 +38,6 @@ class BlocklyWindow extends Component { } render() { - console.log(this.props.initialXml); return ( diff --git a/src/components/Tutorial/SolutionCheck.js b/src/components/Tutorial/SolutionCheck.js index bf05749..6e2eefc 100644 --- a/src/components/Tutorial/SolutionCheck.js +++ b/src/components/Tutorial/SolutionCheck.js @@ -8,6 +8,7 @@ import * as Blockly from 'blockly/core'; import Compile from '../Compile'; import { tutorials } from './tutorials'; +import { checkXml } from './compareXml'; import { withStyles } from '@material-ui/core/styles'; import IconButton from '@material-ui/core/IconButton'; @@ -49,7 +50,7 @@ class SolutionCheck extends Component { check = () => { const workspace = Blockly.getMainWorkspace(); - var msg = tutorials[this.props.currentTutorialId].test(workspace); + var msg = checkXml(tutorials[this.props.currentTutorialId].solution, this.props.xml); this.props.tutorialCheck(msg.type); this.setState({ msg, open: true }); } @@ -97,13 +98,16 @@ class SolutionCheck extends Component { }; } + SolutionCheck.propTypes = { tutorialCheck: PropTypes.func.isRequired, - currentTutorialId: PropTypes.number + currentTutorialId: PropTypes.number, + xml: PropTypes.string.isRequired }; const mapStateToProps = state => ({ - currentTutorialId: state.tutorial.currentId + currentTutorialId: state.tutorial.currentId, + xml: state.workspace.code.xml }); export default connect(mapStateToProps, { tutorialCheck })(withStyles(styles, {withTheme: true})(SolutionCheck)); diff --git a/src/components/Tutorial/Tutorial.js b/src/components/Tutorial/Tutorial.js index 710db70..cba3ba7 100644 --- a/src/components/Tutorial/Tutorial.js +++ b/src/components/Tutorial/Tutorial.js @@ -43,7 +43,6 @@ class Tutorial extends Component { render() { var currentTutorialId = this.props.currentTutorialId; - console.log(this.props); return ( !Number.isInteger(currentTutorialId) || currentTutorialId+1 < 1 || currentTutorialId+1 > tutorials.length ? diff --git a/src/components/Tutorial/compareXml.js b/src/components/Tutorial/compareXml.js new file mode 100644 index 0000000..5ca4619 --- /dev/null +++ b/src/components/Tutorial/compareXml.js @@ -0,0 +1,78 @@ +export const checkXml = (originalXmlString, userXmlString) => { + var originalXml = parseXml(originalXmlString); + var userXml = parseXml(userXmlString); + return compareXml(originalXml, userXml); +}; + +const parseXml = (xmlString) => { + var parser = new DOMParser(); + var xmlDoc = parser.parseFromString(xmlString, "text/xml"); + return xmlDoc; +}; + +const compareNumberOfBlocks = (originalBlocks, userBlocks) => { + if(originalBlocks.length !== userBlocks.length){ + if(originalBlocks.length > userBlocks.length){ + return {text: 'Es wurden zu wenig Blöcke verwendet.', type: 'error'}; + } + else { + return {text: 'Es wurden zu viele Blöcke verwendet.', type: 'error'}; + } + } +}; + +const compareBlockType = (originalBlock, userBlock, index) => { + if(originalBlock.attributes['type'].value !== userBlock.attributes['type'].value){ + return {text: `Es wurde ein falscher Blocktyp an Position ${index+1} verwendet`, type: 'error'}; + } +}; + +const compareParentBlock = (originalBlock, userBlock, index) => { + // using parentNode instead of parenElement + // see https://stackoverflow.com/questions/8685739/difference-between-dom-parentnode-and-parentelement + if(originalBlock.parentNode.attributes['name']){ + if(userBlock.parentNode.attributes['name']){ + // do the blocks have the same name-properties? + if(originalBlock.parentNode.attributes['name'].value !== userBlock.parentNode.attributes['name'].value){ + if(userBlock.parentNode.attributes['name'].value === 'LOOP_FUNC' || userBlock.parentNode.attributes['name'].value === 'SETUP_FUNC'){ + return {text: `Der Block mit dem Typen '${userBlock.attributes['type'].value}' wurde irrtümlicherweise in die ${userBlock.parentNode.attributes['name'].value === 'SETUP_FUNC' ? 'Setup' : 'Endlosschleifen'}-Funktion geschrieben. + Verschiebe den gesamten Block (und alle dazugehörigen Blöcke) in die ${userBlock.parentNode.attributes['name'].value !== 'SETUP_FUNC' ? 'Setup' : 'Endlosschleifen'}-Funktion.`, type: 'error'}; + } + // TODO: has a block two name-properties? + return {text: `Der Block mit dem Typen '${userBlock.attributes['type'].value}' hat ein falsches 'name'-Attribut`, type: 'error'}; + } + } + // user-block has not a name-attribute + else { + // do the user-block has a xmlns-attribute -> user-block is not connected + if(userBlock.parentNode.attributes['xmlns']){ + return {text: `Der Block mit dem Typen '${userBlock.attributes['type'].value}' hat keine Verbindung zu einem anderen Block.`, type: 'error'}; + } + // user-block has not a xmlns- AND name-attribute + else { + return {text: `Der Block an Position ${index+1} ist falsch eingeordnet. Tipp: Block an Position ${index+1} einem vorherigen Block unterordnen.`, type: 'error'}; + } + } + } +}; + +const compareXml = (originalXml, userXml) => { + var originalItemList = originalXml.getElementsByTagName("block"); + var userItemList = userXml.getElementsByTagName("block"); + + // compare number of blocks + var number = compareNumberOfBlocks(originalItemList, userItemList); + if(number){return number;} + + for(var i=0; i < originalItemList.length; i++){ + // compare type + var type = compareBlockType(originalItemList[i], userItemList[i], i); + if(type){return type;} + + // compare name + var parent = compareParentBlock(originalItemList[i], userItemList[i], i); + if(parent){return parent;} + } + + return {text: 'Super. Alles richtig!', type: 'success'}; +}; diff --git a/src/components/Tutorial/tutorials.js b/src/components/Tutorial/tutorials.js index e16d078..5cdc203 100644 --- a/src/components/Tutorial/tutorials.js +++ b/src/components/Tutorial/tutorials.js @@ -18,6 +18,23 @@ export const tutorials = [ ` }, + "solution": ` + + + + + + + + TRUE + + + + + + + + `, "test": function(workspace){ var wifi = workspace.getBlocksByType('sensebox_wifi'); // result is an array with Blocks as objects if(wifi.length > 0){