I basically have two types of blocks: a rule block and a fact block (just like in Prolog). They can both be attached to each other. The rule block expects two inputs of the type 'fact'.
However, it should not be possible to have multiple attached fact blocks as a single input. Therefore I had to set 'setNextStatement' to false whenever a fact block is attached as input of a rule block.
This is what I tried to do in the fact block:
this.setOnChange(function(changeEvent) {
if(changeEvent.type == Blockly.Events.MOVE) {
let prevBlock = this.getPreviousBlock();
if(prevBlock != null && prevBlock.type == "rule") {
let nextBlock = prevBlock.getNextBlock();
if((nextBlock != null && nextBlock != this) || (nextBlock == null)) {
this.setNextStatement(false);
}
} else {
this.setNextStatement(true);
}
}
});
And of course the rule block:
Blockly.Blocks['rule'] = {
init: function() {
this.appendDummyInput("RULE_DATA")
.appendField('Rule: ');
this.appendStatementInput('INPUT_HEAD')
.setCheck("fact")
.appendField("Head");
this.appendStatementInput('INPUT_BODY')
.setCheck("fact")
.appendField("Body");
...
This actually works, but when I separate a fact from the input part of a rule, I always get the following error:
Uncaught Error: Connection lists did not match in length.
at Blockly.BlockSvg.Blockly.Block.getMatchingConnection (blockly_compressed.js:1447)
at Blockly.InsertionMarkerManager.connectMarker_ (blockly_compressed.js:1125)
at Blockly.InsertionMarkerManager.showPreview_ (blockly_compressed.js:1118)
at Blockly.InsertionMarkerManager.maybeShowPreview_ (blockly_compressed.js:1117)
at Blockly.InsertionMarkerManager.update (blockly_compressed.js:1110)
at Blockly.BlockDragger.dragBlock (blockly_compressed.js:1130)
at Blockly.TouchGesture.Blockly.Gesture.startDraggingBlock_ (blockly_compressed.js:1177)
at Blockly.TouchGesture.Blockly.Gesture.updateIsDraggingBlock_ (blockly_compressed.js:1174)
at Blockly.TouchGesture.Blockly.Gesture.updateIsDragging_ (blockly_compressed.js:1176)
at Blockly.TouchGesture.Blockly.Gesture.updateFromEvent_ (blockly_compressed.js:1171)
Does somebody has any idea?
Hi you need is just override the getMatchingConnection function from blockly and comment the check in the function
window.Blockly.Block.prototype.getMatchingConnection = function(otherBlock, conn) {
var connections = this.getConnections_(true);
var otherConnections = otherBlock.getConnections_(true);
// if (connections.length !== otherConnections.length) {
// throw Error("Connection lists did not match in length.");
// }
for (var i = 0; i < otherConnections.length; i++) {
if (otherConnections[i] === conn) {
return connections[i];
}
}
return null;
};
Related
I need to prevent/disable nested lists in text editor implemented in Angular. So far i wrote a hack that undos a nested list when created by the user. But if the user creates a normal list and presses the tab-key the list is shown as nested for a few milliseconds until my hack sets in back to a normal list. I need something like event.preventDefault() or stopPropagation() on tab-event keydown but unfortunately that event is not tracked for some reason. Also the froala settings with tabSpaces: falseis not showing any difference when it comes to nested list...in summary i want is: if the user creates a list and presses the tab-key that nothing happens, not even for a millisecond. Has anyone an idea about that?
Froala’s support told us, there’s no built-in way to suppress nested list creation. They result from TAB key getting hit with the caret on a list item. However we found a way to get around this using MutationObserver
Basically we move the now nested list item to his former sibling and remove the newly created list. Finally we take care of the caret position.
var observer = new MutationObserver(mutationObserverCallback);
observer.observe(editorNode, {
childList: true,
subtree: true
});
var mutationObserverCallback = function (mutationList) {
var setCaret = function (ele) {
if (ele.nextSibling) {
ele = ele.nextSibling;
}
var range = document.createRange();
var sel = window.getSelection();
range.setStart(ele, 0);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
};
var handleAddedListNode = function (listNode) {
if (! listNode.parentNode) {
return;
}
var parentListItem = listNode.parentNode.closest('li');
if (!parentListItem) {
return;
}
var idx = listNode.children.length - 1;
while (idx >= 0) {
var childNode = listNode.children[idx];
if (parentListItem.nextSibling) {
parentListItem.parentNode.insertBefore(childNode, parentListItem.nextSibling);
} else {
parentListItem.parentNode.appendChild(childNode);
}
--idx;
}
setCaret(parentListItem);
listNode.parentNode.removeChild(listNode);
};
mutationList.forEach(function (mutation) {
var addedNodes = mutation.addedNodes;
if (!addedNodes.length) {
return;
}
for (var i = 0; i < addedNodes.length; i++) {
var currentNode = addedNodes[i];
switch (currentNode.nodeName.toLowerCase()) {
case 'ol':
case 'ul':
handleAddedListNode(currentNode);
break;
// more optimizations
}
}
})
};
I'm working on a checker's simulation game for my C++ class. My issue is with the linked list that holds the checkers. I can delete any checker perfectly with the exception of the head of the list. I've looked around here and other websites and I believe there's a memory leak somewhere. I'm fairly new to C++ so I'm not sure what to really do other than playing around with things (which will probably just create a bigger problem). I've never posted here before, so excuse me if the formatting is slightly off or too messy. I'll try to make it brief. First, here's a snippet of the node class for the linked list.
class CheckerpieceNode
{
private:
Checkerpiece *Node;
CheckerpieceNode *Next;
public:
CheckerpieceNode(); // sets Node and Next to NULL in .cpp file
void setNode(Checkerpiece *node);
void setNext(CheckerpieceNode *next);
Checkerpiece* getNode();
CheckerpieceNode* getNext();
};
And the functions are set up pretty much as you would expect in a Checkerpiece.cpp class.
Here's how the code is used. Its called by a Checkerboard object in my main class.
theCheckerboard.removeChecker(theCheckerboard.findChecker(selector->getCurrentX() + 0, selector->getCurrentY() - VERTICAL_SHIFT, listHead), listHead);
The VERTICAL_SHIFT simply has to do with the way my checkerboard graphic is on the console. Since it works perfectly for all other nodes (excluding the head) I've ruled it out as a source of error. Selector is a checkerpiece object but its not part of the list.
Here's the actual findChecker and removeChecker code from Checkerboard class.
Checkerpiece* findChecker(int x, int y, CheckerpieceNode* list_head)
{
if(list_head== NULL) return NULL; // do nothing
else
{
CheckerpieceNode* node = new CheckerpieceNode;
node = list_head;
while(node != NULL && node->getNode() != NULL)
{
if()// comparison check here, but removed for space
{
return node->getNode();
delete node;
node = NULL;
}
else // traversing
node = node->getNext();
}
return NULL;
}
}
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head)
{
if(list_head== NULL) // throw exception
else
{
CheckerpieceNode *temp = NULL, *previous = NULL;
Checkerpiece* c_checker= new Checkerpiece;
temp = list_head;
while(temp != NULL && temp->getNode() != NULL)
{
c_checker= temp->getNode();
if(d_checker!= c_checker)
{
previous = temp;
temp = temp->getNext();
}
else
{
if(temp != list_head)
{
previous->setNext(temp->getNext());
delete temp;
temp = NULL;
}
else if(temp == list_head) // this is where head should get deleted
{
temp = list_head;
list_head= list_head->getNext();
delete temp;
temp = NULL;
}
return;
}
}
}
}
Oh my, you're complicating it. Lots of redundant checks, assignments and unnecessary variables (like c_checker which leaks memory too).
// Write down the various scenarios you can expect first:
// (a) null inputs
// (b) can't find d_checker
// (c) d_checker is in head
// (d) d_checker is elsewhere in the list
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head) {
// first sanitize your inputs
if (d_checker == nullptr || list_head == nullptr) // use nullptr instead of NULL. its a keyword literal of type nullptr_t
throw exception;
// You understand that there is a special case for deleting head. Good.
// Just take care of it once and for all so that you don't check every time in the loop.
CheckerpieceNode *curr = list_head;
// take care of deleting head before traversal
if (d_checker == curr->getNode()) {
list_head = list_head->next; // update list head
delete curr; // delete previous head
return; // we're done
}
CheckerpieceNode *prev = curr;
curr = curr->next;
// traverse through the list - keep track of previous
while (curr != nullptr) {
if (d_checker == curr->getNode()) {
prev->next = curr->next;
delete curr;
break; // we're done!
}
prev = curr;
curr = curr->next;
}
}
I hope that helps. Take the time to break down the problem into smaller pieces, figure out the scenarios possible, how you'll handle them and only then start writing code.
Based on this edit by the question author, the solution he used was to:
I modified the code to show the address passing in the checker delete
function.
void delete_checker(Checker* d_checker, CheckerNode* &list_head) // pass by address
{
if(list_head== NULL) // throw exception
else
{
CheckerNode*temp = NULL, *previous = NULL;
Checker* c_checker= new Checker;
temp = list_head;
while(temp != NULL && temp->node!= NULL)
{
c_checker= temp->node;
if(d_checker!= c_checker)
{
previous = temp;
temp = temp->next;
}
else
{
if(temp != list_head)
{
previous->next = temp->next;
delete temp;
temp = NULL;
}
else if(temp == list_head) // this is where head should get deleted
{
temp = list_head;
list_head= list_head->next;
delete temp;
temp = NULL;
}
delete c_checker;
c_checker = nullptr;
return;
}
}
}
}
removeChecker cannot modify the value of list_head as it is past by value. The method signature should be:
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode** list_head)
// You will need to call this function with &list_head
or
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* &list_head)
// Calling code does not need to change
In this c# code I need to convert the userName value from string to int type.
Is anyone know please help me. I have got error as a compilation error "Cannot convert lambda expression to type 'int' because it is not a delegate type" like this.
ShoppingCartPartRecord cartRecord = null;
try {
cartRecord = _shoppingCartRepository.Get(r => r.Username == userName);
}
catch (InvalidOperationException ex) {
if (ex.Message == "Sequence contains more than one element") {
var badCarts = _shoppingCartRepository.Table.Where(x => x.Username == userName);
foreach (var shoppingCartPartRecord in badCarts) {
_shoppingCartRepository.Delete(shoppingCartPartRecord);
}
}
}
Thank you in advance.
Without the source to your repository we can only guess at what the methods do.
From the errors you are describing the get function expects either an index into an array or an integer primary key and so is the wrong function
You should be able to change the code as follows to achieve the desired effect
ShoppingCartPartRecord cartRecord = null;
try {
cartRecord = _shoppingCartRepository.Table.Single(r => r.Username == userName);
}
catch (InvalidOperationException ex) {
if (ex.Message == "Sequence contains more than one element") {
var badCarts = _shoppingCartRepository.Table.Where(x => x.Username == userName);
foreach (var shoppingCartPartRecord in badCarts) {
_shoppingCartRepository.Delete(shoppingCartPartRecord);
}
}
}
I have a tree structure and I want to find all nodes matching a given criteria. Each time I call the find function, it returns next matching node. Children are searched by recursive function call.
For some reason a key comparison of pointers fails for this implementation. Please see the code below, I have pointed out the failing comparison.
HtmlTag* HtmlContent::FindTag(string tagName, string tagParameterContent)
{
if (tagName.empty() && tagParameterContent.empty())
return NULL;
if (this->startTag == NULL)
return NULL;
this->findContinue = this->FindChildren(this->startTag, &tagName, &tagParameterContent);
return this->findContinue;
}
HtmlTag* HtmlContent::FindChildren(HtmlTag* firstTag, string* tagName, string* tagParameterContent)
{
HtmlTag* currentTag = firstTag;
HtmlTag* childrenFound = NULL;
while (currentTag != NULL)
{
if (!tagName->empty() && *tagName == currentTag->tagName)
{
if (tagParameterContent->empty() || currentTag->tagParameters.find(*tagParameterContent, 0) != -1)
{
if (this->findContinue == NULL)
break; // break now when found
else if (this->findContinue == currentTag) // TODO why this fails?
this->findContinue == NULL; // break on next find
}
}
if (currentTag->pFirstChild != NULL)
{
childrenFound = this->FindChildren(currentTag->pFirstChild, tagName, tagParameterContent);
if (childrenFound != NULL)
{
currentTag = childrenFound;
break;
}
}
currentTag = currentTag->pNextSibling;
}
return currentTag;
}
VC++ compiler accepts this code but for some reason I can't put a breakpoint on this comparison. I guess this is optimized out, but why? Why this comparison fails?
I think that you shoud replace == with = in assignment after comparison. Compiler optimalized this whole section because it doesnt do anything useful.
I have a huge web app that is having issues with memory leak in IE 6.
Fixing a memory leak in a 5 line code sample that demonstrates the problem is easy.
But if I have a very huge application, where should a start from?
Check out Drip. That usually takes the guesswork out of IE memory leaks.
If for some reason Drip doesn't find it, take a close look at any JavaScript code that works with events. That is almost always the source of any significant memory leak in a browser.
Destroying a DOM element with handlers attached to it, without removing those handlers first, will prevent the memory associated with those handlers from being recovered.
Does the application use a lot of JavaScript?
If it does, then one thing I've found that helps for avoiding memory leaks is to make sure you're using a JavaScript framework such as Prototype or jQuery because they have tried and tested event-handling code that doesn't leak memory.
IE6 can also leak memory if you have circular references to DOM objects
Also try this JavaScript Memory Leak Detector and see if you can diagnose where the problem is
Here is how I solved the memory leak problem in IE7. The idea is to dispose/set to null all expando-properties on all DOM nodes at unloading the page. This worked for me. You may find it useful.
<!--[if lt IE 8]>
<script type="text/javascript">
function disposeAll() {
if (window.document.all) {
for (var index = 0; index < window.document.all.length; index++) {
try { dispose(window.document.all[index], []); } catch (e) { debugger; }
}
}
dispose(window.document.body, []);
dispose(window.document, []);
dispose(window, []);
window.disposeAll = null;
window.dispose = null;
window.onunload = null;
}
function dispose(something, map) {
if (something == null) return;
if (something.dispose && typeof (something.dispose) == 'function') {
try { something.dispose(); } catch (e) { debugger; }
}
map.push(something);
for (var key in something) {
var value = null;
try { value = something[key]; } catch (e) { };
if (value == null || value == dispose || value == disposeAll) continue;
var processed = null;
for (var index = 0; index < map.length; index++) {
if (map[index] === value) {
processed = value;
break;
}
}
if (processed != null) continue;
var constructor = value.constructor;
if (constructor == Object || constructor == Array) {
try { dispose(value, map); } catch (e) { debugger; }
}
if (constructor == Object || constructor == Array || constructor == Function) {
try { something[key] = null; } catch (e) { debugger; }
}
}
map.pop();
}
(function() {
var previousUnloadHandler = window.onunload;
if (previousUnloadHandler == null) {
window.onunload = disposeAll;
} else {
window.onunload = function() {
previousUnloadHandler.apply(this, arguments); // <== HERE YOU MAY WANT TO HAVE AN "IF" TO MAKE SURE THE ORIGINAL UNLOAD EVENT WASN'T CANCELLED
disposeAll();
previousUnloadHandler = null;
};
}
}());
</script>
<![endif]-->
You may want to remove all "debugger;" statements if you don't feel like dealing with some occasional exceptions.