checking the Blocks with the solution using the XML strings

This commit is contained in:
Delucse 2020-09-10 13:46:31 +02:00
parent f14508a5ca
commit ab016610bd
6 changed files with 102 additions and 8 deletions

View File

@ -38,7 +38,6 @@ class BlocklyWindow extends Component {
}
render() {
console.log(this.props.initialXml);
return (
<BlocklyComponent ref={this.simpleWorkspace}
style={this.props.blocklyCSS}

View File

@ -2,8 +2,6 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as Blockly from 'blockly/core';
import BlocklyWindow from '../Blockly/BlocklyWindow';
import { tutorials } from './tutorials';
@ -15,7 +13,6 @@ class Instruction extends Component {
render() {
var currentTutorialId = this.props.currentTutorialId;
console.log(currentTutorialId);
return (
tutorials[currentTutorialId].instruction ?
<div>

View File

@ -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));

View File

@ -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 ?
<NotFound button={{title: 'Zurück zur Tutorials-Übersicht', link: '/tutorial'}}/>

View File

@ -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'};
};

View File

@ -18,6 +18,23 @@ export const tutorials = [
</block>
</xml>`
},
"solution": `<xml xmlns="https://developers.google.com/blockly/xml">
<block type="arduino_functions" id="QWW|$jB8+*EL;}|#uA" deletable="false" x="37" y="20">
<statement name="LOOP_FUNC">
<block type="sensebox_telegram_do" id="K%yUabqRVQ{]9eX-8jZD">
<statement name="telegram_do">
<block type="controls_if" id="rA6:!p7,{y2MOuVpv[Pm">
<value name="IF0">
<block type="logic_boolean" id="=[Zh}O6_)fl?JD#2)2bL">
<field name="BOOL">TRUE</field>
</block>
</value>
</block>
</statement>
</block>
</statement>
</block>
</xml>`,
"test": function(workspace){
var wifi = workspace.getBlocksByType('sensebox_wifi'); // result is an array with Blocks as objects
if(wifi.length > 0){