Changes not having any effect out of nowhere - google-apps-script

I was working along and out of nowhere my changes stopped applying. The code functions up until the last logger instruction I wrote in.
Now any change I make to the code is acting like it isn't even there. I click save and run the code, but nothing I change actually takes effect. No instances of Logger.log("hello") do anything, but everything else runs as written.
//variables for shorthand calling of each spread sheet
var ssL = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("SpecsList");
var ssR = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("RequiredSpecs");
//count the number of columns to determine the max range of the spec comparison iterator
var specIteratorMax = ssL.getLastColumn() - 2; // the -2 is to ignore column A which is text and rebase the iterator variable to 0
function runHeatMap() {
//voltage spec compare section
Logger.log("hello");
//retrieve the users preferred output voltage rating
var voltReqed = ssR.getRange("A2").getValue();
Logger.log(voltReqed);
//retrieve the output voltage ratings of all devices
var voltCompareData = ssL.getSheetValues(3, 2, 1, (ssL.getLastColumn() - 1)).flat();
Logger.log(voltCompareData);
Logger.log("hello");
Logger.log(specIteratorMax);
//store current iteration voltage spec and conduct comparison operations
for (var i = 0; i <= specIteratorMax; i++) {
var voltSpec = voltCompareData[i];
Logger.log(voltSpec);
if(voltSpec >= voltReqed) {
ssL.getRange(3,i + 2).setBackground("green");
}
else if(voltSpec < voltReqed && voltSpec >= (voltReqed * 0.95)) {
ssL.getRange(3,i + 2).setBackground("orange");
}
else {
ssL.getRange(3,i + 2).setBackground("red");
}
}
Logger.log("hello");
}

It seems to run on random data
I reduced it down to this:
function runHeatMap() {
var sh0 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet0");
var sh1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var max = sh0.getLastColumn() - 2;
var v1 = sh1.getRange("A2").getValue();
var vs = sh0.getSheetValues(3, 2, 1, sh0.getLastColumn() - 1).flat();
for (var i = 0; i <= max; i++) {
var v2 = vs[i];
if (v2 >= v1) {
sh0.getRange(3, i + 2).setBackground("green");
}
else if (v2 < v1 && v2 >= (v1 * 0.95)) {
sh0.getRange(3, i + 2).setBackground("orange");
}
else {
sh0.getRange(3, i + 2).setBackground("red");
}
}
}

Related

Unable to get this "tagging unanswered email" script to work

The following is a script that I found online to tag all the unanswered emails. It works for one of my gmail accounts, however when I shared it to another account and run it, it returns nothing every single time, even though there are unanswered emails within that time range. I then tried copy and paste the codes into a new project, however still wouldn't work.
Anyone has any ideas?
Thanks in advance!
/*
* This script goes through your Gmail Inbox and finds recent emails where you
* were the last respondent. It applies a nice label to them, so you can
* see them in Priority Inbox or do something else.
*
* To remove and ignore an email thread, just remove the unrespondedLabel and
* apply the ignoreLabel.
*
* This is most effective when paired with a time-based script trigger.
*
* For installation instructions, read this blog post:
* http://jonathan-kim.com/2013/Gmail-No-Response/
*/
// Edit these to your liking.
var unrespondedLabel = 'No Response',
ignoreLabel = 'Ignore No Response',
minDays = 0.125,
maxDays = 5;
function main() {
processUnresponded();
cleanUp();
}
function processUnresponded() {
var threads = GmailApp.search('is:sent from:me -in:chats older_than:' + minDays + 'd newer_than:' + maxDays + 'd'),
numUpdated = 0,
minDaysAgo = new Date();
minDaysAgo.setDate(minDaysAgo.getDate() - minDays);
// Filter threads where I was the last respondent.
for (var i = 0; i < threads.length; i++) {
var thread = threads[i],
messages = thread.getMessages(),
lastMessage = messages[messages.length - 1],
lastFrom = lastMessage.getFrom(),
lastMessageIsOld = lastMessage.getDate().getTime() < minDaysAgo.getTime();
if (isFromMe(lastFrom) && lastMessageIsOld && !threadHasLabel(thread, ignoreLabel)) {
markUnresponded(thread);
numUpdated++;
}
}
Logger.log('Updated ' + numUpdated + ' messages.');
}
function isFromMe(fromAddress) {
var addresses = getEmailAddresses();
for (i = 0; i < addresses.length; i++) {
var address = addresses[i],
r = RegExp(address, 'i');
if (r.test(fromAddress)) {
return true;
}
}
return false;
}
function getEmailAddresses() {
var me = Session.getActiveUser().getEmail(),
emails = GmailApp.getAliases();
emails.push(me);
return emails;
}
function threadHasLabel(thread, labelName) {
var labels = thread.getLabels();
for (i = 0; i < labels.length; i++) {
var label = labels[i];
if (label.getName() == labelName) {
return true;
}
}
return false;
}
function markUnresponded(thread) {
var label = getLabel(unrespondedLabel);
label.addToThread(thread);
}
function getLabel(labelName) {
var label = GmailApp.getUserLabelByName(labelName);
if (label) {
Logger.log('Label exists.');
} else {
Logger.log('Label does not exist. Creating it.');
label = GmailApp.createLabel(labelName);
}
return label;
}
function cleanUp() {
var label = getLabel(unrespondedLabel),
iLabel = getLabel(ignoreLabel),
threads = label.getThreads(),
numExpired = 0,
twoWeeksAgo = new Date();
twoWeeksAgo.setDate(twoWeeksAgo.getDate() - maxDays);
if (!threads.length) {
Logger.log('No threads with that label');
return;
} else {
Logger.log('Processing ' + threads.length + ' threads.');
}
for (i = 0; i < threads.length; i++) {
var thread = threads[i],
lastMessageDate = thread.getLastMessageDate();
// Remove all labels from expired threads.
if (lastMessageDate.getTime() < twoWeeksAgo.getTime()) {
numExpired++;
Logger.log('Thread expired');
label.removeFromThread(thread);
iLabel.removeFromThread(thread);
} else {
Logger.log('Thread not expired');
}
}
Logger.log(numExpired + ' unresponded messages expired.');
}
The Gmail search operator "older_than" does not support decimals, so you cannot use "0.125" in this case. Make sure you use an integer number/day. The script will not return errors, but the search will not work. More info about the Gmail search operators at https://support.google.com/mail/answer/7190?hl=en

Can Google apps script be used to randomize page order on Google forms?

Update #2: Okay, I'm pretty sure my error in update #1 was because of indexing out of bounds over the array (I'm still not used to JS indexing at 0). But here is the new problem... if I write out the different combinations of the loop manually, setting the page index to 1 in moveItem() like so:
newForm.moveItem(itemsArray[0][0], 1);
newForm.moveItem(itemsArray[0][1], 1);
newForm.moveItem(itemsArray[0][2], 1);
newForm.moveItem(itemsArray[1][0], 1);
newForm.moveItem(itemsArray[1][1], 1);
newForm.moveItem(itemsArray[1][2], 1);
newForm.moveItem(itemsArray[2][0], 1);
...
...I don't get any errors but the items end up on different pages! What is going on?
Update #1:: Using Sandy Good's answer as well as a script I found at this WordPress blog, I have managed to get closer to what I needed. I believe Sandy Good misinterpreted what I wanted to do because I wasn't specific enough in my question.
I would like to:
Get all items from a page (section header, images, question etc)
Put them into an array
Do this for all pages, adding these arrays to an array (i.e: [[all items from page 1][all items from page 2][all items from page 3]...])
Shuffle the elements of this array
Repopulate a new form with each element of this array. In this way, page order will be randomized.
My JavaScript skills are poor (this is the first time I've used it). There is a step that produces null entries and I don't know why... I had to remove them manually. I am not able to complete step 5 as I get the following error:
Cannot convert Item,Item,Item to (class).
"Item,Item,Item" is the array element containing all the items from a particular page. So it seems that I can't add three items to a page at a time? Or is something else going on here?
Here is my code:
function shuffleForms() {
var itemsArray,shuffleQuestionsInNewForm,fncGetQuestionID,
newFormFile,newForm,newID,shuffle, sections;
// Copy template form by ID, set a new name
newFormFile = DriveApp.getFileById('1prfcl-RhaD4gn0b2oP4sbcKaRcZT5XoCAQCbLm1PR7I')
.makeCopy();
newFormFile.setName('AAAAA_Shuffled_Form');
// Get ID of new form and open it
newID = newFormFile.getId();
newForm = FormApp.openById(newID);
// Initialize array to put IDs in
itemsArray = [];
function getPageItems(thisPageNum) {
Logger.log("Getting items for page number: " + thisPageNum );
var thisPageItems = []; // Used for result
var thisPageBreakIndex = getPageItem(thisPageNum).getIndex();
Logger.log( "This is index num : " + thisPageBreakIndex );
// Get all items from page
var allItems = newForm.getItems();
thisPageItems.push(allItems[thisPageBreakIndex]);
Logger.log( "Added pagebreak item: " + allItems[thisPageBreakIndex].getIndex() );
for( var i = thisPageBreakIndex+1; ( i < allItems.length ) && ( allItems[i].getType() != FormApp.ItemType.PAGE_BREAK ); ++i ) {
thisPageItems.push(allItems[i]);
Logger.log( "Added non-pagebreak item: " + allItems[i].getIndex() );
}
return thisPageItems;
}
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
Logger.log('shuffle ran')
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
function shuffleAndMove() {
// Get page items for all pages into an array
for(i = 2; i <= 5; i++) {
itemsArray[i] = getPageItems(i);
}
// Removes null values from array
itemsArray = itemsArray.filter(function(x){return x});
// Shuffle page items
itemsArray = shuffle(itemsArray);
// Move page items to the new form
for(i = 2; i <= 5; ++i) {
newForm.moveItem(itemsArray[i], i);
}
}
shuffleAndMove();
}
Original post: I have used Google forms to create a questionnaire. For my purposes, each question needs to be on a separate page but I need the pages to be randomized. A quick Google search shows this feature has not been added yet.
I see that the Form class in the Google apps script has a number of methods that alter/give access to various properties of Google Forms. Since I do not know Javascript and am not too familiar with Google apps/API I would like to know if what I am trying to do is even possible before diving in and figuring it all out.
If it is possible, I would appreciate any insight on what methods would be relevant for this task just to give me some direction to get started.
Based on comments from Sandy Good and two SE questions found here and here, this is the code I have so far:
// Script to shuffle question in a Google Form when the questions are in separate sections
function shuffleFormSections() {
getQuestionID();
createNewShuffledForm();
}
// Get question IDs
function getQuestionID() {
var form = FormApp.getActiveForm();
var items = form.getItems();
arrayID = [];
for (var i in items) {
arrayID[i] = items[i].getId();
}
// Logger.log(arrayID);
return(arrayID);
}
// Shuffle function
function shuffle(a) {
var j, x, i;
for (i = a.length; i; i--) {
j = Math.floor(Math.random() * i);
x = a[i - 1];
a[i - 1] = a[j];
a[j] = x;
}
}
// Shuffle IDs and create new form with new question order
function createNewShuffledForm() {
shuffle(arrayID);
// Logger.log(arrayID);
var newForm = FormApp.create('Shuffled Form');
for (var i in arrayID) {
arrayID[i].getItemsbyId();
}
}
Try this. There's a few "constants" to be set at the top of the function, check the comments. Form file copying and opening borrowed from Sandy Good's answer, thanks!
// This is the function to run, all the others here are helper functions
// You'll need to set your source file id and your destination file name in the
// constants at the top of this function here.
// It appears that the "Title" page does not count as a page, so you don't need
// to include it in the PAGES_AT_BEGINNING_TO_NOT_SHUFFLE count.
function shuffleFormPages() {
// UPDATE THESE CONSTANTS AS NEEDED
var PAGES_AT_BEGINNING_TO_NOT_SHUFFLE = 2; // preserve X intro pages; shuffle everything after page X
var SOURCE_FILE_ID = 'YOUR_SOURCE_FILE_ID_HERE';
var DESTINATION_FILE_NAME = 'YOUR_DESTINATION_FILE_NAME_HERE';
// Copy template form by ID, set a new name
var newFormFile = DriveApp.getFileById(SOURCE_FILE_ID).makeCopy();
newFormFile.setName(DESTINATION_FILE_NAME);
// Open the duplicated form file as a form
var newForm = FormApp.openById(newFormFile.getId());
var pages = extractPages(newForm);
shuffleEndOfPages(pages, PAGES_AT_BEGINNING_TO_NOT_SHUFFLE);
var shuffledFormItems = flatten(pages);
setFormItems(newForm, shuffledFormItems);
}
// Builds an array of "page" arrays. Each page array starts with a page break
// and continues until the next page break.
function extractPages(form) {
var formItems = form.getItems();
var currentPage = [];
var allPages = [];
formItems.forEach(function(item) {
if (item.getType() == FormApp.ItemType.PAGE_BREAK && currentPage.length > 0) {
// found a page break (and it isn't the first one)
allPages.push(currentPage); // push what we've built for this page onto the output array
currentPage = [item]; // reset the current page to just this most recent item
} else {
currentPage.push(item);
}
});
// We've got the last page dangling, so add it
allPages.push(currentPage);
return allPages;
};
// startIndex is the array index to start shuffling from. E.g. to start
// shuffling on page 5, startIndex should be 4. startIndex could also be thought
// of as the number of pages to keep unshuffled.
// This function has no return value, it just mutates pages
function shuffleEndOfPages(pages, startIndex) {
var currentIndex = pages.length;
// While there remain elements to shuffle...
while (currentIndex > startIndex) {
// Pick an element between startIndex and currentIndex (inclusive)
var randomIndex = Math.floor(Math.random() * (currentIndex - startIndex)) + startIndex;
currentIndex -= 1;
// And swap it with the current element.
var temporaryValue = pages[currentIndex];
pages[currentIndex] = pages[randomIndex];
pages[randomIndex] = temporaryValue;
}
};
// Sourced from elsewhere on SO:
// https://stackoverflow.com/a/15030117/4280232
function flatten(array) {
return array.reduce(
function (flattenedArray, toFlatten) {
return flattenedArray.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
},
[]
);
};
// No safety checks around items being the same as the form length or whatever.
// This mutates form.
function setFormItems(form, items) {
items.forEach(function(item, index) {
form.moveItem(item, index);
});
};
I tested this code. It created a new Form, and then shuffled the questions in the new Form. It excludes page breaks, images and section headers. You need to provide a source file ID for the original template Form. This function has 3 inner sub-functions. The inner functions are at the top, and they are called at the bottom of the outer function. The arrayOfIDs variable does not need to be returned or passed to another function because it is available in the outer scope.
function shuffleFormSections() {
var arrayOfIDs,shuffleQuestionsInNewForm,fncGetQuestionID,
newFormFile,newForm,newID,items,shuffle;
newFormFile = DriveApp.getFileById('Put the source file ID here')
.makeCopy();
newFormFile.setName('AAAAA_Shuffled_Form');
newID = newFormFile.getId();
newForm = FormApp.openById(newID);
arrayOfIDs = [];
fncGetQuestionID = function() {
var i,L,thisID,thisItem,thisType;
items = newForm.getItems();
L = items.length;
for (i=0;i<L;i++) {
thisItem = items[i];
thisType = thisItem.getType();
if (thisType === FormApp.ItemType.PAGE_BREAK ||
thisType === FormApp.ItemType.SECTION_HEADER ||
thisType === FormApp.ItemType.IMAGE) {
continue;
}
thisID = thisItem.getId();
arrayOfIDs.push(thisID);
}
Logger.log('arrayOfIDs: ' + arrayOfIDs);
//the array arrayOfIDs does not need to be returned since it is available
//in the outermost scope
}// End of fncGetQuestionID function
shuffle = function() {// Shuffle function
var j, x, i;
Logger.log('shuffle ran')
for (i = arrayOfIDs.length; i; i--) {
j = Math.floor(Math.random() * i);
Logger.log('j: ' + j)
x = arrayOfIDs[i - 1];
Logger.log('x: ' + x)
arrayOfIDs[i - 1] = arrayOfIDs[j];
arrayOfIDs[j] = x;
}
Logger.log('arrayOfIDs: ' + arrayOfIDs)
}
shuffleQuestionsInNewForm = function() {
var i,L,thisID,thisItem,thisQuestion,questionType;
L = arrayOfIDs.length;
for (i=0;i<L;i++) {
thisID = arrayOfIDs[i];
Logger.log('thisID: ' + thisID)
thisItem = newForm.getItemById(thisID);
newForm.moveItem(thisItem, i)
}
}
fncGetQuestionID();//Get all the question ID's and put them into an array
shuffle();
shuffleQuestionsInNewForm();
}

How do I find and select a next bold word

From the https://gist.github.com/oshliaer/d468759b3587cfb424348fa722765187 , It is possible to select a particular word from the findText, I want to implement the same for bold words only
I have a function to find bold. How do I modify the above gist?
var startFlag = x;
var flag = false;
for (var i = x; i < y; i++) {
if (text.isBold(i) && !flag) {
startFlag = i;
flag = true;
} else if (!text.isBold(i) && flag) {
flag = false;
rangeBuilder.addElement(text, startFlag, i - 1);
doc.setSelection(rangeBuilder.build());
return;
}
}
if (flag) {
rangeBuilder.addElement(text, startFlag, i - 1);
doc.setSelection(rangeBuilder.build());
return;
}
Let's assume another algorithm
/*
* #param {(DocumentApp.ElementType.LIST_ITEM | DocumentApp.ElementType.PARAGRAPH)} element
*/
function hasBold(element, start) {
var text = element.editAsText();
var length = element.asText().getText().length;
var first = -1;
var end = -1;
while (start < length) {
if (first < 0 && text.isBold(start)) {
first = start;
}
if (first > -1 && !text.isBold(start)) {
end = start - 1;
return {
s: first,
e: end
}
}
start++;
}
if (first > -1) {
return {
s: first,
e: length - 1
}
}
return false;
}
It's not clean but I've tested it and it works fine.
hasBold lets us finding bolds in the current element.
Finally, we have to loop this feature within document.getBody().
You could to get the full code here find next bold text in google document.
Also you could try it on a copy
A new idea
The Direct searcing
The best way is to use a callback while it is checked
var assay = function (re) {
var text = re.getElement()
.asText();
for (var offset = re.getStartOffset(); offset <= re.getEndOffsetInclusive(); offset++) {
if (!text.isBold(offset)) return false;
}
return true;
}
function findNextBold() {
var sp = 'E.';
Docer.setDocument(DocumentApp.getActiveDocument());
var rangeElement = Docer.findText(sp, Docer.getActiveRangeElement(), assay);
rangeElement ? Docer.selectRangeElement(rangeElement) : Docer.setCursorBegin();
}
The Approx searching
var assay = function(re) {
var text = re.getElement().asText();
var startOffset = re.getStartOffset();
var endOffset = re.getEndOffsetInclusive() + 1;
for (var offset = startOffset; offset < endOffset; offset++) {
if (!text.isBold(offset)) return false;
}
return this.test(text.getText().slice(startOffset, endOffset));
}
function findNextBold() {
var searchPattern = '[^ ]+#[^ ]+';
var testPattern = new RegExp('^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$');
Docer.setDocument(DocumentApp.getActiveDocument());
var rangeElement = Docer.findText(searchPattern, Docer.getActiveRangeElement(), assay.bind(testPattern));
rangeElement ? Docer.selectRangeElement(rangeElement) : Docer.setCursorBegin();
}
Docer
Yes. it is possible to find bold text. You need to use findText(searchPattern) to search the contents of the element for the specific text pattern using regular expressions. The provided regular expression pattern is independently matched against each text block contained in the current element. Then, use isBold() to retrieve the bold setting. It is a Boolean which returns whether the text is bold or null.

find the length of a string in google script

I'm trying to make a script for google sheet, who can count a letter in a text. But it seems that .length doesn't work. Anyone who can give directions on where to find the the solution.
function Tjekkode(tekst , bogstav){
var test = "";
// find the length of laengdeTekst
var laengdeTekst = tekst.length;
var t = 0;
// through the text character by character
for ( var i = 1; i<laengdeTekst ; i++) {
var test = tekst.substr(i,1);
if (test == bogstav) {
// if the letter is found, it is counted up
// REMEMBER == means compare
var t = t + 1;
}
}
// returns percent appearance of the letter
Return = t / længdeTekst * 100
}
Thanks in advance
length is ok in your code. To test it, run this script:
function test( ) {
var test = "123456";
// finder længden på teksten
var laengdeTekst = test.length;
Logger.log(laengdeTekst);
}
After you run it, check Log, press [Ctrl + Enter]
The correct code in your case:
function Tjekkode(tekst, bogstav) {
var test = "";
var laengdeTekst = tekst.length;
var t = 0;
// start looping from zero!
for ( var i = 0; i<laengdeTekst; i++) {
var test = tekst.substr(i,1);
if (test == bogstav) {
var t = t + 1;
}
}
// JavaScript is case sensitive: 'return != Return'
return t / laengdeTekst * 100;
}
Please, look at this tutorial for more info
thanks
I'll guess that I might get the one with the R instead of r at the end, but the script didn't run that line, because it kinda stopped at the .length line :/
the comments in danish is for my pupils (I'm a teacher in elementary school)
I'll see if google wants to cooperate today :|
This is the google script that worked for me. Note the 24 - that's the length of an empty message that has markup like <div>...</div>
function TrashEmptyDrafts() {
var thread = GmailApp.getDraftMessages();
for (var i = 0; i < thread.length; i++) {
b=thread[i].getBody();
if (b.length <= 24.0){
thread[i].moveToTrash();
}
}}

A* algorithm works OK, but not perfectly. What's wrong?

This is my grid of nodes:
I'm moving an object around on it using the A* pathfinding algorithm. It generally works OK, but it sometimes acts wrongly:
When moving from 3 to 1, it correctly goes via 2. When going from 1 to 3 however, it goes via 4.
When moving between 3 and 5, it goes via 4 in either direction instead of the shorter way via 6
What can be wrong? Here's my code (AS3):
public static function getPath(from:Point, to:Point, grid:NodeGrid):PointLine {
// get target node
var target:NodeGridNode = grid.getClosestNodeObj(to.x, to.y);
var backtrace:Map = new Map();
var openList:LinkedSet = new LinkedSet();
var closedList:LinkedSet = new LinkedSet();
// begin with first node
openList.add(grid.getClosestNodeObj(from.x, from.y));
// start A*
var curNode:NodeGridNode;
while (openList.size != 0) {
// pick a new current node
if (openList.size == 1) {
curNode = NodeGridNode(openList.first);
}
else {
// find cheapest node in open list
var minScore:Number = Number.MAX_VALUE;
var minNext:NodeGridNode;
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
curNode = minNext;
}
// have not reached
if (curNode == target) break;
else {
// move to closed
openList.remove(curNode);
closedList.add(curNode);
// put connected nodes on open list
for each (var adjNode:NodeGridNode in curNode.connects) {
if (!openList.contains(adjNode) && !closedList.contains(adjNode)) {
openList.add(adjNode);
backtrace.put(adjNode, curNode);
}
}
}
}
// make path
var pathPoints:Vector.<Point> = new Vector.<Point>();
pathPoints.push(to);
while(curNode != null) {
pathPoints.unshift(curNode.location);
curNode = backtrace.read(curNode);
}
pathPoints.unshift(from);
return new PointLine(pathPoints);
}
NodeGridNode::distanceTo()
public function distanceTo(o:NodeGridNode):Number {
var dx:Number = location.x - o.location.x;
var dy:Number = location.y - o.location.y;
return Math.sqrt(dx*dx + dy*dy);
}
The problem I see here is the line
if (!openList.contains(adjNode) && !closedList.contains(adjNode))
It may be the case that an adjNode may be easier(shorter) to reach through the current node although it was reached from another node previously which means it is in the openList.
Found the bug:
openList.iterate(function(next:NodeGridNode, i:int):int {
var score:Number = curNode.distanceTo(next) + next.distanceTo(target);
if (score < minScore) {
minScore = score;
minNext = next;
return LinkedSet.BREAK;
}
return 0;
});
The return LinkedSet.BREAK (which acts like a break statement in a regular loop) should not be there. It causes the first node in the open list to be selected always, instead of the cheapest one.