<commit_before>function showPoints(elem) {
    $(".div-exercise").each(function() {
        $(this).hide();
    });
    $("#div" + elem.id).show();
}

function toggle(elem) {
    if (elem.hasClass("star-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("V");
                elem.prop('indeterminate', true);
                elem.prop('checked', true);
                break;
            case "V":
                elem.val("O");
                elem.prop('indeterminate', false);
                elem.prop('checked', true);
                break;
            case "O":
                elem.val("");
                elem.prop('indeterminate', false);
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    } else if (elem.hasClass("ns-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("O");
                elem.prop('checked', true);
                break;
            case "O":
                elem.val("");
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    } else if (elem.hasClass("q-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("E");
                elem.prop('indeterminate', true);
                elem.prop('checked', true);
                break;
            case "E":
                elem.val("K");
                elem.prop('indeterminate', false);
                elem.prop('checked', true);
                break;
            case "K":
                elem.val("");
                elem.prop('indeterminate', false);
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    }
}

var flag = false;

function selectAll() {
    $(".ns-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('checked', true);
    });
    $(".star-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', true);
    });
}

function selectAllButStar() {
    $(".ns-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('checked', true);
    });
    $(".star-checkbox").each(function() {
        $(this).val("V");
        $(this).prop('indeterminate', true);
        $(this).prop('checked', true);
    });
}

function removeAll() {
    $(".ns-checkbox").each(function() {
        $(this).val("");
        $(this).prop('checked', false);
    });
    $(".star-checkbox").each(function() {
        $(this).val("");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', false);
    });
}

function selectAllQuestionsYes() {
    $(".q-checkbox").each(function() {
        $(this).val("K");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', true);
    });
}

function selectAllQuestionsNo() {
    $(".q-checkbox").each(function() {
        $(this).val("E");
        $(this).prop('indeterminate', true);
        $(this).prop('checked', true);
    });
}

function removeAllQuestions() {
    $(".q-checkbox").each(function() {
        $(this).val("");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', false);
    });
}

function enable() {
    $("#selCourseNo").prop('disabled', false);
    $("#selCourseNo").selectpicker('refresh');
}

function cancel() {
    removeAll();
    removeAllQuestions();
    flag = false;
    $(".checkbox").each(function(i) {
        $(this).prop('disabled', true);
    });
    $("#selCourseNo").prop('disabled', false);
    $("#selCourseNo").selectpicker('refresh');
}

$(document).ready(function() {
    $('form.destroy-form').on('submit', function(submit) {
        var confirm_message = $(this).attr('data-confirm');
        if (!confirm(confirm_message)) {
            submit.preventDefault();
        }
    });
    if ($("#numberOfReturnedExercises").length) {
        var labels = [];
        var data = [];
        $('input', '#numberOfReturnedExercises').each(function() {
            labels.push($(this).attr('id'));
            data.push($(this).attr('value'));
        });
        var ctx = $("#exerciseChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Tehtäviä palauttaneiden opiskelijoiden lukumäärä",
                    fillColor: "rgba(220,220,220,0.5)",
                    strokeColor: "rgba(220,220,220,0.8)",
                    highlightFill: "rgba(220,220,220,0.75)",
                    highlightStroke: "rgba(220,220,220,1)",
                    data: data
                }
            ]
        };
        var exerciseChart = new Chart(ctx).Bar(data);
    }
    if ($("#numberOfReturnedProblems").length) {
        var labels = [];
        var data = [];
        $('input', '#numberOfReturnedProblems').each(function() {
            labels.push($(this).attr('id'));
            data.push($(this).attr('value'));
        });
        var ctx = $("#problemChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Tehtäviä palauttaneiden opiskelijoiden lukumäärä",
                    fillColor: "rgba(220,220,220,0.5)",
                    strokeColor: "rgba(220,220,220,0.8)",
                    highlightFill: "rgba(220,220,220,0.75)",
                    highlightStroke: "rgba(220,220,220,1)",
                    data: data
                }
            ]
        };
        var exerciseChart = new Chart(ctx).Bar(data);
    }
    if ($("#numberOfCorrectProblems").length) {
        var labels = [];
        var data_correct = [];
        var data_incorrect = [];
        $('input', '#numberOfCorrectProblems').each(function() {
            labels.push($(this).attr('id').slice(0,-1));
            var temp = $(this).attr('value').split("|");
            data_correct.push(temp[0]);
            data_incorrect.push(temp[1]);
        });
        var ctx = $("#starProblemChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Oikein",
                    fillColor: "rgba(70,191,189,0.5)",
                    strokeColor: "rgba(70,191,189,0.8)",
                    highlightFill: "rgba(70,191,189,0.75)",
                    highlightStroke: "rgba(70,191,189,1)",
                    data: data_correct
                },
                {
                    label: "Väärin",
                    fillColor: "rgba(247,70,74,0.5)",
                    strokeColor: "rgba(247,70,74,0.8)",
                    highlightFill: "rgba(247,70,74,0.75)",
                    highlightStroke: "rgba(247,70,74,1)",
                    data: data_incorrect
                }
            ]
        };
        var starExerciseChart = new Chart(ctx).Bar(data);
    }
    $("#nExercises").change(function() {
        $("#starExercises").children().remove();
        for (var i = 1; i <= $(this).val(); i++) {
            $("#starExercises").append('<option value=' + i + '>' + i + '</option>').selectpicker('refresh');
        }
        $("#divStar").show();
    });
    $(".ns-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("O");
                $(this).prop('checked', true);
                break;
            case "O":
                $(this).val("");
                $(this).prop('checked', false);
        }
    });
    $(".star-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("V");
                $(this).prop('indeterminate', true);
                $(this).prop('checked', true);
                break;
            case "V":
                $(this).val("O");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', true);
                break;
            case "O":
                $(this).val("");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', false);
        }
    });
    $(".q-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("E");
                $(this).prop('indeterminate', true);
                $(this).prop('checked', true);
                break;
            case "E":
                $(this).val("K");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', true);
                break;
            case "K":
                $(this).val("");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', false);
        }
    });

    $(".selectpicker").selectpicker();

    $("#selCourseNo").change(function() {
        $("#selCourseNo").prop('disabled', true);
        $("#selCourseNo").selectpicker('refresh');
        var student_no = $(this).val();
        $(".checkbox").each(function(i) {
            $(this).prop('disabled', false);
            if ($(this).hasClass("q-checkbox")) {
                var question_no = $(this).attr('name');
                var temp = student_no + question_no;
                switch ($(document.getElementById(temp)).val()) {
                    case " ":
                        $(this).val("");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                        break;
                    case "K":
                        $(this).val("K");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', true);
                        break;
                    case "E":
                        $(this).val("E");
                        $(this).prop('indeterminate', true);
                        $(this).prop('checked', true);
                }
            } else {
                var problem_no = $(this).attr('name');
                var temp = student_no + "p" + problem_no;
                switch ($(document.getElementById(temp)).val()) {
                    case " ":
                        $(this).val("");
               		$(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                        break;
                    case "O":
                        $(this).val("O");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', true);
                        break;
                    case "V":
                        $(this).val("V");
                        $(this).prop('indeterminate', true);
                        $(this).prop('checked', true);
                }
            }
        });
        flag = true;
    });
});

$(document).keydown(function(e) {
    if (flag) {
        switch (e.which) {
            case 49:
                toggle($("#p1"));
                break;
            case 50:
                toggle($("#p2"));
                break;
            case 51:
                toggle($("#p3"));
                break;
            case 52:
                toggle($("#p4"));
                break;
            case 53:
                toggle($("#p5"));
                break;
            case 54:
                toggle($("#p6"));
                break;
            case 55:
                toggle($("#p7"));
                break;
            case 56:
                toggle($("#p8"));
                break;
            case 57:
                toggle($("#p9"));
                break;
            case 48:
                toggle($("#p10"));
                break;
            case 81:
                toggle($("#p11"));
                break;
            case 87:
                toggle($("#p12"));
                break;
            case 69:
                toggle($("#p13"));
                break;
            case 82:
                toggle($("#p14"));
                break;
            case 84:
                toggle($("#p15"));
                break;
            case 89:
                toggle($("#p16"));
                break;
            case 85:
                toggle($("#p17"));
                break;
            case 73:
                toggle($("#p18"));
                break;
            case 79:
                toggle($("#p19"));
                break;
            case 80:
                toggle($("#p20"));
                break;
            case 65:
                toggle($("#q1"));
                break;
            case 83:
                toggle($("#q2"));
                break;
            case 68:
                toggle($("#q3"));
                break;
            case 70:
                toggle($("#q4"));
                break;
            default:
                return;
        }
    }
});
<commit_msg>varmuuden vuoksi<commit_after>function showPoints(elem) {
    $(".div-exercise").each(function() {
        $(this).hide();
    });
    $("#div" + elem.id).show();
}

function toggle(elem) {
    if (elem.hasClass("star-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("V");
                elem.prop('indeterminate', true);
                elem.prop('checked', true);
                break;
            case "V":
                elem.val("O");
                elem.prop('indeterminate', false);
                elem.prop('checked', true);
                break;
            case "O":
                elem.val("");
                elem.prop('indeterminate', false);
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    } else if (elem.hasClass("ns-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("O");
                elem.prop('checked', true);
                break;
            case "O":
                elem.val("");
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    } else if (elem.hasClass("q-checkbox")) {
        switch (elem.val()) {
            case "":
                elem.val("E");
                elem.prop('indeterminate', true);
                elem.prop('checked', true);
                break;
            case "E":
                elem.val("K");
                elem.prop('indeterminate', false);
                elem.prop('checked', true);
                break;
            case "K":
                elem.val("");
                elem.prop('indeterminate', false);
                elem.prop('checked', false);
                break;
            default:
                return;
        }
    }
}

var flag = false;

function selectAll() {
    $(".ns-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('checked', true);
    });
    $(".star-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', true);
    });
}

function selectAllButStar() {
    $(".ns-checkbox").each(function() {
        $(this).val("O");
        $(this).prop('checked', true);
    });
    $(".star-checkbox").each(function() {
        $(this).val("V");
        $(this).prop('indeterminate', true);
        $(this).prop('checked', true);
    });
}

function removeAll() {
    $(".ns-checkbox").each(function() {
        $(this).val("");
        $(this).prop('checked', false);
    });
    $(".star-checkbox").each(function() {
        $(this).val("");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', false);
    });
}

function selectAllQuestionsYes() {
    $(".q-checkbox").each(function() {
        $(this).val("K");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', true);
    });
}

function selectAllQuestionsNo() {
    $(".q-checkbox").each(function() {
        $(this).val("E");
        $(this).prop('indeterminate', true);
        $(this).prop('checked', true);
    });
}

function removeAllQuestions() {
    $(".q-checkbox").each(function() {
        $(this).val("");
        $(this).prop('indeterminate', false);
        $(this).prop('checked', false);
    });
}

function enable() {
    $("#selCourseNo").prop('disabled', false);
    $("#selCourseNo").selectpicker('refresh');
}

function cancel() {
    removeAll();
    removeAllQuestions();
    flag = false;
    $(".checkbox").each(function(i) {
        $(this).prop('disabled', true);
    });
    $("#selCourseNo").prop('disabled', false);
    $("#selCourseNo").selectpicker('refresh');
    $("#selCourseNo").focus();
}

$(document).ready(function() {
    $('form.destroy-form').on('submit', function(submit) {
        var confirm_message = $(this).attr('data-confirm');
        if (!confirm(confirm_message)) {
            submit.preventDefault();
        }
    });
    if ($("#numberOfReturnedExercises").length) {
        var labels = [];
        var data = [];
        $('input', '#numberOfReturnedExercises').each(function() {
            labels.push($(this).attr('id'));
            data.push($(this).attr('value'));
        });
        var ctx = $("#exerciseChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Tehtäviä palauttaneiden opiskelijoiden lukumäärä",
                    fillColor: "rgba(220,220,220,0.5)",
                    strokeColor: "rgba(220,220,220,0.8)",
                    highlightFill: "rgba(220,220,220,0.75)",
                    highlightStroke: "rgba(220,220,220,1)",
                    data: data
                }
            ]
        };
        var exerciseChart = new Chart(ctx).Bar(data);
    }
    if ($("#numberOfReturnedProblems").length) {
        var labels = [];
        var data = [];
        $('input', '#numberOfReturnedProblems').each(function() {
            labels.push($(this).attr('id'));
            data.push($(this).attr('value'));
        });
        var ctx = $("#problemChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Tehtäviä palauttaneiden opiskelijoiden lukumäärä",
                    fillColor: "rgba(220,220,220,0.5)",
                    strokeColor: "rgba(220,220,220,0.8)",
                    highlightFill: "rgba(220,220,220,0.75)",
                    highlightStroke: "rgba(220,220,220,1)",
                    data: data
                }
            ]
        };
        var exerciseChart = new Chart(ctx).Bar(data);
    }
    if ($("#numberOfCorrectProblems").length) {
        var labels = [];
        var data_correct = [];
        var data_incorrect = [];
        $('input', '#numberOfCorrectProblems').each(function() {
            labels.push($(this).attr('id').slice(0,-1));
            var temp = $(this).attr('value').split("|");
            data_correct.push(temp[0]);
            data_incorrect.push(temp[1]);
        });
        var ctx = $("#starProblemChart").get(0).getContext("2d");
        var data = {
            labels: labels,
            datasets: [
                {
                    label: "Oikein",
                    fillColor: "rgba(70,191,189,0.5)",
                    strokeColor: "rgba(70,191,189,0.8)",
                    highlightFill: "rgba(70,191,189,0.75)",
                    highlightStroke: "rgba(70,191,189,1)",
                    data: data_correct
                },
                {
                    label: "Väärin",
                    fillColor: "rgba(247,70,74,0.5)",
                    strokeColor: "rgba(247,70,74,0.8)",
                    highlightFill: "rgba(247,70,74,0.75)",
                    highlightStroke: "rgba(247,70,74,1)",
                    data: data_incorrect
                }
            ]
        };
        var starExerciseChart = new Chart(ctx).Bar(data);
    }
    $("#nExercises").change(function() {
        $("#starExercises").children().remove();
        for (var i = 1; i <= $(this).val(); i++) {
            $("#starExercises").append('<option value=' + i + '>' + i + '</option>').selectpicker('refresh');
        }
        $("#divStar").show();
    });
    $(".ns-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("O");
                $(this).prop('checked', true);
                break;
            case "O":
                $(this).val("");
                $(this).prop('checked', false);
        }
    });
    $(".star-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("V");
                $(this).prop('indeterminate', true);
                $(this).prop('checked', true);
                break;
            case "V":
                $(this).val("O");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', true);
                break;
            case "O":
                $(this).val("");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', false);
        }
    });
    $(".q-checkbox").click(function() {
        switch ($(this).val()) {
            case "":
                $(this).val("E");
                $(this).prop('indeterminate', true);
                $(this).prop('checked', true);
                break;
            case "E":
                $(this).val("K");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', true);
                break;
            case "K":
                $(this).val("");
                $(this).prop('indeterminate', false);
                $(this).prop('checked', false);
        }
    });

    $(".selectpicker").selectpicker();

    $("#selCourseNo").change(function() {
        $("#selCourseNo").prop('disabled', true);
        $("#selCourseNo").selectpicker('refresh');
        var student_no = $(this).val();
        $(".checkbox").each(function(i) {
            $(this).prop('disabled', false);
            if ($(this).hasClass("q-checkbox")) {
                var question_no = $(this).attr('name');
                var temp = student_no + question_no;
                switch ($(document.getElementById(temp)).val()) {
                    case " ":
                        $(this).val("");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                        break;
                    case "K":
                        $(this).val("K");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', true);
                        break;
                    case "E":
                        $(this).val("E");
                        $(this).prop('indeterminate', true);
                        $(this).prop('checked', true);
                        break;
                    default:
                        $(this).val("");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                }
            } else {
                var problem_no = $(this).attr('name');
                var temp = student_no + "p" + problem_no;
                switch ($(document.getElementById(temp)).val()) {
                    case " ":
                        $(this).val("");
               		   $(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                        break;
                    case "O":
                        $(this).val("O");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', true);
                        break;
                    case "V":
                        $(this).val("V");
                        $(this).prop('indeterminate', true);
                        $(this).prop('checked', true);
                        break;
                    default:
                        $(this).val("");
                        $(this).prop('indeterminate', false);
                        $(this).prop('checked', false);
                }
            }
        });
        flag = true;
    });
});

$(document).keydown(function(e) {
    if (flag) {
        switch (e.which) {
            case 49:
                toggle($("#p1"));
                break;
            case 50:
                toggle($("#p2"));
                break;
            case 51:
                toggle($("#p3"));
                break;
            case 52:
                toggle($("#p4"));
                break;
            case 53:
                toggle($("#p5"));
                break;
            case 54:
                toggle($("#p6"));
                break;
            case 55:
                toggle($("#p7"));
                break;
            case 56:
                toggle($("#p8"));
                break;
            case 57:
                toggle($("#p9"));
                break;
            case 48:
                toggle($("#p10"));
                break;
            case 81:
                toggle($("#p11"));
                break;
            case 87:
                toggle($("#p12"));
                break;
            case 69:
                toggle($("#p13"));
                break;
            case 82:
                toggle($("#p14"));
                break;
            case 84:
                toggle($("#p15"));
                break;
            case 89:
                toggle($("#p16"));
                break;
            case 85:
                toggle($("#p17"));
                break;
            case 73:
                toggle($("#p18"));
                break;
            case 79:
                toggle($("#p19"));
                break;
            case 80:
                toggle($("#p20"));
                break;
            case 65:
                toggle($("#q1"));
                break;
            case 83:
                toggle($("#q2"));
                break;
            case 68:
                toggle($("#q3"));
                break;
            case 70:
                toggle($("#q4"));
                break;
            default:
                return;
        }
    }
});
<|endoftext|>


<commit_before>var ExtractTextPlugin = require('extract-text-webpack-plugin');
var dirVars = require('./base/dir-vars.config.js');

const moduleConfig = require('./inherit/module.config.js');

moduleConfig.rules.push({
  test: /\.css$/,
  include: dirVars.srcRootDir,
  use: ExtractTextPlugin.extract([
    {
      loader: 'css-loader',
      options: {
        minimize: true,
        '-autoprefixer': true,
      },
    },
    // {
    //   loader: 'postcss-loader',
    // }
  ]),
});

module.exports = moduleConfig;<commit_msg>fix No PostCSS Config bug<commit_after>var ExtractTextPlugin = require('extract-text-webpack-plugin');
var dirVars = require('./base/dir-vars.config.js');

const moduleConfig = require('./inherit/module.config.js');

moduleConfig.rules.push({
  test: /\.css$/,
  include: dirVars.srcRootDir,
  use: ExtractTextPlugin.extract({
    fallback: "style-loader",
    use: "css-loader"
  })
});

module.exports = moduleConfig;<|endoftext|>


<commit_before>var zetta = require('zetta');
var MemoryPeerRegistry = require('./memory_peer_registry');
var MemoryRegistry = require('./memory_registry');
var ServiceRegistry = require('./service_registry');
var DeviceDataSqs = require('zetta-device-data-sqs');

var port = process.env.MAPPED_PORT || 3001;
var version = process.env.VERSION || '0';

var options = {
  host: process.env.COREOS_PRIVATE_IPV4
};

var instanceUrl = 'http://' + process.env.COREOS_PRIVATE_IPV4 + ':' + port;

var peerRegistry = new MemoryPeerRegistry();
var serviceRegistryClient = new ServiceRegistry(options);

var instance = zetta({
  registry: new MemoryRegistry(), // no device registry is needed
  peerRegistry: peerRegistry
});

instance.name('cloud-' + port);

if (process.env.DEVICE_DATA_QUEUE) {
  var sqs = new DeviceDataSqs({
    queueUrl: process.env.DEVICE_DATA_QUEUE
  });

  instance.use(sqs.collect());
}

instance.httpServer.server.on('close', function() {
  serviceRegistryClient.remove('cloud-target', instanceUrl);
  clearInterval(timer);
});

var timer = null;
instance.listen(port, function() {
  serviceRegistryClient.add('cloud-target', instanceUrl, version);
  timer = setInterval(function() {
    serviceRegistryClient.add('cloud-target', instanceUrl, version);
  }, 60000);
});

['SIGINT', 'SIGTERM'].forEach(function(signal) {
  process.on(signal, function() {
    clearInterval(timer);
    serviceRegistryClient.remove('cloud-target', instanceUrl, function() {
      process.exit();
    });
  });
});
<commit_msg>Added accesskey and secret from env to aws config used for local vagrant deploy<commit_after>var zetta = require('zetta');
var MemoryPeerRegistry = require('./memory_peer_registry');
var MemoryRegistry = require('./memory_registry');
var ServiceRegistry = require('./service_registry');
var DeviceDataSqs = require('zetta-device-data-sqs');

var port = process.env.MAPPED_PORT || 3001;
var version = process.env.VERSION || '0';

var options = {
  host: process.env.COREOS_PRIVATE_IPV4
};

var instanceUrl = 'http://' + process.env.COREOS_PRIVATE_IPV4 + ':' + port;

var peerRegistry = new MemoryPeerRegistry();
var serviceRegistryClient = new ServiceRegistry(options);

var instance = zetta({
  registry: new MemoryRegistry(), // no device registry is needed
  peerRegistry: peerRegistry
});

instance.name('cloud-' + port);

if (process.env.DEVICE_DATA_QUEUE) {

  var sqs = new DeviceDataSqs({
    queueUrl: process.env.DEVICE_DATA_QUEUE,
    accessKeyId: process.env.AWS_ACCESSKEY,
    secretAccessKey: process.env.AWS_SECRET
  });

  instance.use(sqs.collect());
}

instance.httpServer.server.on('close', function() {
  serviceRegistryClient.remove('cloud-target', instanceUrl);
  clearInterval(timer);
});

var timer = null;
instance.listen(port, function() {
  serviceRegistryClient.add('cloud-target', instanceUrl, version);
  timer = setInterval(function() {
    serviceRegistryClient.add('cloud-target', instanceUrl, version);
  }, 60000);
});

['SIGINT', 'SIGTERM'].forEach(function(signal) {
  process.on(signal, function() {
    clearInterval(timer);
    serviceRegistryClient.remove('cloud-target', instanceUrl, function() {
      process.exit();
    });
  });
});
<|endoftext|>


<commit_before>const app = require('../index');
const models = app.set('models');
const moment = require('moment-timezone');
const async = require('async');
const activities = require('../app/constants/activities');
const slackLib = require('../app/lib/slack');

const today = new Date();

// Heroku scheduler only has daily or hourly cron jobs, we only want to run
// this script once per week on Monday (1). If the day is not Monday on production
// we won't execute the script
if (process.env.NODE_ENV === 'production' && today.getDay() !== 1) {
  console.log('NODE_ENV is production and day is not Monday, script aborted!');
  process.exit();
}

var thisWeekRaw = moment()
    .tz('America/New_York')
    .startOf('isoWeek')
    .add(9, 'hours');
const thisWeek = thisWeekRaw.format();
const lastWeek = thisWeekRaw.subtract(1, 'week').format();

const createdAtClause = {
  $gt: lastWeek,
  $lt: thisWeek
};
const donationClause = {
  createdAt: createdAtClause,
  tags: {
    $contains: ['Donation']
  }
};
const expenseClause = {
  $lt: 0
};
const unapprovedExpenseClause = {
  createdAt: createdAtClause,
  amount: expenseClause,
  approved: false
};
const approvedExpenseClause = {
  createdAt: createdAtClause,
  amount: expenseClause,
  approved: true
};

async.auto({
  donationCount: cb => {
    models.Transaction
        .count({ where: donationClause })
        .done(cb);
  },

  unapprovedExpenseCount: cb => {
    models.Transaction
        .count({ where: unapprovedExpenseClause })
        .done(cb);
  },

  approvedExpenseCount: cb => {
    models.Transaction
        .count({ where: approvedExpenseClause })
        .done(cb);
  },

  stripeReceivedCount: cb => {
    models.Activity
        .count({
          where: {
            createdAt: createdAtClause,
            type: activities.WEBHOOK_STRIPE_RECEIVED
          }
        })
        .done(cb);
  },

  donationAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: donationClause
        })
        .map(row => ' ' + row.SUM + ' ' + row.currency)
        .done(cb);
  },

  unapprovedExpenseAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: unapprovedExpenseClause
        })
        .map(row => ' ' + -row.SUM + ' ' + row.currency)
        .done(cb);
  },

  approvedExpenseAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: approvedExpenseClause
        })
        .map(row => ' ' + -row.SUM + ' ' + row.currency)
        .done(cb);
  }
}, (err, results) => {
  if (err) {
    console.log('err', err);
    process.exit();
  } else {
    const report = transactionReportString(results);

    console.log(report);

    slackLib.postMessage(report)
    .then(() => {
      console.log('Reporting done!');
      process.exit();
    });
  }
});

function transactionReportString(results) {
  return `Weekly transactions summary:
- ${results.donationCount} donations received
- ${results.unapprovedExpenseCount} expenses pending approval
- ${results.approvedExpenseCount} approved expenses
- ${results.stripeReceivedCount} payments received from Stripe
Details:
- total amount collected:${results.donationAmount}
- total expenses pending approval:${results.unapprovedExpenseAmount}
- total approved expenses:${results.approvedExpenseAmount}`;
}<commit_msg>Fix clause to select donations in weekly transactions report<commit_after>const app = require('../index');
const models = app.set('models');
const moment = require('moment-timezone');
const async = require('async');
const activities = require('../app/constants/activities');
const slackLib = require('../app/lib/slack');

const today = new Date();

// Heroku scheduler only has daily or hourly cron jobs, we only want to run
// this script once per week on Monday (1). If the day is not Monday on production
// we won't execute the script
if (process.env.NODE_ENV === 'production' && today.getDay() !== 1) {
  console.log('NODE_ENV is production and day is not Monday, script aborted!');
  process.exit();
}

var thisWeekRaw = moment()
    .tz('America/New_York')
    .startOf('isoWeek')
    .add(9, 'hours');
const thisWeek = thisWeekRaw.format();
const lastWeek = thisWeekRaw.subtract(1, 'week').format();

const createdAtClause = {
  $gt: lastWeek,
  $lt: thisWeek
};
const donationClause = {
  createdAt: createdAtClause,
  amount: { $gt: 0 }
};
const expenseClause = {
  $lt: 0
};
const unapprovedExpenseClause = {
  createdAt: createdAtClause,
  amount: expenseClause,
  approved: false
};
const approvedExpenseClause = {
  createdAt: createdAtClause,
  amount: expenseClause,
  approved: true
};

async.auto({
  donationCount: cb => {
    models.Transaction
        .count({ where: donationClause })
        .done(cb);
  },

  unapprovedExpenseCount: cb => {
    models.Transaction
        .count({ where: unapprovedExpenseClause })
        .done(cb);
  },

  approvedExpenseCount: cb => {
    models.Transaction
        .count({ where: approvedExpenseClause })
        .done(cb);
  },

  stripeReceivedCount: cb => {
    models.Activity
        .count({
          where: {
            createdAt: createdAtClause,
            type: activities.WEBHOOK_STRIPE_RECEIVED
          }
        })
        .done(cb);
  },

  donationAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: donationClause
        })
        .map(row => ' ' + row.SUM + ' ' + row.currency)
        .done(cb);
  },

  unapprovedExpenseAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: unapprovedExpenseClause
        })
        .map(row => ' ' + -row.SUM + ' ' + row.currency)
        .done(cb);
  },

  approvedExpenseAmount: cb => {
    models.Transaction
        .aggregate('amount', 'SUM', {
          plain: false,
          group: ['currency'],
          attributes: ['currency'],
          where: approvedExpenseClause
        })
        .map(row => ' ' + -row.SUM + ' ' + row.currency)
        .done(cb);
  }
}, (err, results) => {
  if (err) {
    console.log('err', err);
    process.exit();
  } else {
    const report = transactionReportString(results);

    console.log(report);

    slackLib.postMessage(report)
    .then(() => {
      console.log('Reporting done!');
      process.exit();
    });
  }
});

function transactionReportString(results) {
  return `Weekly transactions summary:
- ${results.donationCount} donations received
- ${results.unapprovedExpenseCount} expenses pending approval
- ${results.approvedExpenseCount} approved expenses
- ${results.stripeReceivedCount} payments received from Stripe
Details:
- total amount collected:${results.donationAmount}
- total expenses pending approval:${results.unapprovedExpenseAmount}
- total approved expenses:${results.approvedExpenseAmount}`;
}
<|endoftext|>


<commit_before>(function(){
	var component = {
		fileName: 		"Physics",
		classNames:		["Physics"],
		requirements:	[], // Entity?
		description:	"Physics class",
		credits:		"By Luke Nickerson, 2014, some funcitons from stardust.js"
	};

	var Physics = component.Physics = function(){
		this.isCollisionDetectionOn = true;
		this.isObjectGravityOn = false;
		//this.isLinearGravityOn = true;
		this.elasticity = 0.7;
		this.gravitationalConstant = 0.5; // "big G"
	}
	Physics.prototype.apply = function(world){
		var p = this;
		// Loop over all movable entities
		world.loopOverEntities("physics",function(entity1Index, ent1){
			if (ent1.isImmovable) {
				o.force.clear();
				o.acc.clear();
				o.vel.clear();
			} else if (ent1.mass > 0) {
				var forceAcc;
				// Standard newtonian physics...
				ent1.force.add(ent1.impulse);
				forceAcc = new RocketBoots.Coords((ent1.force.x / ent1.mass), (ent1.force.y / ent1.mass));
				ent1.acc.add(forceAcc);
				ent1.vel.add(ent1.acc);
				ent1.pos.add(ent1.vel);
				ent1.acc.clear();
				ent1.force.clear();
				ent1.impulse.clear();
			}
			if (p.isObjectGravityOn) {
				world.loopOverEntities("physics", function(entity2Index, ent2){
					p.applyGravityForce(ent1, ent2);
				});
			}
			if (world.isBounded) {
				world.keepCoordsInBounds(ent1.pos);
			}
		});

		if (p.isCollisionDetectionOn) {
			world.loopOverEntities("physical", function(entity2Index, ent1){
				world.loopOverEntities("physical", function(entity2Index, ent2){
					var r = ent1.pos.getDistance(ent2.pos);
					if (p.isCollisionDetectionOn) {
						if (r == 0) {
							// Don't do anything (Black hole or ent2 is the same as ent1)
						} else {
							var edgeToEdgeDist = r - ent1.radius - ent2.radius;
							if (edgeToEdgeDist <= 0) {
								//console.log("hit");

								var pushBack = edgeToEdgeDist / 1; //(edgeToEdgeDist / 1);
								if (ent1.mass <= ent2.mass) {
									ent1.pos.add( ent1.pos.getUnitVector(ent2.pos).multiply(pushBack) );
								} else {
									ent2.pos.add( ent2.pos.getUnitVector(ent1.pos).multiply(pushBack) );
								}

								p.setNewCollisionVels(ent1, ent2, p.elasticity);
							}
						}
					}
				});
				if (world.isBounded) {
					world.keepCoordsInBounds(ent1.pos);
				}
			});
		}
	};

	Physics.prototype.applyGravityForce = function (o1, o2) {
		var r, rv, Gmm, rSquared, n;
		// Apply gravity forces: F = G (m1 m2) / r^2
		// http://en.wikipedia.org/wiki/Newton's_law_of_universal_gravitation#Vector_form
		//console.log("Forces on", o1.name, " due to ", o2.name);
		r = o1.pos.getDistance(o2.pos);
		rv = o1.pos.getUnitVector(o2.pos);
		//console.log("unit vector", JSON.stringify(rv));

		Gmm = this.gravitationalConstant * o1.mass * o2.mass;
		rSquared = Math.pow(r, 2);
		n = (rSquared == 0) ? 0 : (Gmm/rSquared);
		rv.multiply(n);
		//console.log(JSON.stringify(rv));
		o1.force.add(rv);
		//console.log("physics", i, b, o1.bigG, o1.mass, o2.mass);
	}

	Physics.prototype.setNewCollisionVels = function(o1, o2, elasticity){
		// http://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page=3
		if (o1.mass <= 0 || o2.mass <= 0) {
			return false;
		}
		//console.log(o1.name, o2.name);
		//console.log("original", o1.vel.x, o1.vel.y, o2.vel.x, o2.vel.y);
		//console.log("momentum before", (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude()));
		var p = (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude());
		var n = o1.pos.getUnitVector(o2.pos);
		//console.log("n = ", n);
		var a1 = o1.vel.getDot(n);
		var a2 = o2.vel.getDot(n);
		var optimizedP = (2 * (a1 - a2)) / (o1.mass + o2.mass);
		o1.vel.add( n.getMultiply(-1 * optimizedP * o2.mass) );
		o1.vel.multiply(elasticity);
		o2.vel.add( n.getMultiply(optimizedP * o1.mass) );
		o1.vel.multiply(elasticity);
		//var pNew = (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude());
		//console.log(pNew - p);
		//if (pNew > p) {
			 //console.log(o1.name, o2.name, "pNew > p", pNew, p);
		//}else console.log(o1.name, o2.name, "pNew <= p", pNew, p);
		//console.log("after", newV1.x, newV1.y, newV2.x, newV2.y);
		//console.log("momentum after", (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude()));
		return true;
	}

	// Install into RocketBoots if it exists
	if (typeof RocketBoots === "object") {
		RocketBoots.installComponent(component);
	} else { // Otherwise put the classes on the global window object
		for (var i = 0; i < component.classNames.length; i++) {
			window[component.classNames[i]] = component[component.classNames[i]];
		}
	}
})();<commit_msg>minor fixes<commit_after>(function(){
	var component = {
		fileName: 		"Physics",
		classNames:		["Physics"],
		requirements:	[], // Dependent on Entity-like objects, but not a strict requirement
		description:	"Physics class",
		credits:		"By Luke Nickerson, 2014, 2017, originally from stardust.js"
	};

	var Physics = component.Physics = function(){
		this.isCollisionDetectionOn = true;
		this.isObjectGravityOn = false;
		//this.isLinearGravityOn = true;
		this.elasticity = 0.7;
		this.gravitationalConstant = 0.5; // "big G"
	}
	Physics.prototype.apply = function(world){
		var p = this;
		// Loop over all movable entities
		world.loopOverEntities("physics",function(entity1Index, ent1){
			if (ent1.isImmovable) {
				ent1.vel.clear();
			} else if (ent1.mass > 0) {
				let forceAcc;
				// Standard newtonian physics...
				ent1.force.add(ent1.impulse);
				forceAcc = new RocketBoots.Coords((ent1.force.x / ent1.mass), (ent1.force.y / ent1.mass));
				ent1.acc.add(forceAcc);
				ent1.vel.add(ent1.acc);
				ent1.pos.add(ent1.vel);
			}
			// Acceleration, force, and impulse are momentary forces as currently coded
			ent1.acc.clear();
			ent1.force.clear();
			ent1.impulse.clear();
			// Do gravity between objects
			if (p.isObjectGravityOn) {
				world.loopOverEntities("physics", function(entity2Index, ent2){
					p.applyGravityForce(ent1, ent2);
				});
			}
			if (world.isBounded) {
				world.keepCoordsInBounds(ent1.pos);
			}
		});

		if (p.isCollisionDetectionOn) {
			world.loopOverEntities("physical", function(entity2Index, ent1){
				world.loopOverEntities("physical", function(entity2Index, ent2){
					var r = ent1.pos.getDistance(ent2.pos);
					if (p.isCollisionDetectionOn) {
						if (r == 0) {
							// Don't do anything (Black hole or ent2 is the same as ent1)
						} else {
							let edgeToEdgeDist = r - ent1.radius - ent2.radius;
							if (edgeToEdgeDist <= 0) {
								//console.log("hit");

								let pushBack = edgeToEdgeDist / 1; //(edgeToEdgeDist / 1);
								if (ent1.mass <= ent2.mass) {
									ent1.pos.add( ent1.pos.getUnitVector(ent2.pos).multiply(pushBack) );
								} else {
									ent2.pos.add( ent2.pos.getUnitVector(ent1.pos).multiply(pushBack) );
								}

								p.setNewCollisionVels(ent1, ent2, p.elasticity);
							}
						}
					}
				});
				if (world.isBounded) {
					world.keepCoordsInBounds(ent1.pos);
				}
			});
		}
	};

	Physics.prototype.applyGravityForce = function (o1, o2) {
		var r, rv, Gmm, rSquared, n;
		// Apply gravity forces: F = G (m1 m2) / r^2
		// http://en.wikipedia.org/wiki/Newton's_law_of_universal_gravitation#Vector_form
		//console.log("Forces on", o1.name, " due to ", o2.name);
		r = o1.pos.getDistance(o2.pos);
		rv = o1.pos.getUnitVector(o2.pos);
		//console.log("unit vector", JSON.stringify(rv));

		Gmm = this.gravitationalConstant * o1.mass * o2.mass;
		rSquared = Math.pow(r, 2);
		n = (rSquared == 0) ? 0 : (Gmm/rSquared);
		rv.multiply(n);
		//console.log(JSON.stringify(rv));
		o1.force.add(rv);
		//console.log("physics", i, b, o1.bigG, o1.mass, o2.mass);
	}

	Physics.prototype.setNewCollisionVels = function(o1, o2, elasticity){
		// http://www.gamasutra.com/view/feature/131424/pool_hall_lessons_fast_accurate_.php?page=3
		if (o1.mass <= 0 || o2.mass <= 0) {
			return false;
		}
		//console.log(o1.name, o2.name);
		//console.log("original", o1.vel.x, o1.vel.y, o2.vel.x, o2.vel.y);
		//console.log("momentum before", (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude()));
		var p = (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude());
		var n = o1.pos.getUnitVector(o2.pos);
		//console.log("n = ", n);
		var a1 = o1.vel.getDot(n);
		var a2 = o2.vel.getDot(n);
		var optimizedP = (2 * (a1 - a2)) / (o1.mass + o2.mass);
		o1.vel.add( n.getMultiply(-1 * optimizedP * o2.mass) );
		o1.vel.multiply(elasticity);
		o2.vel.add( n.getMultiply(optimizedP * o1.mass) );
		o1.vel.multiply(elasticity);
		//var pNew = (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude());
		//console.log(pNew - p);
		//if (pNew > p) {
			 //console.log(o1.name, o2.name, "pNew > p", pNew, p);
		//}else console.log(o1.name, o2.name, "pNew <= p", pNew, p);
		//console.log("after", newV1.x, newV1.y, newV2.x, newV2.y);
		//console.log("momentum after", (o1.mass * o1.vel.getMagnitude()) + (o2.mass * o2.vel.getMagnitude()));
		return true;
	}

	// Install into RocketBoots if it exists
	if (typeof RocketBoots === "object") {
		RocketBoots.installComponent(component);
	} else { // Otherwise put the classes on the global window object
		for (var i = 0; i < component.classNames.length; i++) {
			window[component.classNames[i]] = component[component.classNames[i]];
		}
	}
})();<|endoftext|>


<commit_before>/*
 * grunt-combine
 * https://github.com/mcgaryes/grunt-combine
 * https://github.com/gruntjs/grunt/
 *
 * Copyright (c) 2013 Eric McGary
 * Licensed under the MIT license.
 *
 * @main grunt-combine
 */
module.exports = function(grunt) {

  "use strict";

  var _ = require("underscore");
  var fs = require('fs');

  var starttime = (new Date()).getTime();
  var processed = 0;
  var tokens;
  var input;
  var output;
  var done;
  var timer;

  /**
   * Main task kick-off functionality
   *
   * @for grunt-combine
   * @method registerMultiTask
   */
  grunt.registerMultiTask('combine', 'Combine files with token based search and replace functionality.', function() {

    // set out defaults
    done = this.async();
    input = this.data.input;
    output = this.data.output;
    tokens = this.data.tokens;

    // check to make sure that we have everything that we need before continuing
    if(_.isUndefined(input) || _.isUndefined(output)) {
      grunt.fail.warn('You must specify an input/output.');
    }

    // load the input file as text
    fs.readFile(input, 'utf8', function(e, data) {

      if(e) {
        grunt.fail.warn('There was an error processing the input file.');
      }

      // run through each of the replacements and load the files if needed. Replace the
      // replacement with the files contents if it happens to be a file
      grunt.log.writeln('Processing Input: ' + (input).cyan);
      input = data;

      // now process all of out replacements
      processed = 0;
      processTokens(tokens);

    });

    // complete the task
    timer = setTimeout(function() {
      grunt.fail.warn('The task has timed out.');
    }, 10000);

  });

  /**
   * Processes all of the passed replacements
   *
   * @for grunt-combine
   * @method processReplacements
   */
  var processTokens = function(){

    _.each(tokens, function(token,index) {

        // determain whether or not this is a file reference or a string
        if(token.file) {

          // read the file and reset replacement to what was loaded
          fs.readFile(token.file, 'utf8', function(e, data) {
            if(e) {
              grunt.fail.warn("There was an error processing the replacement '" + token.file + "' file.");
            }
            tokens[index].contents = data;
            processCompleteCallback();
          });

        } else if (token.string) {
          // we didn't need to load a file
          tokens[index].contents = token.string;
          processCompleteCallback();
        } else {
          processCompleteCallback();
        }

      }, this);
  };

  /**
   * Process completion callback. When all replacements have been processed the actual
   * combining of files takes place.
   *
   * @for grunt-combine
   * @method processCompleteCallback
   */
  var processCompleteCallback = function(){
    processed++;
    if(processed === tokens.length) {
      findAndReplaceTokens();
    }
  };

  /**
   * Looks for the specified token and replaces it with the next replacement
   * in the replacements array.
   *
   * @for grunt-combine
   * @method findAndReplaceTokens
   */
  var findAndReplaceTokens = function(){

    // run through the document and replace anything we can in the input string
    _.each(tokens,function(token,index){
      if(token.contents !== undefined ){
        var position = input.search(token.token);
        var pre = input.substr(0, position);
        var post = input.substr(position + token.token.length, input.length);
        input = pre + token.contents + post;
      } else {
          grunt.log.writeln("Replacement failed for token '" + token.token + "'.");
      }
    });

    writeOutput();
  };

  /**
   * Writes the processed input file to the specified output name.
   *
   * @for grunt-combine
   * @method findAndReplaceTokens
   */
  var writeOutput = function(){
    // write the input string to the output file name
    grunt.log.writeln('Writing Output: ' + (output).cyan);
    fs.writeFile(output, input, 'utf8', function (err) {
      if (err) {
        clearTimeout(timer);
        grunt.fail.warn("Could not write output '" + output + "' file.");
      }
      var endtime = (new Date()).getTime();
      grunt.log.writeln('Combine task completed in ' + ((endtime - starttime) / 1000) + ' seconds');
      clearTimeout(timer);
      done();
    });
  };

};
<commit_msg>Enables multiple files to be combined simultaneously for the same tokens<commit_after>/*
 * grunt-combine
 * https://github.com/mcgaryes/grunt-combine
 * https://github.com/gruntjs/grunt/
 *
 * Copyright (c) 2013 Eric McGary
 * Licensed under the MIT license.
 *
 * @main grunt-combine
 */
module.exports = function (grunt) {

    "use strict";

    var _ = require("underscore");
    var fs = require('fs');

    var starttime = (new Date()).getTime();
    var processedFiles = 0;
    var processed = 0;
    var tokens;
    var input = [];
    var fileContents = [];
    var output;
    var done;
    var timer;
    var cwd;

    /**
     * Main task kick-off functionality
     *
     * @for grunt-combine
     * @method registerMultiTask
     */
    grunt.registerMultiTask('combine', 'Combine files with token based search and replace functionality.', function () {

        // set out defaults
        done = this.async();
        cwd = this.data.cwd;
        input = this.data.input;
        output = this.data.output;
        tokens = this.data.tokens;

        // load the input file as text
        _.each(input, function (elem, index) {
            // check to make sure that we have everything that we need before continuing
            if (_.isUndefined(elem)) {
                grunt.fail.warn('You must specify an input/output.');
            }

            var path = cwd + elem;

            fs.readFile(path, 'utf8', function (e, data) {
                if (e) {
                    grunt.fail.warn('There was an error processing the input file.');
                }

                // run through each of the replacements and load the files if needed. Replace the
                // replacement with the files contents if it happens to be a file
                fileContents[index] = data;

                // now process all of out replacements
                processed = 0;
                processTokens(index);
            });
        });

        // complete the task
        timer = setTimeout(function () {
            grunt.fail.warn('The task has timed out.');
        }, 10000);

        /**
         * Processes all of the passed replacements
         *
         * @for grunt-combine
         * @method processReplacements
         */
        var processTokens = function (inputIndex) {

            _.each(tokens, function (token, index) {

                // determain whether or not this is a file reference or a string
                if (token.file) {

                    // read the file and reset replacement to what was loaded
                    fs.readFile(token.file, 'utf8', function (e, data) {
                        if (e) {
                            grunt.fail.warn("There was an error processing the replacement '" + token.file + "' file.");
                        }
                        tokens[index].contents = data;
                        processCompleteCallback(inputIndex);
                    });

                } else if (token.string) {
                    // we didn't need to load a file
                    tokens[index].contents = token.string;
                    processCompleteCallback(inputIndex);
                } else {
                    processCompleteCallback(inputIndex);
                }

            }, this);
        };

        /**
         * Process completion callback. When all replacements have been processed the actual
         * combining of files takes place.
         *
         * @for grunt-combine
         * @method processCompleteCallback
         */
        var processCompleteCallback = function (inputIndex) {
            processed++;
            if (processed === tokens.length) {
                findAndReplaceTokens(inputIndex);
            }
        };

        /**
         * Looks for the specified token and replaces it with the next replacement
         * in the replacements array.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var findAndReplaceTokens = function (inputIndex) {

            // run through the document and replace anything we can in the input string
            _.each(tokens, function (token) {
                if (token.contents !== undefined) {
                    var position = fileContents[inputIndex].search(token.token);
                    var pre = fileContents[inputIndex].substr(0, position);
                    var post = fileContents[inputIndex].substr(position + token.token.length, fileContents[inputIndex].length);
                    fileContents[inputIndex] = pre + token.contents + post;
                } else {
                    grunt.log.writeln("Replacement failed for token '" + token.token + "'.");
                }
            });

            writeOutput(inputIndex);
        };

        /**
         * Writes the processed input file to the specified output name.
         *
         * @for grunt-combine
         * @method findAndReplaceTokens
         */
        var writeOutput = function (inputIndex) {
            var path = output + input[inputIndex];
            // write the input string to the output file name
            grunt.log.writeln('Writing Output: ' + (path).cyan);
            fs.writeFile(path, fileContents[inputIndex], 'utf8', function (err) {
                if (err) {
                    clearTimeout(timer);
                    grunt.fail.warn("Could not write output '" + output + "' file.");
                }
                var endtime = (new Date()).getTime();
                clearTimeout(timer);
                processedFiles++;
                if (processedFiles === fileContents.length) {
                    done();
                }
            });
        };
    });
};
<|endoftext|>


<commit_before>/*
 * grunt-html2js
 * https://github.com/karlgoldstein/grunt-html2js
 *
 * Copyright (c) 2013 Karl Goldstein
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  var path = require('path');
  var minify = require('html-minifier').minify;

  var escapeContent = function(content, quoteChar, indentString) {
    var bsRegexp = new RegExp('\\\\', 'g');
    var quoteRegexp = new RegExp('\\' + quoteChar, 'g');
    var nlReplace = '\\n' + quoteChar + ' +\n' + indentString + indentString + quoteChar;
    return content.replace(bsRegexp, '\\\\').replace(quoteRegexp, '\\' + quoteChar).replace(/\r?\n/g, nlReplace);
  };

  // convert Windows file separator URL path separator
  var normalizePath = function(p) {
    if ( path.sep !== '/' ) {
      p = p.replace(/\\/g, '/');
    }
    return p;
  };

  // Warn on and remove invalid source files (if nonull was set).
  var existsFilter = function(filepath) {

    if (!grunt.file.exists(filepath)) {
      grunt.log.warn('Source file "' + filepath + '" not found.');
      return false;
    } else {
      return true;
    }
  };

  // return template content
  var getContent = function(filepath, quoteChar, indentString, htmlmin, process) {
    var content = grunt.file.read(filepath);

    // Process files as templates if requested.
    if (typeof process === "function") {
      content = process(content, filepath);
    } else if (process) {
      if (process === true) {
        process = {};
      }
      content = grunt.template.process(content, process);
    }

    if (Object.keys(htmlmin).length) {
      try {
        content = minify(content, htmlmin);
      } catch (err) {
        grunt.warn(filepath + '\n' + err);
      }
    }

    return escapeContent(content, quoteChar, indentString);
  };

  // compile a template to an angular module
  var compileTemplate = function(moduleName, filepath, quoteChar, indentString, useStrict, htmlmin, process) {

    var content = getContent(filepath, quoteChar, indentString, htmlmin, process);
    var doubleIndent = indentString + indentString;
    var strict = (useStrict) ? indentString + quoteChar + 'use strict' + quoteChar + ';\n' : '';

    var module = 'angular.module(' + quoteChar + moduleName +
      quoteChar + ', []).run([' + quoteChar + '$templateCache' + quoteChar + ', function($templateCache) ' +
      '{\n' + strict + indentString + '$templateCache.put(' + quoteChar + moduleName + quoteChar + ',\n' + doubleIndent  + quoteChar +  content +
       quoteChar + ');\n}]);\n';

    return module;
  };

  // compile a template to an angular module
  var compileCoffeeTemplate = function(moduleName, filepath, quoteChar, indentString, htmlmin, process) {
    var content = getContent(filepath, quoteChar, indentString, htmlmin, process);
    var doubleIndent = indentString + indentString;

    var module = 'angular.module(' + quoteChar + moduleName +
      quoteChar + ', []).run([' + quoteChar + '$templateCache' + quoteChar + ', ($templateCache) ->\n' +
      indentString + '$templateCache.put(' + quoteChar + moduleName + quoteChar + ',\n' + doubleIndent  + quoteChar +  content +
      quoteChar + ')\n])\n';

    return module;
  };

  grunt.registerMultiTask('html2js', 'Compiles Angular-JS templates to JavaScript.', function() {

    var options = this.options({
      base: 'src',
      module: 'templates-' + this.target,
      quoteChar: '"',
      fileHeaderString: '',
      fileFooterString: '',
      indentString: '  ',
      target: 'js',
      htmlmin: {},
      process: false
    });

    var counter = 0;

    // generate a separate module
    this.files.forEach(function(f) {

      // f.dest must be a string or write will fail

      var moduleNames = [];

      var modules = f.src.filter(existsFilter).map(function(filepath) {

        var moduleName = normalizePath(path.relative(options.base, filepath));
        if (grunt.util.kindOf(options.rename) === 'function') {
          moduleName = options.rename(moduleName);
        }
        moduleNames.push("'" + moduleName + "'");
        if (options.target === 'js') {
          return compileTemplate(moduleName, filepath, options.quoteChar, options.indentString, options.useStrict, options.htmlmin, options.process);
        } else if (options.target === 'coffee') {
          return compileCoffeeTemplate(moduleName, filepath, options.quoteChar, options.indentString, options.htmlmin, options.process);
        } else {
          grunt.fail.fatal('Unknow target "' + options.target + '" specified');
        }

      });

      counter += modules.length;
      modules  = modules.join('\n');

      var fileHeader = options.fileHeaderString !== '' ? options.fileHeaderString + '\n' : '';
      var fileFooter = options.fileFooterString !== '' ? options.fileFooterString + '\n' : '';
      var bundle = "";
      var targetModule = f.module || options.module;
      // If options.module is a function, use that to get the targetModule
      if (grunt.util.kindOf(targetModule) === 'function') {
	targetModule = targetModule(f);
      }
      //Allow a 'no targetModule if module is null' option
      if (targetModule) {
        bundle = "angular.module('" + targetModule + "', [" + moduleNames.join(', ') + "])";
        if (options.target === 'js') {
          bundle += ';';
        }

        bundle += "\n\n";
      }
      grunt.file.write(f.dest, grunt.util.normalizelf(fileHeader + bundle + modules + fileFooter));
    });
    //Just have one output, so if we making thirty files it only does one line
    grunt.log.writeln("Successfully converted "+(""+counter).green +
                      " html templates to " + options.target + ".");
  });
};
<commit_msg>Trim content<commit_after>/*
 * grunt-html2js
 * https://github.com/karlgoldstein/grunt-html2js
 *
 * Copyright (c) 2013 Karl Goldstein
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  var path = require('path');
  var minify = require('html-minifier').minify;

  var escapeContent = function(content, quoteChar, indentString) {
    var bsRegexp = new RegExp('\\\\', 'g');
    var quoteRegexp = new RegExp('\\' + quoteChar, 'g');
    var nlReplace = '\\n' + quoteChar + ' +\n' + indentString + indentString + quoteChar;
    return content.replace(bsRegexp, '\\\\').replace(quoteRegexp, '\\' + quoteChar).replace(/\r?\n/g, nlReplace);
  };

  // convert Windows file separator URL path separator
  var normalizePath = function(p) {
    if ( path.sep !== '/' ) {
      p = p.replace(/\\/g, '/');
    }
    return p;
  };

  // Warn on and remove invalid source files (if nonull was set).
  var existsFilter = function(filepath) {

    if (!grunt.file.exists(filepath)) {
      grunt.log.warn('Source file "' + filepath + '" not found.');
      return false;
    } else {
      return true;
    }
  };

  // return template content
  var getContent = function(filepath, quoteChar, indentString, htmlmin, process) {
    var content = grunt.file.read(filepath);

    // Process files as templates if requested.
    if (typeof process === "function") {
      content = process(content, filepath);
    } else if (process) {
      if (process === true) {
        process = {};
      }
      content = grunt.template.process(content, process);
    }

    if (Object.keys(htmlmin).length) {
      try {
        content = minify(content, htmlmin);
      } catch (err) {
        grunt.warn(filepath + '\n' + err);
      }
    }

    content = content.trim();

    return escapeContent(content, quoteChar, indentString);
  };

  // compile a template to an angular module
  var compileTemplate = function(moduleName, filepath, quoteChar, indentString, useStrict, htmlmin, process) {

    var content = getContent(filepath, quoteChar, indentString, htmlmin, process);
    var doubleIndent = indentString + indentString;
    var strict = (useStrict) ? indentString + quoteChar + 'use strict' + quoteChar + ';\n' : '';

    var module = 'angular.module(' + quoteChar + moduleName +
      quoteChar + ', []).run([' + quoteChar + '$templateCache' + quoteChar + ', function($templateCache) ' +
      '{\n' + strict + indentString + '$templateCache.put(' + quoteChar + moduleName + quoteChar + ',\n' + doubleIndent  + quoteChar +  content +
       quoteChar + ');\n}]);\n';

    return module;
  };

  // compile a template to an angular module
  var compileCoffeeTemplate = function(moduleName, filepath, quoteChar, indentString, htmlmin, process) {
    var content = getContent(filepath, quoteChar, indentString, htmlmin, process);
    var doubleIndent = indentString + indentString;

    var module = 'angular.module(' + quoteChar + moduleName +
      quoteChar + ', []).run([' + quoteChar + '$templateCache' + quoteChar + ', ($templateCache) ->\n' +
      indentString + '$templateCache.put(' + quoteChar + moduleName + quoteChar + ',\n' + doubleIndent  + quoteChar +  content +
      quoteChar + ')\n])\n';

    return module;
  };

  grunt.registerMultiTask('html2js', 'Compiles Angular-JS templates to JavaScript.', function() {

    var options = this.options({
      base: 'src',
      module: 'templates-' + this.target,
      quoteChar: '"',
      fileHeaderString: '',
      fileFooterString: '',
      indentString: '  ',
      target: 'js',
      htmlmin: {},
      process: false
    });

    var counter = 0;

    // generate a separate module
    this.files.forEach(function(f) {

      // f.dest must be a string or write will fail

      var moduleNames = [];

      var modules = f.src.filter(existsFilter).map(function(filepath) {

        var moduleName = normalizePath(path.relative(options.base, filepath));
        if (grunt.util.kindOf(options.rename) === 'function') {
          moduleName = options.rename(moduleName);
        }
        moduleNames.push("'" + moduleName + "'");
        if (options.target === 'js') {
          return compileTemplate(moduleName, filepath, options.quoteChar, options.indentString, options.useStrict, options.htmlmin, options.process);
        } else if (options.target === 'coffee') {
          return compileCoffeeTemplate(moduleName, filepath, options.quoteChar, options.indentString, options.htmlmin, options.process);
        } else {
          grunt.fail.fatal('Unknow target "' + options.target + '" specified');
        }

      });

      counter += modules.length;
      modules  = modules.join('\n');

      var fileHeader = options.fileHeaderString !== '' ? options.fileHeaderString + '\n' : '';
      var fileFooter = options.fileFooterString !== '' ? options.fileFooterString + '\n' : '';
      var bundle = "";
      var targetModule = f.module || options.module;
      // If options.module is a function, use that to get the targetModule
      if (grunt.util.kindOf(targetModule) === 'function') {
	targetModule = targetModule(f);
      }
      //Allow a 'no targetModule if module is null' option
      if (targetModule) {
        bundle = "angular.module('" + targetModule + "', [" + moduleNames.join(', ') + "])";
        if (options.target === 'js') {
          bundle += ';';
        }

        bundle += "\n\n";
      }
      grunt.file.write(f.dest, grunt.util.normalizelf(fileHeader + bundle + modules + fileFooter));
    });
    //Just have one output, so if we making thirty files it only does one line
    grunt.log.writeln("Successfully converted "+(""+counter).green +
                      " html templates to " + options.target + ".");
  });
};
<|endoftext|>


<commit_before>/*
 * grunt-htmlint
 * https://github.com/nikestep/grunt-htmlint
 *
 * Copyright (c) 2014 Nik Estep
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

    var w3cjs = require('w3cjs');
    var colors = require('colors');

    colors.setTheme({
        silly: 'rainbow',
        input: 'grey',
        verbose: 'cyan',
        prompt: 'grey',
        info: 'green',
        data: 'grey',
        help: 'cyan',
        warn: 'yellow',
        debug: 'blue',
        error: 'red',
        blue: 'blue'
    });

    grunt.registerMultiTask('htmlint', 'An HTML5 linter aimed at AngularJS projects.', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            angular: true,
            customtags: [],
            customattrs: [],
            relaxerror: [],
            doctype: 'HTML5',
            charset: 'utf-8'
        });

        // Force task into async mode and grab a handle to the "done" function.
        var done = this.async();

        // Set up the linked list for processing
        var count = 0,
            list = {
                head: null,
                tail: null
            },
            succeedCount = 0;

        // Iterate over all specified file groups.
        this.files.forEach(function(f) {
            // Build the list of files to validate
            f.src.filter(function(filepath) {
                if (!grunt.file.exists(filepath)) {
                    // Warn that the file cannot be found
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    // Add the file to the list
                    count += 1;
                    if (list.head === null) {
                        list.head = {
                            path: filepath,
                            next: null
                        };
                        list.tail = list.head;
                    }
                    else {
                        list.tail.next = {
                            path: filepath,
                            next: null
                        };
                        list.tail = list.tail.next;
                    }
                    return true;
                }
            });
        });

        // Check that we got files
        if (count === 0) {
            grunt.log.warn('No source files were found');
            done();
            return;
        }

        var validate = function(file) {
            var results = w3cjs.validate({
                file: file.path, // file can either be a local file or a remote file
                output: 'json', // Defaults to 'json', other option includes html
                doctype: 'HTML5', // Defaults false for autodetect
                charset: 'utf-8', // Defaults false for autodetect
                callback: function (res) {
                    // Handle results
                    if (res.messages.length === 0) {
                        succeedCount += 1;
                    } else {
                        grunt.log.writeln('Linting ' +
                                          file.path +
                                          ' ...' +
                                          'ERROR'.red);
                        for (var i = 0; i < res.messages.length; i += 1) {
                            if (res.messages[i].message === '(Suppressing further errors from this subtree.)') {
                                grunt.log.errorlns('Supressing further errors');
                            } else {
                                grunt.log.writeln('['.red +
                                                  'L'.yellow +
                                                  ('' + res.messages[i].lastLine).yellow +
                                                  ':'.red +
                                                  'C'.yellow +
                                                  ('' + res.messages[i].lastColumn).yellow +
                                                  '] '.red +
                                                  res.messages[i].message.yellow);
                            }
                        }
                    }

                    // Move on to next file or finish
                    if (file.next === null) {
                        if (succeedCount === count) {
                            grunt.log.oklns(succeedCount + ' files lint free');
                            done();
                        }
                        else {
                            grunt.fail.warn('HTML validation failed');
                            done(false);
                        }
                    } else {
                        validate(file.next);
                    }
                    // depending on the output type, res will either be a json object or a html string
                }
            });
        };

        // Start the validation
        validate(list.head);
    });
};<commit_msg>Applying custom options to W3C validator<commit_after>/*
 * grunt-htmlint
 * https://github.com/nikestep/grunt-htmlint
 *
 * Copyright (c) 2014 Nik Estep
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

    var w3cjs = require('w3cjs');
    var colors = require('colors');

    colors.setTheme({
        silly: 'rainbow',
        input: 'grey',
        verbose: 'cyan',
        prompt: 'grey',
        info: 'green',
        data: 'grey',
        help: 'cyan',
        warn: 'yellow',
        debug: 'blue',
        error: 'red',
        blue: 'blue'
    });

    grunt.registerMultiTask('htmlint', 'An HTML5 linter aimed at AngularJS projects.', function() {
        // Merge task-specific and/or target-specific options with these defaults.
        var options = this.options({
            angular: true,
            customtags: [],
            customattrs: [],
            relaxerror: [],
            doctype: 'HTML5',
            charset: 'utf-8'
        });

        // Force task into async mode and grab a handle to the "done" function.
        var done = this.async();

        // Set up the linked list for processing
        var count = 0,
            list = {
                head: null,
                tail: null
            },
            succeedCount = 0;

        // Iterate over all specified file groups.
        this.files.forEach(function(f) {
            // Build the list of files to validate
            f.src.filter(function(filepath) {
                if (!grunt.file.exists(filepath)) {
                    // Warn that the file cannot be found
                    grunt.log.warn('Source file "' + filepath + '" not found.');
                    return false;
                } else {
                    // Add the file to the list
                    count += 1;
                    if (list.head === null) {
                        list.head = {
                            path: filepath,
                            next: null
                        };
                        list.tail = list.head;
                    }
                    else {
                        list.tail.next = {
                            path: filepath,
                            next: null
                        };
                        list.tail = list.tail.next;
                    }
                    return true;
                }
            });
        });

        // Check that we got files
        if (count === 0) {
            grunt.log.warn('No source files were found');
            done();
            return;
        }

        var validate = function(file) {
            var results = w3cjs.validate({
                file: file.path,
                output: 'json',
                doctype: options.doctype,
                charset: options.charset,
                callback: function (res) {
                    // Handle results
                    if (res.messages.length === 0) {
                        succeedCount += 1;
                    } else {
                        grunt.log.writeln('Linting ' +
                                          file.path +
                                          ' ...' +
                                          'ERROR'.red);
                        for (var i = 0; i < res.messages.length; i += 1) {
                            if (res.messages[i].message === '(Suppressing further errors from this subtree.)') {
                                grunt.log.errorlns('Supressing further errors');
                            } else {
                                grunt.log.writeln('['.red +
                                                  'L'.yellow +
                                                  ('' + res.messages[i].lastLine).yellow +
                                                  ':'.red +
                                                  'C'.yellow +
                                                  ('' + res.messages[i].lastColumn).yellow +
                                                  '] '.red +
                                                  res.messages[i].message.yellow);
                            }
                        }
                    }

                    // Move on to next file or finish
                    if (file.next === null) {
                        if (succeedCount === count) {
                            grunt.log.oklns(succeedCount + ' files lint free');
                            done();
                        }
                        else {
                            grunt.fail.warn('HTML validation failed');
                            done(false);
                        }
                    } else {
                        validate(file.next);
                    }
                    // depending on the output type, res will either be a json object or a html string
                }
            });
        };

        // Start the validation
        validate(list.head);
    });
};<|endoftext|>


<commit_before>/*
 * grunt-contrib-jasmine
 * http://gruntjs.com/
 *
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // node api
  var fs   = require('fs'),
    path = require('path');

  // npm lib
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // local lib
  var jasmine = require('./lib/jasmine').init(grunt, phantomjs);

  var junitTemplate = __dirname + '/jasmine/templates/JUnit.tmpl';

  var status = {
    specs    : 0,
    failed   : 0,
    passed   : 0,
    total    : 0,
    skipped  : 0,
    duration : 0
  };

  grunt.registerMultiTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {

    // Merge task-specific options with these defaults.
    var options = this.options({
      timeout : 10000,
      specs   : [],
      helpers : [],
      vendor  : [],
      outfile : '_SpecRunner.html',
      host    : '',
      template : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
      templateOptions : {},
      phantomjs : {},
      junit: {}
    });

    if (options.template === 'requirejs') {
      grunt.log.warn(
        'The requirejs template is no longer included in grunt-contrib-jasmine core.\n' +
        'Please see the https://github.com/gruntjs/grunt-contrib-jasmine README for details'
      );
    }

    if (grunt.option('debug')) {
      grunt.log.debug(options);
    }

    setup(options);

    jasmine.buildSpecrunner(this.filesSrc,options);

    // If we're just building (e.g. for web), skip phantom.
    if (this.flags.build) return;

    var done = this.async();
    phantomRunner(options, function(err,status) {
      if (err) grunt.log.error(err);
      if (status.failed === 0) grunt.log.ok('0 failures');
      else grunt.log.error(status.failed + ' failures');
      teardown(options);
      done(!err && status.failed === 0);
    });

  });

  function phantomRunner(options,cb){
    var file = options.outfile;

    if (options.host) {
      file = options.host + options.outfile;
    }

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');

    phantomjs.spawn(file, {
      failCode : 90,
      options  : options,
      done     : function(err){
        cb(err,status);
      }
    });
  }

  function teardown(options) {
    if (fs.statSync(options.outfile).isFile()) fs.unlink(options.outfile);
    jasmine.cleanTemp();

    // Have to explicitly unregister nested wildcards. Need to file a bug for EventEmitter2
    phantomjs.removeAllListeners('*');
    phantomjs.removeAllListeners('jasmine.*');
    phantomjs.removeAllListeners('error.*');
    phantomjs.removeAllListeners('jasmine.done.*');
  }

  function setup(options) {
    var thisRun = {};

    phantomjs.on('fail.timeout',function(){
      grunt.log.writeln();
      grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
    });

    phantomjs.on('console',console.log.bind(console));
    phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
    phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
    phantomjs.on('write', grunt.log.write.bind(grunt.log));
    phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
    phantomjs.on('error.onError',function(string, trace){
      if (trace) {
        grunt.log.error(string.red + ' at ');
        trace.forEach(function(line) {
          var file = line.file.replace(/^file:/,'');
          var message = grunt.util._('%s:%d %s').sprintf(path.relative('.',file), line.line, line.function);
          grunt.log.error(message.red);
        });
      } else {
        grunt.log.error(string.red);
      }
    });

    phantomjs.onAny(function() {
      var args = [this.event].concat(grunt.util.toArray(arguments));
      grunt.event.emit.apply(grunt.event, args);
    });

    phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
      grunt.verbose.writeln('Starting...');
      thisRun.start_time = (new Date()).getTime();
      thisRun.executed_specs = 0;
      thisRun.passed_specs = 0;
    });

    phantomjs.on('jasmine.reportSpecStarting',function(spec) {
      thisRun.executed_specs++;
      grunt.verbose.write(spec.suite.description + ':' + spec.description + '...');
    });

    phantomjs.on('jasmine.reportSuiteResults',function(suite){
      //grunt.verbose.writeln(suite.description + ": " + suite.results.passedCount + " of " + suite.results.totalCount + " passed.");
    });

    phantomjs.on('jasmine.reportSpecResults',function(specId, result,summary) {
      if (result.passed) thisRun.passed_specs++;

      grunt.verbose.writeln(summary.passed ? result.msg.green : result.msg.red);
      for (var i = 0; i < result.messages.length; i++) {
        var item = result.messages[i];

        if (item.type === 'log') {
          grunt.verbose.writeln(item.toString());
        } else if (item.type === 'expect' && !item.passed_) {
          grunt.log.writeln(summary.description + ':' + result.msg.red);
          phantomjs.emit('onError', item.message, item.trace);
        }
      }
      phantomjs.emit( 'jasmine.testDone', result.totalCount, result.passedCount, result.failedCount, result.skipped );

    });

    phantomjs.on('jasmine.reportRunnerResults',function(){
      grunt.verbose.writeln('Runner finished');
      var dur = (new Date()).getTime() - thisRun.start_time;
      var failed = thisRun.executed_specs - thisRun.passed_specs;
      var spec_str = thisRun.executed_specs + (thisRun.executed_specs === 1 ? " spec, " : " specs, ");
      var fail_str = failed + (failed === 1 ? " failure in " : " failures in ");
      grunt.log.writeln(spec_str + fail_str + (dur/1000) + "s.");
    });

    phantomjs.on('jasmine.testDone',function(totalAssertions, passedAssertions, failedAssertions, skippedAssertions){
      status.specs++;
      status.failed  += failedAssertions;
      status.passed  += passedAssertions;
      status.total   += totalAssertions;
      status.skipped += skippedAssertions;
    });

    phantomjs.on('jasmine.reportJUnitResults',function(junitData){
      if (options.junit && options.junit.path) {
        var template = grunt.file.read(junitTemplate);
        if (options.junit.consolidate) {
          grunt.util._(junitData.consolidatedSuites).each(function(suites){
            var xmlFile = path.join(options.junit.path, 'TEST-' + suites[0].name.replace(/[^\w]/g, '') + '.xml');
            grunt.file.write(xmlFile, grunt.util._.template(template, { testsuites: suites}));
          });
        } else {
          junitData.suites.forEach(function(suiteData){
            var xmlFile = path.join(options.junit.path, 'TEST-' + suiteData.name.replace(/[^\w]/g, '') + '.xml');
            grunt.file.write(xmlFile, grunt.util._.template(template, { testsuites: [suiteData] }));
          });
        }
      }
    });

    phantomjs.on('jasmine.done',function(elapsed){
      phantomjs.halt();
      status.duration = elapsed;
    });

    phantomjs.on('jasmine.done.PhantomReporter',function(){
      phantomjs.emit('jasmine.done');
    });

    phantomjs.on('jasmine.done_fail',function(url){
      grunt.log.error();
      grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90);
    });
  }

};<commit_msg>From the end result I removed the failure spec count, because task return value also displayed that information.<commit_after>/*
 * grunt-contrib-jasmine
 * http://gruntjs.com/
 *
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {

  // node api
  var fs   = require('fs'),
    path = require('path');

  // npm lib
  var phantomjs = require('grunt-lib-phantomjs').init(grunt);

  // local lib
  var jasmine = require('./lib/jasmine').init(grunt, phantomjs);

  var junitTemplate = __dirname + '/jasmine/templates/JUnit.tmpl';

  var status = {
    specs    : 0,
    failed   : 0,
    passed   : 0,
    total    : 0,
    skipped  : 0,
    duration : 0
  };

  grunt.registerMultiTask('jasmine', 'Run jasmine specs headlessly through PhantomJS.', function() {

    // Merge task-specific options with these defaults.
    var options = this.options({
      timeout : 10000,
      specs   : [],
      helpers : [],
      vendor  : [],
      outfile : '_SpecRunner.html',
      host    : '',
      template : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
      templateOptions : {},
      phantomjs : {},
      junit: {}
    });

    if (options.template === 'requirejs') {
      grunt.log.warn(
        'The requirejs template is no longer included in grunt-contrib-jasmine core.\n' +
        'Please see the https://github.com/gruntjs/grunt-contrib-jasmine README for details'
      );
    }

    if (grunt.option('debug')) {
      grunt.log.debug(options);
    }

    setup(options);

    jasmine.buildSpecrunner(this.filesSrc,options);

    // If we're just building (e.g. for web), skip phantom.
    if (this.flags.build) return;

    var done = this.async();
    phantomRunner(options, function(err,status) {
      if (err) grunt.log.error(err);
      if (status.failed === 0) grunt.log.ok('0 failures');
      else grunt.log.error(status.failed + ' failures');
      teardown(options);
      done(!err && status.failed === 0);
    });

  });

  function phantomRunner(options,cb){
    var file = options.outfile;

    if (options.host) {
      file = options.host + options.outfile;
    }

    grunt.verbose.subhead('Testing jasmine specs via phantom').or.writeln('Testing jasmine specs via phantom');

    phantomjs.spawn(file, {
      failCode : 90,
      options  : options,
      done     : function(err){
        cb(err,status);
      }
    });
  }

  function teardown(options) {
    if (fs.statSync(options.outfile).isFile()) fs.unlink(options.outfile);
    jasmine.cleanTemp();

    // Have to explicitly unregister nested wildcards. Need to file a bug for EventEmitter2
    phantomjs.removeAllListeners('*');
    phantomjs.removeAllListeners('jasmine.*');
    phantomjs.removeAllListeners('error.*');
    phantomjs.removeAllListeners('jasmine.done.*');
  }

  function setup(options) {
    var thisRun = {};

    phantomjs.on('fail.timeout',function(){
      grunt.log.writeln();
      grunt.warn('PhantomJS timed out, possibly due to an unfinished async spec.', 90);
    });

    phantomjs.on('console',console.log.bind(console));
    phantomjs.on('verbose',grunt.verbose.writeln.bind(grunt.verbose));
    phantomjs.on('debug', grunt.log.debug.bind(grunt.log, 'phantomjs'));
    phantomjs.on('write', grunt.log.write.bind(grunt.log));
    phantomjs.on('writeln', grunt.log.writeln.bind(grunt.log));
    phantomjs.on('error.onError',function(string, trace){
      if (trace) {
        grunt.log.error(string.red + ' at ');
        trace.forEach(function(line) {
          var file = line.file.replace(/^file:/,'');
          var message = grunt.util._('%s:%d %s').sprintf(path.relative('.',file), line.line, line.function);
          grunt.log.error(message.red);
        });
      } else {
        grunt.log.error(string.red);
      }
    });

    phantomjs.onAny(function() {
      var args = [this.event].concat(grunt.util.toArray(arguments));
      grunt.event.emit.apply(grunt.event, args);
    });

    phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
      grunt.verbose.writeln('Starting...');
      thisRun.start_time = (new Date()).getTime();
      thisRun.executed_specs = 0;
      thisRun.passed_specs = 0;
    });

    phantomjs.on('jasmine.reportSpecStarting',function(spec) {
      thisRun.executed_specs++;
      grunt.verbose.write(spec.suite.description + ':' + spec.description + '...');
    });

    phantomjs.on('jasmine.reportSuiteResults',function(suite){
      //grunt.verbose.writeln(suite.description + ": " + suite.results.passedCount + " of " + suite.results.totalCount + " passed.");
    });

    phantomjs.on('jasmine.reportSpecResults',function(specId, result,summary) {
      if (result.passed) thisRun.passed_specs++;

      grunt.verbose.writeln(summary.passed ? result.msg.green : result.msg.red);
      for (var i = 0; i < result.messages.length; i++) {
        var item = result.messages[i];

        if (item.type === 'log') {
          grunt.verbose.writeln(item.toString());
        } else if (item.type === 'expect' && !item.passed_) {
          grunt.log.writeln(summary.description + ':' + result.msg.red);
          phantomjs.emit('onError', item.message, item.trace);
        }
      }
      phantomjs.emit( 'jasmine.testDone', result.totalCount, result.passedCount, result.failedCount, result.skipped );

    });

    phantomjs.on('jasmine.reportRunnerResults',function(){
      grunt.verbose.writeln('Runner finished');
      var dur = (new Date()).getTime() - thisRun.start_time;
      var spec_str = thisRun.executed_specs + (thisRun.executed_specs === 1 ? " spec " : " specs ");
      grunt.log.writeln(spec_str + 'in ' + (dur/1000) + "s.");
    });

    phantomjs.on('jasmine.testDone',function(totalAssertions, passedAssertions, failedAssertions, skippedAssertions){
      status.specs++;
      status.failed  += failedAssertions;
      status.passed  += passedAssertions;
      status.total   += totalAssertions;
      status.skipped += skippedAssertions;
    });

    phantomjs.on('jasmine.reportJUnitResults',function(junitData){
      if (options.junit && options.junit.path) {
        var template = grunt.file.read(junitTemplate);
        if (options.junit.consolidate) {
          grunt.util._(junitData.consolidatedSuites).each(function(suites){
            var xmlFile = path.join(options.junit.path, 'TEST-' + suites[0].name.replace(/[^\w]/g, '') + '.xml');
            grunt.file.write(xmlFile, grunt.util._.template(template, { testsuites: suites}));
          });
        } else {
          junitData.suites.forEach(function(suiteData){
            var xmlFile = path.join(options.junit.path, 'TEST-' + suiteData.name.replace(/[^\w]/g, '') + '.xml');
            grunt.file.write(xmlFile, grunt.util._.template(template, { testsuites: [suiteData] }));
          });
        }
      }
    });

    phantomjs.on('jasmine.done',function(elapsed){
      phantomjs.halt();
      status.duration = elapsed;
    });

    phantomjs.on('jasmine.done.PhantomReporter',function(){
      phantomjs.emit('jasmine.done');
    });

    phantomjs.on('jasmine.done_fail',function(url){
      grunt.log.error();
      grunt.warn('PhantomJS unable to load "' + url + '" URI.', 90);
    });
  }

};<|endoftext|>