5
\$\begingroup\$

This is a for-loop which runs once for each step with i>1 and maybe for 0 <= i <= 1.

var i;
var prob_ = 3.5;
for ( i = prob_; i >= 0; i -= 1 ) {
    if ( i > 1 || withProbability(i) ) {
        loadHttp(randomUrl());
    }
}

with

function withProbability(chance) {
    return Math.random() < chance;
}

JsLint gave me a for-loop error. Is this code ok despite that warning, or should this for-loop be changed to some other looping construct?

Background

prob_ is a ratio between fake actions and real actions. The loop is triggered once for each real action. If prob_ is greater than 1, the fake action is done. If it is in between 0 and 1, it is considered a probability and thus maybe a fake action follows.

This is a case where it was not clear how to replace the for-loop with a forEach, as is often recommended. Maybe ES6 tail recursion could be used...

More context

function loadHttp(toLoad) {
    require("sdk/page-worker").Page({
        contentURL: toLoad
    });
}

The implementation of randomUrl() is rather lengthy and does not relate to the question. It determines a statistically probable length of a HTML (or embedded object like js, img, css, ...) site, then does a lookup for the next bigger URL in a hardcoded list. It is supposed that the randomness will confuse someone who watches for traffic patterns.

Full class coverTraffic.js

This is initialized via

const coverTraffic = require('./coverTraffic.js');
coverTraffic.setLoader(require('./load.js'));

with load.js containing similar to loadHttp as above. It is triggered via

function loads(URL) {
    if ( _.contains(activeHosts, URL.host) ) { // has already started
        coverTraffic.loadNext();
    } else {
        activeHosts.push(URL.host);
        coverTraffic.start();
    }
}
exports.loads = URL => loads(URL);

which is called whenever the browser loads a new URL.

"use strict";

exports.DOC = 'creates cover traffic, up to predetermined parameters';

const { setTimeout } = require("sdk/timers");

const coverUrl = require("./coverUrl.js");
const stats = require("./stats.js");

/** overhead of dummy traffic -1; 1.5 has overhead of 50% */
const FACTOR = 1.5;

var load;

var site_ = {};
var pad_ = {};
var prob_;

function setLoader(load_param) {
    load = load_param;
}
exports.setLoader = (load_param) => setLoader(load_param);

/** a website is loaded by the user. covertraffic determines a target
 * feature vector and adds to the load to approximate the target.
 */
function start() {
    site_ = {};
    pad_ = {};

    site_.html = stats.htmlSize(1); // td: buffer known sites in bloomfilter
    pad_.html = stats.htmlSize(FACTOR) - site_.html;
    site_.num_embedded = stats.numberEmbeddedObjects(1); // td: see above
    pad_.num_embedded = stats.numberEmbeddedObjects(FACTOR) - site_.num_embedded;
    prob_ = pad_.num_embedded / site_.num_embedded;

    //    setTimeout(loadNext, stats.parsingTime());
    load.http(coverUrl.sized(pad_.html));
}
exports.start = start;

function loadNext() {
    var i;
    if ( pad_.num_embedded > 0 ) {
    for ( i = prob_; i >= 0; i -= 1 ) {
        if ( i > 1 || stats.withProbability(i) ) {
        load.http(coverUrl.sized(stats.embeddedObjectSize()));
        pad_.num_embedded -= 1;
        }
    }
    } else {
    console.log("cover traffic empty, num: " + pad_.num_embedded);
    }
}
exports.loadNext = loadNext;

The stats module provides statistical distributions, the load-module just loading a URL as described above.

\$\endgroup\$
8
  • \$\begingroup\$ See What topics can I ask about here? If your code is not working correctly then the question is off-topic for this site \$\endgroup\$
    – Phrancis
    Feb 10, 2016 at 14:11
  • \$\begingroup\$ @Phrancis: but it is working correctly, right? \$\endgroup\$
    – serv-inc
    Feb 10, 2016 at 14:18
  • 2
    \$\begingroup\$ Looks like a good question to me - provided you tested it... Although you might want to show what doSomething() is, rather than giving an example. \$\endgroup\$
    – Pimgd
    Feb 10, 2016 at 14:28
  • \$\begingroup\$ @Pimgd: there are even unit tests (I have not checked the coverage, though) \$\endgroup\$
    – serv-inc
    Feb 10, 2016 at 14:29
  • \$\begingroup\$ @Pimgd: doSomething basically does a HTTP request and decrements a counter. It does not use i internally. Including the whole code with two more modules would deviate from a minimal example. If you recommend posting it, just leave a comment. \$\endgroup\$
    – serv-inc
    Feb 10, 2016 at 14:37

1 Answer 1

3
\$\begingroup\$

The problem JSLint is pointing at is that you usually iterate with an index that is an integer. If you were to have an array, you couldn't use i to access the array elements, because if i is big enough, rounding issues may cause you to skip elements or see elements twice!

What I'd recommend is that you just use i as integer, and then once the for loop is done, check if there is an additional chance to roll for. That way, you don't have to worry about floating point rounding errors accumulating.

Another way you could do it is first roll, and then if you roll high enough, up i by 1. That way you only have one place where you run your code.

So like this:

var chance = i % 1;
if (chance !== 0 && withProbability(chance)){
    i = Math.ceil(i);
} else {
    i = Math.floor(i);
}
//for loop goes here
\$\endgroup\$
2
  • \$\begingroup\$ One more question: Would you also do an else { i = Math.floor(i); } or just keep i as a non_Integer otherwise? \$\endgroup\$
    – serv-inc
    Feb 11, 2016 at 12:09
  • 1
    \$\begingroup\$ @user you're absolutely right, you do want to convert i to integer. \$\endgroup\$
    – Pimgd
    Feb 11, 2016 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.