Optimizing a loop to cut down on the number of draws - javascript

I'm creating an animated strip chart that redraws on every new packet message received from the header. First I create a function that checks if the chart already exists and if not builds it:
function drawAccel() {
if (chart == null) {
chart = Stripchart(document.getElementById('accel'));
}
if (orienteer == null) {
orienteer = Orienteer(document.getElementById('orienteer'));
}
chart.draw();
orienteer.draw();
}
Following that I run this function which loops and redraws the chart on every header packet recieved:
function messagecb(header, message) {
if(header.type == 6) {
// echo reply
// processEchoReply(message);
}else if(header.type == 4) {
// accel
var accels = message.b64UnpackAccelMsg();
for(var index in accels) {
var accel = accels[index];
var totalClock = accelEpochAdjust(accel.clock);
addAccelDatum(totalClock, accel.x, accel.y, accel.z);
}
drawAccel();
} else if(header.type == 3) {
// info
var info2 = message.b64UnpackInfo2Msg();
displayCurrentPosition(info2.fixtime, info2.lat, info2.lon, info2.alt);
displayMobileStatus(info2.rssi, info2.bandClass, info2.batt);
} else if(header.type == 11) {
btReceive(header, message);
}
}
I have no issues in all the modern browsers using this method, but in IE8 it really slows down a lot. This causes a slow running script error to occur which eventually ends up breaking the app. I also think something about my current logic is causing the chart to redraw even if the graph hasn't visually changed, but I'm unsure of how to check on that. Sorry for being long winded any help is greatly appreciated!

This might not be much help so please dont downvote.
I had a similar problem and only redrew every so many packets or over a set time frame like:
var mycars = new Array();
var count = 0;
function newPakcet(pck) {
mycars[mycars.length + 1] = pck;
redraw();
}
var redrawSize = 10;
function redraw(pck) {
if (mycars.length > 10) {
for(var i = 0 ;i < mycars.length;i++){
//Draw here
}
mycars = new Array();
}
}
Not tested it so there may be more syntax error.

After some trial and error along with a little help from some one else this ended up solving the problem. Set a local variable rather than a global to act as a counter that can be checked to see if it is a multiple of 10. Wrap the draw function with it so that it draws on every tenth packet.
function messagecb(header, message) {
if(header.type == 6) {
// processEchoReply(message);
} else if(header.type == 4) {
var accels = message.b64UnpackAccelMsg();
for(var index = 0; index < accels.length; ++index) {
var accel = accels[index];
var totalClock = accelEpochAdjust(accel.clock);
addAccelDatum(totalClock, accel.x, accel.y, accel.z);
}
if ( typeof messagecb.counter == 'undefined' ) {
messagecb.counter = 0;
}
++messagecb.counter;
if (messagecb.counter % 10 == 0) {
drawAccel();
}
} else if(header.type == 3) {
// info
var info2 = message.b64UnpackInfo2Msg();
displayCurrentPosition(info2.fixtime, info2.lat, info2.lon, info2.alt);
displayMobileStatus(info2.rssi, info2.bandClass, info2.batt);
} else if(header.type == 11) {
btReceive(header, message);
}
}

Related

How to underline charachters in InDesign with JavaScript?

I started writing this piece of code for InDesign to underline all letters except from the one with descendants, and added a dialog window to chose stroke and offset of the line.
Now I have two problems:
the program underlines all letters
the stroke and offset won't change
I'm a beginner in Javascript and it's the first time coding for InDesign. Does someone have a clue? Thank you!
// UNDERLINE ALL BUT NO DESCENDANTS
//Make certain that user interaction (display of dialogs, etc.) is turned on.
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
if (app.documents.length != 0){
try {
// Run script with single undo if supported
if (parseFloat(app.version) < 6) {
main();
} else {
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Expand State Abbreviations");
}
// Global error reporting
} catch ( error ) {
alert( error + " (Line " + error.line + " in file " + error.fileName + ")");
}
}else{
alert("Open a document first before running this script.");
}
///MAIN FUNCTION
function main(){
if(app.selection.length != 0){
myDisplayDialog();
}
}
//INTERFACE
function myDisplayDialog(){
//declare variables
//general
var myDoc = app.activeDocument;
var mS = myDoc.selection;
// dialog
var myDialog = app.dialogs.add({name:"Underliner"});
var myLabelWidth = 70;
with(myDialog.dialogColumns.add()){
with(borderPanels.add()){
with(dialogColumns.add()){
with(dialogRows.add()){
staticTexts.add({staticLabel:"Stroke:", minWidth:myLabelWidth});
staticTexts.add({staticLabel:"Offset:", minWidth:myLabelWidth});
}
}
with(dialogRows.add()){
staticTexts.add({staticLabel:""});
var myStroke = measurementEditboxes.add({editValue:1, editUnits:MeasurementUnits.points});
var myOffset = measurementEditboxes.add({editValue: 15, editUnits:MeasurementUnits.points});
}
}
}
var myResult = myDialog.show();
if(myResult == true){
var myStroke = myStroke.editValue;
var myOffset = myOffset.editValue;
myDialog.destroy();
underline(mS,myStroke,myOffset);
}
else{
myDialog.destroy();
alert("Invalid page range.");
}
}
//REAL FUNCTION
function underline(charList,stroke, offset){
var len = charList.length;
const doNotUnderline = ['g','j','p','q','y'];
for (var i=0; i < len; i++){
try{
var myChar = charList[i];
//console.log(typeof myText);
if (includes(myChar, doNotUnderline) == false)
{
myChar.underline = true;
myChar.underlineWeight == stroke;
myChar.underlineOffset == offset;
} else {
myChar.underline = false;
}
}catch(r){
alert(r.description);
break;
}
}
}
//function to know if char is in array
function includes(elemento,array)
{
var len = array.length;
for(var i=0; i<len ;i++)
{
if(array[i]==elemento){return true;}
}
return false;
}
Try these changes in the function underline():
//REAL FUNCTION
function underline(words,stroke, offset) { // <------ here 'words' instead of 'charList'
var charList = words[0].characters; // <------ here get 'characters' of the 'words'
var len = charList.length;
const doNotUnderline = ['g','j','p','q','y'].join(); // <------- here '.join()'
for (var i=0; i < len; i++){
try{
var myChar = charList[i];
// if (includes(myChar, doNotUnderline) == false) // <----- no need
if (doNotUnderline.indexOf(myChar.contents) < 0) // <------ 'indexOf()' instead of 'includes()'
{
myChar.underline = true;
myChar.underlineWeight = stroke; // <------- here '=' instead of '=='
myChar.underlineOffset = offset; // <------- here '=' instead of '=='
} else {
myChar.underline = false;
}
}catch(r){
alert(r.description);
break;
}
}
}
Probably there can be another improvements as well. It's need additional researches. But if you change these lines it should work to a degree.
And there is one little thing that improves user experience greatly: to keep last used values in the input fields. It can be done pretty easy, let me know it you need it.
Update
Here is the way I'm using to store and restore any preferences of my scripts.
Add somewhere at the start of your script these lines:
// get preferences
var PREFS = { stroke: 1, offset: 15 }; // set default prefs
var PREFS_FILE = File(Folder.temp + '/underline_prefs.json'); // the file with preferences
if (PREFS_FILE.exists) PREFS = $.evalFile(PREFS_FILE); // get the prefs from the file
Now you can use the global values PREFS.stroke and PREFS.offset anywhere you want. In your case they go here:
with(dialogRows.add()){
staticTexts.add({staticLabel:""});
var myStroke = measurementEditboxes.add({editValue:PREFS.stroke, editUnits:MeasurementUnits.points});
var myOffset = measurementEditboxes.add({editValue:PREFS.offset, editUnits:MeasurementUnits.points});
}
This way script will get the stroke and weight from the file underline_prefs.json that will be stored in the standard temporary folder of current user.
Final step is to save the values back into the file after the script got them from the dialog window.
I'd put this piece of code here:
if (myResult == true) {
var myStroke = myStroke.editValue;
var myOffset = myOffset.editValue;
myDialog.destroy();
underline(mS, myStroke, myOffset);
// save preferences here
PREFS.stroke = myStroke;
PREFS.offset = myOffset;
PREFS_FILE.open('w');
PREFS_FILE.write(PREFS.toSource());
PREFS_FILE.close();
} else {
myDialog.destroy();
alert("Invalid page range.");
}
Voilá. Now don't need to type the values every time they differ from default ones.

LocalStorage Problem - Key not being Created properly - returns null

I am having a LocalStorage Problem where it isn’t creating a new LocalStorage Key when the key doesn’t exist.
I have this code:
var times = [];
var solves = 0;
if(localStorage.getItem("solvesDone") === null)
{
alert("Creating a Solves Object")
localStorage.setItem("solvesDone", 0);
}
else
{
if(localStorage.getItem("solvesDone") !== null)
{
solves = localStorage.getItem("solvesDone");
localStorage.setItem("solvesDone", JSON.parse(solves));
solveCount.innerHTML = "Solves: " + solves;
}
}
if(localStorage.getItem("timesDone") === null)
{
localStorage.setItem("timesDone", JSON.stringify(times));
}
else
{
if(localStorage.getItem("timesDone") !== null)
{
times = localStorage.getItem("timesDone");
localStorage.setItem("timesDone", times);
alert(times);
}
}
Here, it’s not creating the key even if the key doesn’t exist.
I’m trying to make a speedcube timer.
The full website is here of you want to see it: https://speedcube-timer.coderguru.repl.co/
Thanks in Advance.
Your code works as expected however I did some refactoring. You don't need the deeply nested if condition
var times = [];
var solves = 0;
if(!localStorage.getItem("solvesDone")) {
alert("Creating a Solves Object")
localStorage.setItem("solvesDone", 0);
} else {
solves = localStorage.getItem("solvesDone");
localStorage.setItem("solvesDone", JSON.parse(solves));
solveCount.innerHTML = "Solves: " + solves;
}
if(!localStorage.getItem("timesDone")) {
localStorage.setItem("timesDone", JSON.stringify(times));
} else {
times = localStorage.getItem("timesDone");
localStorage.setItem("timesDone", JSON.parse(times));
alert('times', times);
}

Javascript For Loop interrupted by function call?

I have a for-loop that is terminating without finishing the loop. It seems to be related to whether or not a call to another function is made within the loop.
this.cycle = function() {
var list = this.getBreaches("Uncontained");
if (list.length > 0) {
for (i=0; i < list.length; i++) {
this.saveVsRupture(DC=11, i); //calls this.rupture() if save failed
}}
return 1;
};
this.saveVsRupture() calls a function that rolls a d20 and checks the result. If the save fails, it calls a method called this.rupture() that does some adjusting to this.
Problem
If the saving throw is successful, the loop continues, but if the saving throw fails, it runs the this.rupture() function and then breaks the for-loop. It should keep running the for-loop.
Why is this happening?
Additional Details
Here are the other functions...
savingThrow = function(DC=11) {
// DC = Difficulty Check on a d20
try {
if (0 <= DC) {
var roll = Math.floor((Math.random() * 20))+1; //roll d20
var msg = "(Rolled "+roll+" vs DC "+DC+")";
console.log(msg);
if (roll >= DC) { //Saved
return true;
}
else { //Failed save
return false;
}
}
}
catch(e) {
console.log("Exception in savingThrow: "+e);
};
};
this.saveVsRupture = function(DC=1, i=null) {
try {
if (!savingThrow(DC)) {
this.rupture(i);
return false;
}
return true;
}
catch(e) {
console.log(e);
}
};
this.rupture = function(i=null) {
if (i == null) {
i = range(1,this.damageList.length).sample();
}
var hole = this.damageList[i];
var dmg = range(1,this.harmonics()).sample();
hole.rupture(dmg);
msg = "*ALERT* " + hole + " expanded by " + dmg + "% Hull Integrity #"+this.hullIntegrity();
this.log(msg);
if (hole.size % 10 == 0) {
this.health -= 25;
msg = "The ship creaks ominously.";
this.log(msg);
}
return 1;
};
The correct syntax for the for-loop declares the counter variable.
for (var i=0; i < list.length; i++) {etc..
/// Causes the For-Loop to exit prematurely...
for (i=0; i < list.length; i++) {etc..
Once the "var i=0" is used, the for-loop operates as expected.
consider implementing a try-catch in your for loop, with your saveVsRupture function within the try. This implementation will catch errors in your function but allow the program to keep running.
Change the saveVsRupture function like this:
function saveVsRupture(a,b) {
try{
//your saveVsRupture code here...
}
catch(e){}
}
Your should catch problems that occurred in your code with try,catch block to prevent throw them to top level of your code (the browser in this example) .
Don't use return in for loop!
Change your code as following:
this.cycle = function() {
var list = this.getBreaches("Uncontained");
if (list.length > 0) {
for (i=0; i < list.length; i++) {
var temp = this.saveVsRupture(DC=11, i); //calls this.rupture() if save failed
console.log(temp);
}}
return 1;
};

My javascript crashes the server

Now before everyone is helpful (seriously, you guys are awesome) I am doing a coding challenge that means I can't get code from other users/people. This does not, however, extend to advice so I wanted to know why my code crashes google chrome. I don't want am not allowed any code so please just point me in the right direction. I am sorry for such an odd request but I am at my wit's end.
http://jsfiddle.net/clarinetking/c49mutqw/9/
var chars;
var keyword = [];
var cipher;
var done = false;
var list1 = [];
var list2 = [];
var list3 = [];
var list4 = [];
var list5 = [];
var keylngth = 0;
$('#apnd').click(function () {
cipher = $('#Input').val();
chars = cipher.split('');
$('#Output').append(chars);
});
$('#key').click(function () {
while (done === false) {
var letter = prompt('insert letter, xyz to close');
keylngth++;
if (letter == 'xyz') {
done = true;
} else {
//Push letter to keyword array
keyword.push(letter);
}
}
});
$('#list').click(function () {
for (i = 0; i < chars.length; i++) {
var x = 1;
for (i = 1; i < keylngth+1; i++) {
if (i/x === 1) {
list1.push(chars[x]);
}
if (i/x === 2) {
list1.push(chars[x]);
}
if (i/x === 3) {
list1.push(chars[x]);
}
if (i/x === 4) {
list1.push(chars[x]);
}
if (i/x === 5) {
list1.push(chars[x]);
}
if (i/x === 6) {
list1.push(chars[x]);
}
if (i/x === 7) {
list1.push(chars[x]);
}
if (i/x === 8) {
list1.push(chars[x]);
}
}
x++;
}
alert(list1);
alert(list2);
});
I apologize to all you coders out there that are probably screaming at me USE A REPEAT LOOP! but for the list function I see no way to. As previously mentioned, no code please unless it's pseudo code :)
In your $('#list').click(function ()) function you are running an infinite for bucle, it's because you use the same i counter for the two for bucles so you javascript will run forerver and crash the browser

javascript single thread makes some calculations impossible

Considering I'm trying to make an algorithm that finds the least expansive path.
Every computation of the current path is async.
My algorithm just kills the stack. Any other alternative?
The code for what I've been coding is:
function DFS(unvisitedNodes, currentVertex, currentRouteFromStart, depth, minimalPath, finalVertex, maxDepth, doneCallback) {
// Add the final destination to the top of the list.
var copiedUnvisitedVertices = unvisitedNodes.slice(0);
copiedUnvisitedVertices.splice(0, 0, finalVertex);
var i = 0;
var singleIteration = function (i) {
if (i == copiedUnvisitedVertices.length) {
doneCallback(minimalPath);
return;
}
if (i > 0) {
// Putting the check here makes sure we compute the edge
// for the last depth for the destination vertex only.
if (depth == maxDepth) {
currentRouteFromStart.pop();
doneCallback(minimalPath);
return;
}
}
var dest = copiedUnvisitedVertices[i];
computeEdge(currentVertex, dest, function (edgeInfo) {
currentRouteFromStart.push(edgeInfo);
var currentCost = edgeCost(currentRouteFromStart);
var afterBFSDone = function (_minimalPath) {
currentRouteFromStart.pop();
singleIteration(i + 1);
return;
}
if (dest == finalVertex) {
var minPrice = edgeCost(minimalPath);
if (currentCost < minPrice) {
minimalPath = currentRouteFromStart.slice(0);
}
}
else {
DFS(unvisitedNodes.slice(0).splice(i - 1), dest, currentRouteFromStart, depth + 1, minimalPath, finalVertex, maxDepth, afterBFSDone);
}
afterBFSDone(minimalPath);
});
};
singleIteration(0);
}

Categories

Resources