<commit_before>var EZ_TIME_CONSTANT = 20.571428571428574,
    logicdata = new Array(24),
    last_hour = -1,
    data = undefined,
    eorzea_time = document.getElementById("eorzea_time").children[1],
    real_time = document.getElementById("real_time"),
    left = document.getElementById("left"),
    right = document.getElementById("right"),
    settingsRows = document.getElementById("rows"),
    settings = document.getElementById("settings"),
    blacken = document.getElementById("blacken"),
    currents = null,
    daily = null,
    weekly = null,
    leve = null,
    dtimer = document.getElementById("daily"),
    wtimer = document.getElementById("weekly"),
    ltimer = document.getElementById("leve"),
    sup = document.getElementById("eorzea_time").children[0],
    moonel = document.getElementById("eorzea_time").children[2];

var DateUTC = function(year, month, day, hour, minute, second) {
  var d = new Date();
  d.setFullYear(year);
  d.setUTCMonth(month);
  d.setUTCDate(day);
  d.setUTCHours(hour);
  d.setUTCMinutes(minute);
  d.setUTCSeconds(second);
  return d;
}, regenTimers = function() {
  currents = new Date();
  daily = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 15, 0, 0).getTime();
  if(currents.getTime() > daily) {
    daily = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + 1, 15, 0, 0).getTime();
  }

  var distance = currents.getUTCDay();
  distance -= 2;
  if(distance < 0) {
    distance = Math.abs(distance);
  }
  weekly = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + distance, 8, 0, 0).getTime();

  leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 0, 0, 0).getTime();
  if(currents.getTime() > leve) {
    leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 12, 0, 0).getTime();
    if(currents.getTime() > leve) {
      leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + 1, 0, 0, 0).getTime();
    }
  }
}, getEorzeaTime = function() {
  return Math.floor((Date.now() - 26127360000000) * EZ_TIME_CONSTANT);
}, formatTime = function(epoch, days, shmrd) {
  var date = new Date(epoch);
  var h = date.getUTCHours(), m = date.getUTCMinutes();
  var meridiem = "AM";
  if(h > 11 && !shmrd) {
    h -= 12;
    meridiem = "PM";
  }

  if(days && date.getUTCDate() > 1) {
    h += date.getUTCDate() * 24
  }

  var str = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2) + ":" + ("0" + date.getUTCSeconds()).substr(-2);

  if(!shmrd) {
    str += " " + meridiem;
  }
  return str;
}, remaining = function(futureHours) {
  return new Date(175 * futureHours * 1000).getTime() / 1000 / 60;
}, calculateHours = function(last, hour) {
  var timeDifference = 0;
  if(hour == last || hour == last + 1) {
    timeDifference = 1;
  } else {
    timeDifference = hour - last;
    if(timeDifference < 1) {
      timeDifference += 24;
    }
  }
  return timeDifference;
}, playSound = function(se) {
  var se = "/se/"+se+".mp3";
  var a = new Audio();
  a.addEventListener("canplay", function(){
    a.play();
  }, false);
  a.src = se;
  a.volume = 1;
}, tick = function() {
  var start = Date.now();
  var now = getEorzeaTime(),
      date = new Date(now),
      hour = date.getUTCHours();

  if(last_hour != hour) {
    data = sortByTime(hour);
    last_hour = hour;
    while(left.children.length) {
      left.removeChild(left.children[0]);
    }
    while(right.children.length) {
      right.removeChild(right.children[0]);
    }

    if(document.getElementById("seenabled"+hour) !== null && document.getElementById("seenabled"+hour).checked) {
      playSound(document.getElementById("se"+hour).value);
    }

    var ul = document.createElement("ul");
    for(var i = 0; i < 24; ++i) {
      var n = data[i];
      if(n === undefined) {
        continue;
      }
      var li = document.createElement("li");
      var hour = n.hour,
          meridiem = "AM";
      if(hour > 11) {
        hour -= 12;
        meridiem = "PM";
      }

      li.textContent = ("0" + hour).substr(-2) + ":00 " + meridiem;

      var timeDifference = calculateHours(last_hour, n.hour);
      var timeLeft = document.createElement("span");
      timeLeft.dataset.fh = timeDifference;
      var minuteDifference = 60 - date.getUTCMinutes();
      timeDifference -= (1 - (minuteDifference / 60));
      timeLeft.textContent = Math.floor(remaining(timeDifference));
      if(timeLeft.textContent == "0") {
        timeLeft.textContent = "LESS THAN 1";
      }
      timeLeft.className = "countdown";
      if(n.hour == last_hour) {
        timeLeft.className += " active";
      }
      li.dataset.fh = n.hour;
      li.appendChild(timeLeft);
      ul.appendChild(li);

      var n_ul = document.createElement("ul");
      n_ul.id = "nodes"+n.hour;
      for(var j = 0; j < n.nodes.length; ++j) {
        var node = n.nodes[j];
        var n_li = document.createElement("li");
        var c = document.createElement("span"),
            it = document.createElement("span"),
            s = document.createElement("span"),
            l = document.createElement("span");

        c.className = "class";
        it.className = "item";
        s.className = "slot";
        l.className = "location";

        n_li.className = c.textContent = node.class;
        it.textContent = node.item;
        if("location" in node) {
          l.textContent = node.location + " (" + node.coordinates[0] + ", " + node.coordinates[1] + ")";
        }

        if("slot" in node) {
          s.textContent = "Slot #"+node.slot;
        }

        n_li.appendChild(c);
        n_li.appendChild(it);
        n_li.appendChild(s);
        n_li.appendChild(l);

        n_ul.appendChild(n_li);
      }
      right.appendChild(n_ul);

      right.children[0].className = "show";
      li.addEventListener("mouseenter", function(event) {
        document.querySelector(".show").className = ""
        document.getElementById("nodes"+event.target.dataset.fh).className = "show";
        document.querySelector("li.active").className = "";
        event.target.className = "active";
      }, false);

    }
    left.appendChild(ul);
    left.children[0].children[0].className = "active";

    var ace = Aetheryte.getEorzeaTimeAce(),
        element = Aetheryte.getElement(ace),
        moon = "moon_"+["0", "-25", "-50", "-75", "100", "+75", "+50", "+25"][Aetheryte.getMoonPhase(ace).phase]+".png",
        nightday = "night";
    if(last_hour >= 6 && last_hour < 18) {
      moon_day = "day";
    }

    moonel.className = "phase " + nightday;
    moonel.children[1].src = "/cycle/"+moon;
    moonel.children[0].title = moonel.children[1].title = Aetheryte.getMoonPhase(ace).moon;

    sup.children[0].src = "/cycle/"+element.hour+".png";
    sup.children[0].title = (element.astral ? "astral" : "umbral") + " " + element.hour;
  } else {
    var cds = document.querySelectorAll(".countdown");
    for(var i = 0; i < cds.length; ++i) {
      var minuteDifference = 60 - date.getUTCMinutes();
      var timeDifference = parseInt(cds[i].dataset.fh) - (1 - (minuteDifference / 60));
      cds[i].textContent = Math.floor(remaining(timeDifference));
      if(cds[i].textContent == "0") {
        cds[i].textContent = "LESS THAN 1";
      }
    }
  }

  eorzea_time.textContent = formatTime(now);
  real_time.textContent = formatTime(start) + " UTC";

  if(daily === null || weekly === null || leve === null ||
     daily - start < 0 || weekly - start < 0 || leve - start < 0) {
    regenTimers();
  }

  dtimer.textContent = formatTime(daily - start, false, true);
  wtimer.textContent = formatTime(weekly - start, true, true);
  ltimer.textContent = formatTime(leve - start, false, true);
  var next =  50 - (Date.now() - start);
  if(next < 5) {
    next = 100;
  }
  setTimeout(tick, next);
}, init = function() {
  for(var key in window.nodes) {
    var number = parseInt(key);
    logicdata[number] = {hour: number, nodes: window.nodes[key]};

    var row = document.createElement("div");
    row.className = "row";
    var checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    checkbox.id = "seenabled"+number;
    checkbox.checked = localStorage[checkbox.id] || false;
    checkbox.addEventListener("mousedown", function(event) {
      localStorage[event.target.id] = event.target.checked;
    }, false);
    row.appendChild(checkbox);

    var rowTime = document.createElement("span");

    var rt = number, meridiem = "AM";
    if(rt > 11) {
      rt -= 12;
      meridiem = "PM";
    }
    rowTime.textContent = ("00" + rt).substr(-2) + ":00 " + meridiem;
    row.appendChild(rowTime);

    var span1 = document.createElement("span");
    span1.textContent = " | Sound Effect #";
    row.appendChild(span1);

    var rowNumber = document.createElement("input");
    rowNumber.id = "se"+number;
    rowNumber.min = 1;
    rowNumber.max = 16;
    rowNumber.value = localStorage[rowNumber.id] || 1;
    rowNumber.type = "number";
    rowNumber.addEventListener("change", function(event) {
      localStorage[event.target.id] = event.target.value;
    }, false);
    row.appendChild(rowNumber);

    var span2 = document.createElement("span");
    span2.textContent = " | ";
    row.appendChild(span2);

    var button = document.createElement("button");
    button.textContent = "Test";
    button.id="sebutton"+number;
    row.appendChild(button);
    button.addEventListener("mouseup", function(event) {
      playSound(document.getElementById("se"+event.target.id.replace("sebutton", "")).value);
    }, false);

    settingsRows.appendChild(row);
  }

  document.getElementById("close").addEventListener("mousedown", function() {
    settings.style.display = blacken.style.display = "none";
  }, false);

  document.getElementById("cog").addEventListener("mousedown", function() {
    settings.style.display = blacken.style.display = "block";
  }, false);

  tick();
}, sortByTime = function(hours) {
  var _ = logicdata.concat([]);
  for(var i = 0; i < hours; ++i) {
    _.push(_.shift());
  }
  return _;
}

init();
<commit_msg>Fix nightday variable in time.xivbeat.com<commit_after>var EZ_TIME_CONSTANT = 20.571428571428574,
    logicdata = new Array(24),
    last_hour = -1,
    data = undefined,
    eorzea_time = document.getElementById("eorzea_time").children[1],
    real_time = document.getElementById("real_time"),
    left = document.getElementById("left"),
    right = document.getElementById("right"),
    settingsRows = document.getElementById("rows"),
    settings = document.getElementById("settings"),
    blacken = document.getElementById("blacken"),
    currents = null,
    daily = null,
    weekly = null,
    leve = null,
    dtimer = document.getElementById("daily"),
    wtimer = document.getElementById("weekly"),
    ltimer = document.getElementById("leve"),
    sup = document.getElementById("eorzea_time").children[0],
    moonel = document.getElementById("eorzea_time").children[2];

var DateUTC = function(year, month, day, hour, minute, second) {
  var d = new Date();
  d.setFullYear(year);
  d.setUTCMonth(month);
  d.setUTCDate(day);
  d.setUTCHours(hour);
  d.setUTCMinutes(minute);
  d.setUTCSeconds(second);
  return d;
}, regenTimers = function() {
  currents = new Date();
  daily = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 15, 0, 0).getTime();
  if(currents.getTime() > daily) {
    daily = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + 1, 15, 0, 0).getTime();
  }

  var distance = currents.getUTCDay();
  distance -= 2;
  if(distance < 0) {
    distance = Math.abs(distance);
  }
  weekly = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + distance, 8, 0, 0).getTime();

  leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 0, 0, 0).getTime();
  if(currents.getTime() > leve) {
    leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate(), 12, 0, 0).getTime();
    if(currents.getTime() > leve) {
      leve = DateUTC(currents.getFullYear(), currents.getUTCMonth(), currents.getUTCDate() + 1, 0, 0, 0).getTime();
    }
  }
}, getEorzeaTime = function() {
  return Math.floor((Date.now() - 26127360000000) * EZ_TIME_CONSTANT);
}, formatTime = function(epoch, days, shmrd) {
  var date = new Date(epoch);
  var h = date.getUTCHours(), m = date.getUTCMinutes();
  var meridiem = "AM";
  if(h > 11 && !shmrd) {
    h -= 12;
    meridiem = "PM";
  }

  if(days && date.getUTCDate() > 1) {
    h += date.getUTCDate() * 24
  }

  var str = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2) + ":" + ("0" + date.getUTCSeconds()).substr(-2);

  if(!shmrd) {
    str += " " + meridiem;
  }
  return str;
}, remaining = function(futureHours) {
  return new Date(175 * futureHours * 1000).getTime() / 1000 / 60;
}, calculateHours = function(last, hour) {
  var timeDifference = 0;
  if(hour == last || hour == last + 1) {
    timeDifference = 1;
  } else {
    timeDifference = hour - last;
    if(timeDifference < 1) {
      timeDifference += 24;
    }
  }
  return timeDifference;
}, playSound = function(se) {
  var se = "/se/"+se+".mp3";
  var a = new Audio();
  a.addEventListener("canplay", function(){
    a.play();
  }, false);
  a.src = se;
  a.volume = 1;
}, tick = function() {
  var start = Date.now();
  var now = getEorzeaTime(),
      date = new Date(now),
      hour = date.getUTCHours();

  if(last_hour != hour) {
    data = sortByTime(hour);
    last_hour = hour;
    while(left.children.length) {
      left.removeChild(left.children[0]);
    }
    while(right.children.length) {
      right.removeChild(right.children[0]);
    }

    if(document.getElementById("seenabled"+hour) !== null && document.getElementById("seenabled"+hour).checked) {
      playSound(document.getElementById("se"+hour).value);
    }

    var ul = document.createElement("ul");
    for(var i = 0; i < 24; ++i) {
      var n = data[i];
      if(n === undefined) {
        continue;
      }
      var li = document.createElement("li");
      var hour = n.hour,
          meridiem = "AM";
      if(hour > 11) {
        hour -= 12;
        meridiem = "PM";
      }

      li.textContent = ("0" + hour).substr(-2) + ":00 " + meridiem;

      var timeDifference = calculateHours(last_hour, n.hour);
      var timeLeft = document.createElement("span");
      timeLeft.dataset.fh = timeDifference;
      var minuteDifference = 60 - date.getUTCMinutes();
      timeDifference -= (1 - (minuteDifference / 60));
      timeLeft.textContent = Math.floor(remaining(timeDifference));
      if(timeLeft.textContent == "0") {
        timeLeft.textContent = "LESS THAN 1";
      }
      timeLeft.className = "countdown";
      if(n.hour == last_hour) {
        timeLeft.className += " active";
      }
      li.dataset.fh = n.hour;
      li.appendChild(timeLeft);
      ul.appendChild(li);

      var n_ul = document.createElement("ul");
      n_ul.id = "nodes"+n.hour;
      for(var j = 0; j < n.nodes.length; ++j) {
        var node = n.nodes[j];
        var n_li = document.createElement("li");
        var c = document.createElement("span"),
            it = document.createElement("span"),
            s = document.createElement("span"),
            l = document.createElement("span");

        c.className = "class";
        it.className = "item";
        s.className = "slot";
        l.className = "location";

        n_li.className = c.textContent = node.class;
        it.textContent = node.item;
        if("location" in node) {
          l.textContent = node.location + " (" + node.coordinates[0] + ", " + node.coordinates[1] + ")";
        }

        if("slot" in node) {
          s.textContent = "Slot #"+node.slot;
        }

        n_li.appendChild(c);
        n_li.appendChild(it);
        n_li.appendChild(s);
        n_li.appendChild(l);

        n_ul.appendChild(n_li);
      }
      right.appendChild(n_ul);

      right.children[0].className = "show";
      li.addEventListener("mouseenter", function(event) {
        document.querySelector(".show").className = ""
        document.getElementById("nodes"+event.target.dataset.fh).className = "show";
        document.querySelector("li.active").className = "";
        event.target.className = "active";
      }, false);

    }
    left.appendChild(ul);
    left.children[0].children[0].className = "active";

    var ace = Aetheryte.getEorzeaTimeAce(),
        element = Aetheryte.getElement(ace),
        moon = "moon_"+["0", "-25", "-50", "-75", "100", "+75", "+50", "+25"][Aetheryte.getMoonPhase(ace).phase]+".png",
        nightday = "night";
    if(ace.hour >= 6 && ace.hour < 18) {
      moon_day = "day";
    }

    moonel.className = "phase " + nightday;
    moonel.children[1].src = "/cycle/"+moon;
    moonel.children[0].title = moonel.children[1].title = Aetheryte.getMoonPhase(ace).moon;

    sup.children[0].src = "/cycle/"+element.hour+".png";
    sup.children[0].title = (element.astral ? "astral" : "umbral") + " " + element.hour;
  } else {
    var cds = document.querySelectorAll(".countdown");
    for(var i = 0; i < cds.length; ++i) {
      var minuteDifference = 60 - date.getUTCMinutes();
      var timeDifference = parseInt(cds[i].dataset.fh) - (1 - (minuteDifference / 60));
      cds[i].textContent = Math.floor(remaining(timeDifference));
      if(cds[i].textContent == "0") {
        cds[i].textContent = "LESS THAN 1";
      }
    }
  }

  eorzea_time.textContent = formatTime(now);
  real_time.textContent = formatTime(start) + " UTC";

  if(daily === null || weekly === null || leve === null ||
     daily - start < 0 || weekly - start < 0 || leve - start < 0) {
    regenTimers();
  }

  dtimer.textContent = formatTime(daily - start, false, true);
  wtimer.textContent = formatTime(weekly - start, true, true);
  ltimer.textContent = formatTime(leve - start, false, true);
  var next =  50 - (Date.now() - start);
  if(next < 5) {
    next = 100;
  }
  setTimeout(tick, next);
}, init = function() {
  for(var key in window.nodes) {
    var number = parseInt(key);
    logicdata[number] = {hour: number, nodes: window.nodes[key]};

    var row = document.createElement("div");
    row.className = "row";
    var checkbox = document.createElement("input");
    checkbox.type = "checkbox";
    checkbox.id = "seenabled"+number;
    checkbox.checked = localStorage[checkbox.id] || false;
    checkbox.addEventListener("mousedown", function(event) {
      localStorage[event.target.id] = event.target.checked;
    }, false);
    row.appendChild(checkbox);

    var rowTime = document.createElement("span");

    var rt = number, meridiem = "AM";
    if(rt > 11) {
      rt -= 12;
      meridiem = "PM";
    }
    rowTime.textContent = ("00" + rt).substr(-2) + ":00 " + meridiem;
    row.appendChild(rowTime);

    var span1 = document.createElement("span");
    span1.textContent = " | Sound Effect #";
    row.appendChild(span1);

    var rowNumber = document.createElement("input");
    rowNumber.id = "se"+number;
    rowNumber.min = 1;
    rowNumber.max = 16;
    rowNumber.value = localStorage[rowNumber.id] || 1;
    rowNumber.type = "number";
    rowNumber.addEventListener("change", function(event) {
      localStorage[event.target.id] = event.target.value;
    }, false);
    row.appendChild(rowNumber);

    var span2 = document.createElement("span");
    span2.textContent = " | ";
    row.appendChild(span2);

    var button = document.createElement("button");
    button.textContent = "Test";
    button.id="sebutton"+number;
    row.appendChild(button);
    button.addEventListener("mouseup", function(event) {
      playSound(document.getElementById("se"+event.target.id.replace("sebutton", "")).value);
    }, false);

    settingsRows.appendChild(row);
  }

  document.getElementById("close").addEventListener("mousedown", function() {
    settings.style.display = blacken.style.display = "none";
  }, false);

  document.getElementById("cog").addEventListener("mousedown", function() {
    settings.style.display = blacken.style.display = "block";
  }, false);

  tick();
}, sortByTime = function(hours) {
  var _ = logicdata.concat([]);
  for(var i = 0; i < hours; ++i) {
    _.push(_.shift());
  }
  return _;
}

init();
<|endoftext|>


<commit_before>"use strict";

const seedrandom = require('seedrandom');

const lua        = require('./lua.js');
const lauxlib    = require('./lauxlib.js');
const llimit     = require('./llimit.js');
const luaconf    = require('./luaconf.js');

var RNG          = seedrandom();

const math_randomseed = function(L) {
    RNG = seedrandom(Math.abs(lauxlib.luaL_checknumber(L, 1)));
};

const math_random = function(L) {
    let low, up;
    let r = RNG();
    switch (lua.lua_gettop(L)) {  /* check number of arguments */
        case 0:
            lua.lua_pushnumber(L, r);  /* Number between 0 and 1 */
            return 1;
        case 1: {
            low = 1;
            up = lauxlib.luaL_checkinteger(L, 1);
            break;
        }
        case 2: {
            low = lauxlib.luaL_checkinteger(L, 1);
            up = lauxlib.luaL_checkinteger(L, 2);
            break;
        }
        default: return lauxlib.luaL_error(L, lua.to_luastring("wrong number of arguments", true));
    }

    /* random integer in the interval [low, up] */
    lauxlib.luaL_argcheck(L, low <= up, 1, lua.to_luastring("interval is empty", true));
    lauxlib.luaL_argcheck(L, low >= 0 || up <= llimit.MAX_INT + low, 1,
            lua.to_luastring("interval too large", true));

    r *= (up - low) + 1;
    lua.lua_pushinteger(L, Math.floor(r) + low);
    return 1;
};

const math_abs = function(L) {
    if (lua.lua_isinteger(L, 1)) {
        let n = lua.lua_tointeger(L, 1);
        if (n < 0) n = (-n)|0;
        lua.lua_pushinteger(L, n);
    }
    else
        lua.lua_pushnumber(L, Math.abs(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_sin = function(L) {
    lua.lua_pushnumber(L, Math.sin(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_cos = function(L) {
    lua.lua_pushnumber(L, Math.cos(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_tan = function(L) {
    lua.lua_pushnumber(L, Math.tan(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_asin = function(L) {
    lua.lua_pushnumber(L, Math.asin(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_acos = function(L) {
    lua.lua_pushnumber(L, Math.acos(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_atan = function(L) {
    lua.lua_pushnumber(L, Math.atan(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_toint = function(L) {
    let n = lua.lua_tointegerx(L, 1);
    if (n !== false)
        lua.lua_pushinteger(L, n);
    else {
        lauxlib.luaL_checkany(L, 1);
        lua.lua_pushnil(L);  /* value is not convertible to integer */
    }
    return 1;
};

const pushnumint = function(L, d) {
    let n = luaconf.lua_numbertointeger(d);
    if (n !== false)  /* does 'd' fit in an integer? */
        lua.lua_pushinteger(L, n);  /* result is integer */
    else
        lua.lua_pushnumber(L, d);  /* result is float */
};

const math_floor = function(L) {
    if (lua.lua_isinteger(L, 1))
        lua.lua_settop(L, 1);
    else
        pushnumint(L, Math.floor(lauxlib.luaL_checknumber(L, 1)));

    return 1;
};

const math_ceil = function(L) {
    if (lua.lua_isinteger(L, 1))
        lua.lua_settop(L, 1);
    else
        pushnumint(L, Math.ceil(lauxlib.luaL_checknumber(L, 1)));

    return 1;
};

const math_sqrt = function(L) {
    lua.lua_pushnumber(L, Math.sqrt(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_ult = function(L) {
    let a = lauxlib.luaL_checkinteger(L, 1);
    let b = lauxlib.luaL_checkinteger(L, 2);
    if (a < 0) a += 4294967296;
    if (b < 0) b += 4294967296;
    lua.lua_pushboolean(L, a < b);
    return 1;
};

const math_log = function(L) {
    let x = lauxlib.luaL_checknumber(L, 1);
    let res;
    if (lua.lua_isnoneornil(L, 2))
        res = Math.log(x);
    else {
        let base = lauxlib.luaL_checknumber(L, 2);
        if (base === 2)
            res = Math.log2(x);
        else if (base === 10)
            res = Math.log10(x);
        else
            res = Math.log(x)/Math.log(base);
    }
    lua.lua_pushnumber(L, res);
    return 1;
};

const math_exp = function(L) {
    lua.lua_pushnumber(L, Math.exp(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_deg = function(L) {
    lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (180 / Math.PI));
    return 1;
};

const math_rad = function(L) {
    lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (Math.PI / 180));
    return 1;
};

const math_min = function(L) {
    let n = lua.lua_gettop(L);  /* number of arguments */
    let imin = 1;  /* index of current minimum value */
    lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected", true));
    for (let i = 2; i <= n; i++){
        if (lua.lua_compare(L, i, imin, lua.LUA_OPLT))
            imin = i;
    }
    lua.lua_pushvalue(L, imin);
    return 1;
};

const math_max = function(L) {
    let n = lua.lua_gettop(L);  /* number of arguments */
    let imax = 1;  /* index of current minimum value */
    lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected", true));
    for (let i = 2; i <= n; i++){
        if (lua.lua_compare(L, imax, i, lua.LUA_OPLT))
            imax = i;
    }
    lua.lua_pushvalue(L, imax);
    return 1;
};

const math_type = function(L) {
    if (lua.lua_type(L, 1) === lua.LUA_TNUMBER) {
        if (lua.lua_isinteger(L, 1))
            lua.lua_pushliteral(L, "integer");
        else
            lua.lua_pushliteral(L, "float");
    } else {
        lauxlib.luaL_checkany(L, 1);
        lua.lua_pushnil(L);
    }
    return 1;
};

const math_fmod = function(L) {
    if (lua.lua_isinteger(L, 1) && lua.lua_isinteger(L, 2)) {
        let d = lua.lua_tointeger(L, 2);
        /* no special case needed for -1 in javascript */
        if (d === 0) {
            lauxlib.luaL_argerror(L, 2, lua.to_luastring("zero", true));
        } else
            lua.lua_pushinteger(L, (lua.lua_tointeger(L, 1) % d)|0);
    } else {
        let a = lauxlib.luaL_checknumber(L, 1);
        let b = lauxlib.luaL_checknumber(L, 2);
        lua.lua_pushnumber(L, a%b);
    }
    return 1;
};

const math_modf = function(L) {
    if (lua.lua_isinteger(L, 1)) {
        lua.lua_settop(L, 1);  /* number is its own integer part */
        lua.lua_pushnumber(L, 0);  /* no fractional part */
    } else {
        let n = lauxlib.luaL_checknumber(L, 1);
        let ip = n < 0 ? Math.ceil(n) : Math.floor(n);
        pushnumint(L, ip);
        lua.lua_pushnumber(L, n === ip ? 0 : n - ip);
    }
    return 2;
};

const mathlib = {
    "abs":        math_abs,
    "acos":       math_acos,
    "asin":       math_asin,
    "atan":       math_atan,
    "ceil":       math_ceil,
    "cos":        math_cos,
    "deg":        math_deg,
    "exp":        math_exp,
    "floor":      math_floor,
    "fmod":       math_fmod,
    "log":        math_log,
    "max":        math_max,
    "min":        math_min,
    "modf":       math_modf,
    "rad":        math_rad,
    "random":     math_random,
    "randomseed": math_randomseed,
    "sin":        math_sin,
    "sqrt":       math_sqrt,
    "tan":        math_tan,
    "tointeger":  math_toint,
    "type":       math_type,
    "ult":        math_ult
};

const luaopen_math = function(L) {
    lauxlib.luaL_newlib(L, mathlib);
    lua.lua_pushnumber(L, Math.PI);
    lua.lua_setfield(L, -2, lua.to_luastring("pi", true));
    lua.lua_pushnumber(L, Infinity);
    lua.lua_setfield(L, -2, lua.to_luastring("huge", true));
    lua.lua_pushinteger(L, llimit.MAX_INT);
    lua.lua_setfield(L, -2, lua.to_luastring("maxinteger", true));
    lua.lua_pushinteger(L, llimit.MIN_INT);
    lua.lua_setfield(L, -2, lua.to_luastring("mininteger", true));
    return 1;
};

module.exports.luaopen_math = luaopen_math;
<commit_msg>src/lmathlib.js: Implement math.atan second argument<commit_after>"use strict";

const seedrandom = require('seedrandom');

const lua        = require('./lua.js');
const lauxlib    = require('./lauxlib.js');
const llimit     = require('./llimit.js');
const luaconf    = require('./luaconf.js');

var RNG          = seedrandom();

const math_randomseed = function(L) {
    RNG = seedrandom(Math.abs(lauxlib.luaL_checknumber(L, 1)));
};

const math_random = function(L) {
    let low, up;
    let r = RNG();
    switch (lua.lua_gettop(L)) {  /* check number of arguments */
        case 0:
            lua.lua_pushnumber(L, r);  /* Number between 0 and 1 */
            return 1;
        case 1: {
            low = 1;
            up = lauxlib.luaL_checkinteger(L, 1);
            break;
        }
        case 2: {
            low = lauxlib.luaL_checkinteger(L, 1);
            up = lauxlib.luaL_checkinteger(L, 2);
            break;
        }
        default: return lauxlib.luaL_error(L, lua.to_luastring("wrong number of arguments", true));
    }

    /* random integer in the interval [low, up] */
    lauxlib.luaL_argcheck(L, low <= up, 1, lua.to_luastring("interval is empty", true));
    lauxlib.luaL_argcheck(L, low >= 0 || up <= llimit.MAX_INT + low, 1,
            lua.to_luastring("interval too large", true));

    r *= (up - low) + 1;
    lua.lua_pushinteger(L, Math.floor(r) + low);
    return 1;
};

const math_abs = function(L) {
    if (lua.lua_isinteger(L, 1)) {
        let n = lua.lua_tointeger(L, 1);
        if (n < 0) n = (-n)|0;
        lua.lua_pushinteger(L, n);
    }
    else
        lua.lua_pushnumber(L, Math.abs(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_sin = function(L) {
    lua.lua_pushnumber(L, Math.sin(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_cos = function(L) {
    lua.lua_pushnumber(L, Math.cos(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_tan = function(L) {
    lua.lua_pushnumber(L, Math.tan(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_asin = function(L) {
    lua.lua_pushnumber(L, Math.asin(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_acos = function(L) {
    lua.lua_pushnumber(L, Math.acos(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_atan = function(L) {
    let y = lauxlib.luaL_checknumber(L, 1);
    let x = lauxlib.luaL_optnumber(L, 2, 1);
    lua.lua_pushnumber(L, Math.atan2(y, x));
    return 1;
};

const math_toint = function(L) {
    let n = lua.lua_tointegerx(L, 1);
    if (n !== false)
        lua.lua_pushinteger(L, n);
    else {
        lauxlib.luaL_checkany(L, 1);
        lua.lua_pushnil(L);  /* value is not convertible to integer */
    }
    return 1;
};

const pushnumint = function(L, d) {
    let n = luaconf.lua_numbertointeger(d);
    if (n !== false)  /* does 'd' fit in an integer? */
        lua.lua_pushinteger(L, n);  /* result is integer */
    else
        lua.lua_pushnumber(L, d);  /* result is float */
};

const math_floor = function(L) {
    if (lua.lua_isinteger(L, 1))
        lua.lua_settop(L, 1);
    else
        pushnumint(L, Math.floor(lauxlib.luaL_checknumber(L, 1)));

    return 1;
};

const math_ceil = function(L) {
    if (lua.lua_isinteger(L, 1))
        lua.lua_settop(L, 1);
    else
        pushnumint(L, Math.ceil(lauxlib.luaL_checknumber(L, 1)));

    return 1;
};

const math_sqrt = function(L) {
    lua.lua_pushnumber(L, Math.sqrt(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_ult = function(L) {
    let a = lauxlib.luaL_checkinteger(L, 1);
    let b = lauxlib.luaL_checkinteger(L, 2);
    if (a < 0) a += 4294967296;
    if (b < 0) b += 4294967296;
    lua.lua_pushboolean(L, a < b);
    return 1;
};

const math_log = function(L) {
    let x = lauxlib.luaL_checknumber(L, 1);
    let res;
    if (lua.lua_isnoneornil(L, 2))
        res = Math.log(x);
    else {
        let base = lauxlib.luaL_checknumber(L, 2);
        if (base === 2)
            res = Math.log2(x);
        else if (base === 10)
            res = Math.log10(x);
        else
            res = Math.log(x)/Math.log(base);
    }
    lua.lua_pushnumber(L, res);
    return 1;
};

const math_exp = function(L) {
    lua.lua_pushnumber(L, Math.exp(lauxlib.luaL_checknumber(L, 1)));
    return 1;
};

const math_deg = function(L) {
    lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (180 / Math.PI));
    return 1;
};

const math_rad = function(L) {
    lua.lua_pushnumber(L, lauxlib.luaL_checknumber(L, 1) * (Math.PI / 180));
    return 1;
};

const math_min = function(L) {
    let n = lua.lua_gettop(L);  /* number of arguments */
    let imin = 1;  /* index of current minimum value */
    lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected", true));
    for (let i = 2; i <= n; i++){
        if (lua.lua_compare(L, i, imin, lua.LUA_OPLT))
            imin = i;
    }
    lua.lua_pushvalue(L, imin);
    return 1;
};

const math_max = function(L) {
    let n = lua.lua_gettop(L);  /* number of arguments */
    let imax = 1;  /* index of current minimum value */
    lauxlib.luaL_argcheck(L, n >= 1, 1, lua.to_luastring("value expected", true));
    for (let i = 2; i <= n; i++){
        if (lua.lua_compare(L, imax, i, lua.LUA_OPLT))
            imax = i;
    }
    lua.lua_pushvalue(L, imax);
    return 1;
};

const math_type = function(L) {
    if (lua.lua_type(L, 1) === lua.LUA_TNUMBER) {
        if (lua.lua_isinteger(L, 1))
            lua.lua_pushliteral(L, "integer");
        else
            lua.lua_pushliteral(L, "float");
    } else {
        lauxlib.luaL_checkany(L, 1);
        lua.lua_pushnil(L);
    }
    return 1;
};

const math_fmod = function(L) {
    if (lua.lua_isinteger(L, 1) && lua.lua_isinteger(L, 2)) {
        let d = lua.lua_tointeger(L, 2);
        /* no special case needed for -1 in javascript */
        if (d === 0) {
            lauxlib.luaL_argerror(L, 2, lua.to_luastring("zero", true));
        } else
            lua.lua_pushinteger(L, (lua.lua_tointeger(L, 1) % d)|0);
    } else {
        let a = lauxlib.luaL_checknumber(L, 1);
        let b = lauxlib.luaL_checknumber(L, 2);
        lua.lua_pushnumber(L, a%b);
    }
    return 1;
};

const math_modf = function(L) {
    if (lua.lua_isinteger(L, 1)) {
        lua.lua_settop(L, 1);  /* number is its own integer part */
        lua.lua_pushnumber(L, 0);  /* no fractional part */
    } else {
        let n = lauxlib.luaL_checknumber(L, 1);
        let ip = n < 0 ? Math.ceil(n) : Math.floor(n);
        pushnumint(L, ip);
        lua.lua_pushnumber(L, n === ip ? 0 : n - ip);
    }
    return 2;
};

const mathlib = {
    "abs":        math_abs,
    "acos":       math_acos,
    "asin":       math_asin,
    "atan":       math_atan,
    "ceil":       math_ceil,
    "cos":        math_cos,
    "deg":        math_deg,
    "exp":        math_exp,
    "floor":      math_floor,
    "fmod":       math_fmod,
    "log":        math_log,
    "max":        math_max,
    "min":        math_min,
    "modf":       math_modf,
    "rad":        math_rad,
    "random":     math_random,
    "randomseed": math_randomseed,
    "sin":        math_sin,
    "sqrt":       math_sqrt,
    "tan":        math_tan,
    "tointeger":  math_toint,
    "type":       math_type,
    "ult":        math_ult
};

const luaopen_math = function(L) {
    lauxlib.luaL_newlib(L, mathlib);
    lua.lua_pushnumber(L, Math.PI);
    lua.lua_setfield(L, -2, lua.to_luastring("pi", true));
    lua.lua_pushnumber(L, Infinity);
    lua.lua_setfield(L, -2, lua.to_luastring("huge", true));
    lua.lua_pushinteger(L, llimit.MAX_INT);
    lua.lua_setfield(L, -2, lua.to_luastring("maxinteger", true));
    lua.lua_pushinteger(L, llimit.MIN_INT);
    lua.lua_setfield(L, -2, lua.to_luastring("mininteger", true));
    return 1;
};

module.exports.luaopen_math = luaopen_math;
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')

class FileService {
  get scripts() {
    const folderContent = fs.readdirSync(path.join(this.configService.folderPath, 'scripts'))
    const authorizedExtensions = this.configService.scriptExtension

    return folderContent
      .filter(element => {
        const foundResults = []
        for (const extension of authorizedExtensions) {
          foundResults.push(element.includes(extension))
        }

        return foundResults.filter(element => element).length > 0
      })
      .map(element => {
        const [scriptName] = element.split('.')
        const scriptSlug = scriptName
          .toLowerCase()
          .replace(/ /g,'-')
          .replace(/[^\w-]+/g,'')

        return {
          script: scriptSlug,
          file: element
        }
      })
  }

  get modules() {}

  constructor(configService) {
    this.configService = configService

    this._scripts = []
    this._modules = []
  }
}

module.exports = exports = { FileService }
<commit_msg>Add path to script in FileService<commit_after>const fs = require('fs')
const path = require('path')

class FileService {
  get scripts() {
    const folderContent = fs.readdirSync(path.join(this.configService.folderPath, 'scripts'))
    const authorizedExtensions = this.configService.scriptExtension

    return folderContent
      .filter(element => {
        const foundResults = []
        for (const extension of authorizedExtensions) {
          foundResults.push(element.includes(extension))
        }

        return foundResults.filter(element => element).length > 0
      })
      .map(element => {
        const [scriptName] = element.split('.')
        const scriptSlug = scriptName
          .toLowerCase()
          .replace(/ /g,'-')
          .replace(/[^\w-]+/g,'')

        return {
          script: scriptSlug,
          file : element,
          path: path.join(this.configService.folderPath, 'scripts', element)
        }
      })
  }

  get modules() {}

  constructor(configService) {
    this.configService = configService

    this._scripts = []
    this._modules = []
  }
}

module.exports = exports = { FileService }
<|endoftext|>


<commit_before>module.exports = function (_Firebase) {
  Firebase = _Firebase
  return Node
}

var debug = require('debug')('fireflower')
var events = require('events')
var inherits = require('inherits')
var SimplePeer = require('simple-peer')
var Firebase = null

var CONNECTION_TIMEOUT = 2000

inherits(Node, events.EventEmitter)

function Node (url, opts) {
  if (!(this instanceof Node)) {
    return new Node(url, opts)
  }

  this.url = url
  this.opts = opts || {}
  this.id = this.opts.id
  this.state = 'disconnected'
  this.config = {}
  this.peers = {}

  // firebase refs
  this._ref = new Firebase(this.url)
  this._requestsRef = this._ref.child('requests')
  this._configRef = this._ref.child('configuration')

  // if we weren't assigned an id, get one from the db
  this.id = this.id || this._requestsRef.push().key()

  this._requestRef = this._requestsRef.child(this.id)
  this._responsesRef = this._requestRef.child('responses')

  // bind callbacks
  this._onconfig = this._onconfig.bind(this)
  this._doconnect = this._doconnect.bind(this)
  this._onresponse = this._onresponse.bind(this)
  this._onrequest = this._onrequest.bind(this)

  events.EventEmitter.call(this)
}

Node.prototype.connect = function () {
  if (this.state !== 'disconnected') {
    throw new Error('invalid state for connect')
  }

  // make sure this is not set
  this._preventReconnect = false

  // change state -> requesting
  debug(this.id + ' requesting connection')
  this.state = 'requesting'
  this.emit('statechange')

  // watch config
  if (!this._watchingConfig) {
    this._configRef.on('value', this._onconfig)
    this._watchingConfig = true
  }

  // ensure required config info
  if (!this.config.root || !this.config.K) {
    this.once('configure', this._doconnect)
    return this
  }

  this._doconnect()

  return this
}

Node.prototype.disconnect = function () {
  this.state = 'disconnected'
  this._preventReconnect = true

  // teardown listeners
  this.removeListener('configure', this._doconnect)
  this._configRef.off('value', this._onconfig)
  this._requestsRef.off('child_added', this._onrequest)
  this._responsesRef.off('child_added', this._onresponse)

  // ensure request is removed
  this._requestRef.remove()

  // destroy upstream connection
  this.root && this.root !== this && this.root.destroy()

  // destroy downstream connections
  for (var i in this.peers) {
    this.peers[i].destroy()
  }

  this.root = null
  this.peers = {}
  this._watchingConfig = false

  return this
}

// private api below

Node.prototype._onconfig = function (snapshot) {
  var data = snapshot.val()

  if (!data) {
    this.emit('error', new Error('missing configuration'))
    return
  }

  if (!data.K) {
    this.emit('error', new Error('configuration did not supply valid value for K'))
    return
  }

  if (!data.root) {
    this.emit('error', new Error('configuration did not supply a valid root'))
    return
  }

  this.config = data
  debug(this.id + ' updated configuration')
  this.emit('configure')
}

Node.prototype._doconnect = function () {
  var self = this

  // are we root?
  if (this.id === this.config.root) {
    this.root = this
    this.branch = ''

    // emit connect but in nextTick
    setTimeout(function () {
      // change state -> connected
      debug(self.id + ' connected as root')
      self.state = 'connected'
      self.emit('statechange')

      // emit connect
      self.emit('connect')

      // start responding to requests
      self._requestsRef.on('child_added', self._onrequest)
    })

    return
  }

  // make sure we have a branch
  this.branch = this.branch || this.id.slice(-5)

  // we are not root so publish a connection request
  this._dorequest()

  // make sure no one removes our request until we're connected
  this._requestRef.child('removal_flag').on('child_removed', function () {
    if (self.state === 'requesting') {
      self._dorequest()
    }
  })

  // listen for responses
  this._responsesRef.on('child_added', this._onresponse)
}

Node.prototype._dorequest = function () {
  this._requestRef.update({
    branch: this.branch,
    removal_flag: {
      removed: false
    }
  }, function (err) {
    if (err) throw err // can this ever happen?
  })
}

Node.prototype._onrequest = function (snapshot) {
  if (this.state !== 'connected') {
    return // can't respond to requests unless we are connected
  }

  if (this.disabled) {
    return // useful for debugging
  }

  if (Object.keys(this.peers).length >= this.config.K) {
    return // can't respond to requests if we've hit K peers
  }

  var self = this
  var request = snapshot.val()
  var requestRef = snapshot.ref()
  var peerId = snapshot.key()

  // responders may accidentally recreate requests
  // these won't have a branch though and can be removed
  if (!request.branch) {
    requestRef.remove()
    return
  }

  // prevent circles
  if (this.branch.slice(0, 5) === request.branch.slice(0, 5) &&
      this.branch.length >= request.branch.length) {
    return
  }

  // it is possible to see a peer we already knew about
  var knownPeer = this.peers[peerId]
  if (knownPeer) {
    if (knownPeer.didConnect) {
      // we may not have witnessed them disconnect before they re-requested
      // if that happens we destroy them in the same tick and respond immediately
      knownPeer.destroy()
    } else {
      // we may have timed out while trying to connect to somebody else
      // if that happens we may have gotten a fresh list of requests
      // that included this peer which we are still connecting to
      return
    }
  }

  debug(this.id + ' saw request by ' + peerId)

  var responseRef = requestRef.child('responses/' + this.id)

  // initiate peer connection
  // we have to do this before actually writing our response because
  // firebase can trigger events in the same tick which could circumvent
  // the K check at the top of this method
  this._connectToPeer(peerId, true, responseRef)

  // publish response
  responseRef.update({
    branch: this.branch || '-'
  })

  // watch for request withdrawal
  responseRef.once('child_removed', function () {
    var peer = self.peers[peerId]
    if (peer && !peer.didConnect) {
      peer.requestWithdrawn = true
      peer.destroy()
    }
  })
}

Node.prototype._onresponse = function (snapshot) {
  if (this.state !== 'requesting') {
    return
  }

  var response = snapshot.val()
  var responseRef = snapshot.ref()
  var peerId = snapshot.key()
  var branch = response.branch

  if (!branch) {
    return
  } else if (branch === '-') {
    branch = ''
  }

  // TODO! prevent circles / allow proper healing
  // using this.branch and request.branch
  // this should be handled on the _onrequest side
  // but decisions should be rechecked on this side too

  // change state -> connecting (this prevents accepting multiple responses)
  debug(this.id + ' got response from ' + peerId)
  this.state = 'connecting'
  this.emit('statechange')

  // stop taking responses
  // WARNING: no idea why, but calling off() can trigger additional
  // events in the same tick so be sure to do it after changing state
  this._responsesRef.off('child_added', this._onresponse)
  this._requestRef.child('removal_flag').off()

  // attempt a connection
  this._connectToPeer(peerId, false, responseRef, branch)
}

Node.prototype._connectToPeer = function (peerId, initiator, responseRef, branch) {
  var self = this
  var localSignals = responseRef.child(initiator ? 'responderSignals' : 'requesterSignals')
  var remoteSignals = responseRef.child(initiator ? 'requesterSignals' : 'responderSignals')

  var peer = new SimplePeer({
    initiator: initiator
  })

  peer.id = peerId

  if (initiator) {
    this.peers[peer.id] = peer
  } else {
    peer.branch = branch
  }

  peer.on('connect', this._onpeerConnect.bind(this, peer, remoteSignals))
  peer.on('close', this._onpeerDisconnect.bind(this, peer, remoteSignals))

  peer.on('error', function (err) {
    debug(this.id + ' saw peer connection error', err)
  })

  peer.on('signal', function (signal) {
    if (initiator && self.state !== 'connected') return
    signal = JSON.parse(JSON.stringify(signal))
    localSignals.push(signal)
  })

  remoteSignals.on('child_added', function (snapshot) {
    if (initiator && self.state !== 'connected') return
    var signal = snapshot.val()
    peer.signal(signal)
  })

  // timeout connections
  setTimeout(function () {
    if (!peer.didConnect) {
      peer.destroy()
    }
  }, CONNECTION_TIMEOUT)
}

Node.prototype._onpeerConnect = function (peer, remoteSignals) {
  peer.didConnect = true
  peer.removeAllListeners('connect')
  peer.removeAllListeners('signal')
  remoteSignals.off()

  peer._channel.maxPacketLifeTime = this.opts.maxPacketLifeTime || null
  peer._channel.maxRetransmits = this.opts.maxRetransmits || null
  peer._channel.ordered = this.opts.ordered === false ? false : true

  if (this.peers[peer.id]) {
    this._ondownstreamConnect(peer)
  } else {
    this._onupstreamConnect(peer)
  }
}

Node.prototype._onpeerDisconnect = function (peer, remoteSignals) {
  peer.removeAllListeners()
  remoteSignals.off()

  if (this.peers[peer.id]) {
    this._ondownstreamDisconnect(peer)
  } else {
    this._onupstreamDisconnect(peer)
  }
}

Node.prototype._onupstreamConnect = function (peer) {
  // remove our request
  this._requestRef.remove()

  // already got connected by someone else
  if (this.state === 'connected') {
    peer.destroy()
    return
  }

  // whoever just connected us is (as good as) root
  this.root = peer

  // update branch
  this.branch = peer.branch + this.id.slice(-5)

  // change state -> connected
  debug(this.id + ' was connected by ' + peer.id)
  this.state = 'connected'
  this.emit('statechange')

  // emit connect
  this.emit('connect', peer)

  // start responding to requests
  if (Object.keys(this.peers).length < this.config.K) {
    this._requestsRef.on('child_added', this._onrequest)
  }
}

Node.prototype._onupstreamDisconnect = function (peer) {
  // stop responding to new requests
  this._requestsRef.off('child_added', this._onrequest)

  // remove request
  this._requestRef.remove()

  delete this.root

  // change state -> disconnected
  debug(this.id + ' lost connection to ' + peer.id)
  this.state = 'disconnected'
  this.emit('statechange')

  // emit disconnect if we were connected
  if (peer.didConnect) {
    this.emit('disconnect', peer)
  }

  // FIXME kill all downstream connections to ensure circles don't occur
  for (var i in this.peers) {
    this.peers[i].destroy()
  }

  // attempt to reconnect if we were not disconnected intentionally
  if (!this._preventReconnect) {
    this.connect()
  }
}

Node.prototype._ondownstreamConnect = function (peer) {
  // emit peerconnect
  debug(this.id + ' did connect peer ' + peer.id)
  this.emit('peerconnect', peer)

  // stop responding to requests if peers > K
  if (Object.keys(this.peers).length >= this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
  }
}

Node.prototype._ondownstreamDisconnect = function (peer) {
  // remove from lookup
  delete this.peers[peer.id]

  // emit events and potentially remove stale requests
  if (peer.didConnect) {
    debug(this.id + ' lost connection to peer ' + peer.id)
    this.emit('peerdisconnect', peer)
  } else {
    if (peer.requestWithdrawn) {
      debug(this.id + ' saw request withdrawn by ' + peer.id)
    } else {
      debug(this.id + ' removing stale request by ' + peer.id)
      this._requestsRef.child(peer.id).remove()
    }
  }

  // if we are connected but not currently taking requests
  // and back below K, start accepting them again
  if (this.state === 'connected' && Object.keys(this.peers).length < this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
    this._requestsRef.on('child_added', this._onrequest)
  }
}
<commit_msg>eliminate cascading disconnects<commit_after>module.exports = function (_Firebase) {
  Firebase = _Firebase
  return Node
}

var debug = require('debug')('fireflower')
var events = require('events')
var inherits = require('inherits')
var SimplePeer = require('simple-peer')
var Firebase = null

var CONNECTION_TIMEOUT = 2000

inherits(Node, events.EventEmitter)

function Node (url, opts) {
  if (!(this instanceof Node)) {
    return new Node(url, opts)
  }

  this.url = url
  this.opts = opts || {}
  this.root = this.opts.root
  this.state = 'disconnected'
  this.config = {}
  this.upstream = null
  this.downstream = {}

  // firebase refs
  this._ref = new Firebase(this.url)
  this._configRef = this._ref.child('configuration')
  this._requestsRef = this._ref.child('requests')

  // set a random id if one was not provided
  this.id = this.opts.id || this._requestsRef.push().key()

  // bind callbacks
  this._onconfig = this._onconfig.bind(this)
  this._doconnect = this._doconnect.bind(this)
  this._onrequest = this._onrequest.bind(this)
  this._onresponse = this._onresponse.bind(this)
  this._onmaskupdate = this._onmaskupdate.bind(this)

  events.EventEmitter.call(this)
}

Node.prototype.connect = function () {
  if (this.state !== 'disconnected') {
    throw new Error('invalid state for connect')
  }

  this._preventReconnect = false

  // change state -> requesting
  debug(this.id + ' requesting connection')
  this.state = 'requesting'
  this.emit('statechange')

  // watch config
  if (!this._watchingConfig) {
    this._configRef.on('value', this._onconfig)
    this._watchingConfig = true
  }

  // ensure required config info
  if (!this.config.K) {
    this.once('configure', this._doconnect)
    return this
  }

  this._doconnect()

  return this
}

Node.prototype.disconnect = function () {
  this.state = 'disconnected'
  this._preventReconnect = true
  this._watchingConfig = false

  // remove some listeners
  this.removeListener('configure', this._doconnect)
  this._configRef.off('value', this._onconfig)
  this._requestsRef.off('child_added', this._onrequest)

  // remove outstanding request / response listener
  if (this._requestRef) {
    this._requestRef.remove()
    this._responsesRef.off('child_added', this._onresponse)
  }

  // destroy upstream connection
  if (this.upstream) {
    this.upstream.destroy()
    this.upstream = null
  }

  // destroy downstream connections
  for (var i in this.downstream) {
    this.downstream[i].destroy()
  }
  this.downstream = {}

  return this
}

// private api below

Node.prototype._onconfig = function (snapshot) {
  var data = snapshot.val()

  if (!data) {
    this.emit('error', new Error('missing configuration'))
    return
  }

  if (!data.K || isNaN(data.K)) {
    this.emit('error', new Error('configuration did not supply valid value for K'))
    return
  }

  this.config = data
  debug(this.id + ' updated configuration')
  this.emit('configure')
}

Node.prototype._doconnect = function () {
  var self = this

  if (this.root) {

    // emit connect but in nextTick
    setTimeout(function () {
      // change state -> connected
      debug(self.id + ' connected as root')
      self.state = 'connected'
      self.emit('statechange')

      // emit connect
      self.emit('connect')

      // start responding to requests
      self._requestsRef.on('child_added', self._onrequest)
    })

    return
  }

  // we are not root so publish a connection request
  this._dorequest()
}

Node.prototype._dorequest = function () {
  var self = this

  this._requestRef = this._requestsRef.push({
    id: this.id,
    removal_flag: {
      removed: false
    }
  })

  // make sure no one removes our request until we're connected
  this._requestRef.child('removal_flag').once('child_removed', function () {
    if (self.state === 'requesting') {
      self._responsesRef.off('child_added', self._onresponse)
      self._dorequest()
    }
  })

  // listen for a response
  this._responsesRef = this._requestRef.child('responses')
  this._responsesRef.once('child_added', this._onresponse)
}

Node.prototype._onrequest = function (snapshot) {
  if (this.state !== 'connected') {
    return // can't respond to requests unless we are connected
  }

  if (Object.keys(this.downstream).length >= this.config.K) {
    return // can't respond to requests if we've hit K peers
  }

  var self = this
  var requestRef = snapshot.ref()
  var requestId = snapshot.key()
  var request = snapshot.val()
  var peerId = request.id

  // responders may accidentally recreate requests
  // these won't have an id though and can be removed
  if (!peerId) {
    requestRef.remove()
    return
  }

  // prevent circles
  if (peerId === this._mask) {
    return
  }

  // since we review requests after every connect / disconnect
  // it is possible to see a peer we know about
  var knownPeer = this.downstream[peerId]
  if (knownPeer) {
    if (knownPeer.requestId !== requestId) {
      // if request ids don't match, the peer must have disconnected without us noticing
      knownPeer.destroy()
    } else {
      return
    }
  }

  debug(this.id + ' saw request by ' + peerId)

  var responseRef = requestRef.child('responses/' + this.id)

  // initiate peer connection
  // we have to do this before actually writing our response because
  // firebase can trigger events in the same tick which could circumvent
  // the K check at the top of this method
  this._connectToPeer(true, peerId, requestId, responseRef)

  // publish response
  responseRef.update({
    id: this.id
  })

  // watch for request withdrawal
  responseRef.once('child_removed', function () {
    var peer = self.downstream[peerId]
    if (peer && !peer.didConnect) {
      peer.requestWithdrawn = true
      peer.destroy()
    }
  })
}

Node.prototype._onresponse = function (snapshot) {
  if (this.state !== 'requesting') {
    return
  }

  var responseRef = snapshot.ref()
  var response = snapshot.val()
  var peerId = response.id

  if (!peerId) {
    return
  }

  // change state -> connecting (this prevents accepting multiple responses)
  debug(this.id + ' got response from ' + peerId)
  this.state = 'connecting'
  this.emit('statechange')

  // stop watching for request removal
  this._requestRef.child('removal_flag').off()

  // attempt a connection
  this._connectToPeer(false, peerId, null, responseRef)
}

Node.prototype._connectToPeer = function (initiator, peerId, requestId, responseRef) {
  var self = this
  var localSignals = responseRef.child(initiator ? 'responderSignals' : 'requesterSignals')
  var remoteSignals = responseRef.child(initiator ? 'requesterSignals' : 'responderSignals')

  var peer = new SimplePeer({
    initiator: initiator
  })

  peer.id = peerId

  if (initiator) {
    this.downstream[peer.id] = peer
    peer.notifications = peer._pc.createDataChannel('notifications')
    peer.requestId = requestId
  } else {
    var oldondatachannel = peer._pc.ondatachannel
    peer._pc.ondatachannel = function (evt) {
      if (evt.channel.label === 'notifications') {
        peer.notifications = evt.channel
        peer.notifications.onmessage = self._onmaskupdate
      } else {
        oldondatachannel(evt)
      }
    }
  }

  peer.on('connect', this._onpeerConnect.bind(this, peer, remoteSignals))
  peer.on('close', this._onpeerDisconnect.bind(this, peer, remoteSignals))

  peer.on('error', function (err) {
    debug(this.id + ' saw peer connection error', err)
  })

  peer.on('signal', function (signal) {
    if (initiator && self.state !== 'connected') return
    signal = JSON.parse(JSON.stringify(signal))
    localSignals.push(signal)
  })

  remoteSignals.on('child_added', function (snapshot) {
    if (initiator && self.state !== 'connected') return
    var signal = snapshot.val()
    peer.signal(signal)
  })

  // timeout connections
  setTimeout(function () {
    if (!peer.didConnect) {
      peer.destroy()
    }
  }, CONNECTION_TIMEOUT)
}

Node.prototype._onpeerConnect = function (peer, remoteSignals) {
  peer.didConnect = true
  peer.removeAllListeners('connect')
  peer.removeAllListeners('signal')
  remoteSignals.off()

  peer._channel.maxPacketLifeTime = this.opts.maxPacketLifeTime || null
  peer._channel.maxRetransmits = this.opts.maxRetransmits || null
  peer._channel.ordered = this.opts.ordered === false ? false : true

  if (this.downstream[peer.id]) {
    this._ondownstreamConnect(peer)
  } else {
    this._onupstreamConnect(peer)
  }
}

Node.prototype._onpeerDisconnect = function (peer, remoteSignals) {
  peer.removeAllListeners()
  remoteSignals.off()

  if (this.downstream[peer.id]) {
    this._ondownstreamDisconnect(peer)
  } else {
    this._onupstreamDisconnect(peer)
  }
}

Node.prototype._onupstreamConnect = function (peer) {
  // remove our request
  this._requestRef.remove()

  // already got connected by someone else
  if (this.state === 'connected') {
    debug(this.id + ' rejected upstream connection by ' + peer.id)
    peer.destroy()
    return
  }

  this.upstream = peer

  // change state -> connected
  debug(this.id + ' established upstream connection to ' + peer.id)
  this.state = 'connected'
  this.emit('statechange')
  this.emit('connect', peer)

  // begin responding to requests
  this._reviewRequests()
}

Node.prototype._onupstreamDisconnect = function (peer) {
  // stop responding to new requests
  this._requestsRef.off('child_added', this._onrequest)

  // remove request
  this._requestRef.remove()

  this.upstream = null

  // change state -> disconnected
  if (this.state !== 'disconnected') {
    debug(this.id + ' lost upstream connection to ' + peer.id)
  }

  this.state = 'disconnected'
  this.emit('statechange')

  // emit disconnect if we were connected
  if (peer.didConnect) {
    this.emit('disconnect', peer)
  }

  // attempt to reconnect if we were not disconnected intentionally
  if (!this._preventReconnect) {

    // mask off our descendants
    this._onmaskupdate({ data: this.id })

    // give our mask update a tiny head start
    var self = this
    setTimeout(function () {
      self.connect()
    }, 100)
  }
}

Node.prototype._ondownstreamConnect = function (peer) {
  // emit peerconnect
  debug(this.id + ' established downstream connection to ' + peer.id)
  this.emit('peerconnect', peer)

  // stop responding to requests if peers > K
  if (Object.keys(this.downstream).length >= this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
  }
}

Node.prototype._ondownstreamDisconnect = function (peer) {
  // remove from lookup
  delete this.downstream[peer.id]

  // emit events and potentially remove stale requests
  if (peer.didConnect) {
    if (this.state !== 'disconnected') {
      debug(this.id + ' lost downstream connection to ' + peer.id)
    }

    this.emit('peerdisconnect', peer)
  } else {
    if (peer.requestWithdrawn) {
      debug(this.id + ' saw request withdrawn by ' + peer.id)
    } else {
      debug(this.id + ' removing stale request by ' + peer.id)
      this._requestsRef.child(peer.requestId).remove()
    }
  }

  this._reviewRequests()
}

Node.prototype._onmaskupdate = function (evt) {
  this._mask = evt.data

  debug(this.id + ' set mask to ' + this._mask)

  // oops we made a circle, fix that
  if (this.downstream[this._mask]) {
    debug(this.id + ' destroying accidental circle back to ' + this._mask)
    this.downstream[this._mask].destroy()
  }

  for (var i in this.downstream) {
    try {
      this.downstream[i].notifications.send(this._mask)
    } catch (err) {
      // this would only happen if the peer was in
      // the process of closing so we don't care
    }
  }
}

Node.prototype._reviewRequests = function () {
  if (this.state === 'connected' && Object.keys(this.downstream).length < this.config.K) {
    this._requestsRef.off('child_added', this._onrequest)
    this._requestsRef.on('child_added', this._onrequest)
  }
}
<|endoftext|>


<commit_before>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function () {

    'use strict';

    /**
     * @module
     *
     * @description
     * Main stockmanagement module.
     */
    angular.module('stockmanagement', [
        'ngResource',
        'ui.router',
        'openlmis-urls',
        'openlmis-auth',
        'openlmis-i18n',
        'openlmis-modal',
        'openlmis-table',
        'openlmis-pagination',
        'openlmis-rights',
        'openlmis-date',
        'openlmis-main-state',
    ]);

})();
<commit_msg>OLMIS-4055: removed trailing coma<commit_after>/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright © 2017 VillageReach
 *
 * This program is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Affero General Public License as published by the Free Software Foundation, either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details. You should have received a copy of
 * the GNU Affero General Public License along with this program. If not, see
 * http://www.gnu.org/licenses.  For additional information contact info@OpenLMIS.org.
 */

(function () {

    'use strict';

    /**
     * @module
     *
     * @description
     * Main stockmanagement module.
     */
    angular.module('stockmanagement', [
        'ngResource',
        'ui.router',
        'openlmis-urls',
        'openlmis-auth',
        'openlmis-i18n',
        'openlmis-modal',
        'openlmis-table',
        'openlmis-pagination',
        'openlmis-rights',
        'openlmis-date',
        'openlmis-main-state'
    ]);

})();
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var JekyllInuitGenerator = module.exports = function JekyllInuitGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(JekyllInuitGenerator, yeoman.generators.Base);

JekyllInuitGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    type: 'input',
    name: 'appname',
    message: 'What name shall we give your project?',
    default: this.appname
  }, {
    type: 'input',
    name: 'description',
    message: 'How would you summarise your project?',
    default: ''
  }, {
    type: 'input',
    name: 'authorName',
    message: 'What is your name?',
    default: ''
  }, {
    type: 'input',
    name: 'authorGithub',
    message: 'What is your GitHub username?',
    default: ''
  }, {
    type: 'input',
    name: 'authorTwitter',
    message: 'What is your twitter handle?',
    default: ''
  }, {
    type: 'input',
    name: 'authorEmail',
    message: 'What is your Email?',
    default: ''
  }];

  this.prompt(prompts, function (props) {
    this.appname = props.appname;
    this.description = props.description;
    this.authorName = props.authorName;
    this.authorGithub = props.authorGithub;
    this.authorTwitter = props.authorTwitter;
    this.authorEmail = props.authorEmail;

    cb();
  }.bind(this));
};

JekyllInuitGenerator.prototype.app = function app() {
  // copy directories
  this.directory('_layouts', '_layouts');
  this.directory('_posts', '_posts');
  this.directory('css', 'css');

  // interpolated file contents
  this.template('_config.yml', 'config.yml');
  this.template('_package.json', 'package.json');

  // straight copies of files
  this.copy('_config.yml', '_config.yml');
  this.copy('config.rb', 'config.rb');
  this.copy('favicon.ico', 'favicon.ico');
  this.copy('gitignore', '.gitignore');
  this.copy('Gruntfile.js', 'Gruntfile.js');
  this.copy('index.html', 'index.html');
  this.copy('jshintrc', '.jshintrc');
  this.copy('README.md', 'README.md');
};
<commit_msg>Remove duplicate Jekyll config.<commit_after>'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');

var JekyllInuitGenerator = module.exports = function JekyllInuitGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(JekyllInuitGenerator, yeoman.generators.Base);

JekyllInuitGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    type: 'input',
    name: 'appname',
    message: 'What name shall we give your project?',
    default: this.appname
  }, {
    type: 'input',
    name: 'description',
    message: 'How would you summarise your project?',
    default: ''
  }, {
    type: 'input',
    name: 'authorName',
    message: 'What is your name?',
    default: ''
  }, {
    type: 'input',
    name: 'authorGithub',
    message: 'What is your GitHub username?',
    default: ''
  }, {
    type: 'input',
    name: 'authorTwitter',
    message: 'What is your twitter handle?',
    default: ''
  }, {
    type: 'input',
    name: 'authorEmail',
    message: 'What is your Email?',
    default: ''
  }];

  this.prompt(prompts, function (props) {
    this.appname = props.appname;
    this.description = props.description;
    this.authorName = props.authorName;
    this.authorGithub = props.authorGithub;
    this.authorTwitter = props.authorTwitter;
    this.authorEmail = props.authorEmail;

    cb();
  }.bind(this));
};

JekyllInuitGenerator.prototype.app = function app() {
  // copy directories
  this.directory('_layouts', '_layouts');
  this.directory('_posts', '_posts');
  this.directory('css', 'css');

  // interpolated file contents
  this.template('_config.yml', 'config.yml');
  this.template('_package.json', 'package.json');

  // straight copies of files
  this.copy('config.rb', 'config.rb');
  this.copy('favicon.ico', 'favicon.ico');
  this.copy('gitignore', '.gitignore');
  this.copy('Gruntfile.js', 'Gruntfile.js');
  this.copy('index.html', 'index.html');
  this.copy('jshintrc', '.jshintrc');
  this.copy('README.md', 'README.md');
};
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

import * as Actions from '../Actions.js';
import CounterStore from '../stores/CounterStore.js';

const buttonStyle = {
  margin: '10px'
};

class Counter extends Component {

  constructor(props) {
    super(props);

    this.onChange = this.onChange.bind(this);
    this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
    this.onClickDecrementButton = this.onClickDecrementButton.bind(this);

    this.state = {
      count: CounterStore.getCounterValues()[props.caption]
    }

  }

  shouldComponentUpdate(nextProps, nextState) {
    return (nextProps.caption !== this.props.caption) ||
           (nextState.count !== this.state.count);
  }

  componentDidMount() {
    CounterStore.addChangeListener(this.onChange);
  }

  componentWillUnmount() {
    CounterStore.removeChangeListener(this.onChange);
  }

  onChange() {
    const newCount = CounterStore.getCounterValues()[this.props.caption];
    this.setState({count: newCount});
  }

  onClickIncrementButton() {
    Actions.increment(this.props.caption);
  }

  onClickDecrementButton() {
    Actions.decrement(this.props.caption);
  }

  render() {
    const {caption} = this.props;
    return (

        <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button>
        <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button>
        {caption} count: {this.state.count}

    );
  }
}

Counter.propTypes = {
  caption: PropTypes.string.isRequired,
  initValue: PropTypes.number,
  onUpdate: PropTypes.func
};

Counter.defaultProps = {
  initValue: 0,
  onUpdate: f => f //什么都不做的函数
};

export default Counter;

<commit_msg>remove redundant initValue prop<commit_after>import React, { Component, PropTypes } from 'react';

import * as Actions from '../Actions.js';
import CounterStore from '../stores/CounterStore.js';

const buttonStyle = {
  margin: '10px'
};

class Counter extends Component {

  constructor(props) {
    super(props);

    this.onChange = this.onChange.bind(this);
    this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
    this.onClickDecrementButton = this.onClickDecrementButton.bind(this);

    this.state = {
      count: CounterStore.getCounterValues()[props.caption]
    }

  }

  shouldComponentUpdate(nextProps, nextState) {
    return (nextProps.caption !== this.props.caption) ||
           (nextState.count !== this.state.count);
  }

  componentDidMount() {
    CounterStore.addChangeListener(this.onChange);
  }

  componentWillUnmount() {
    CounterStore.removeChangeListener(this.onChange);
  }

  onChange() {
    const newCount = CounterStore.getCounterValues()[this.props.caption];
    this.setState({count: newCount});
  }

  onClickIncrementButton() {
    Actions.increment(this.props.caption);
  }

  onClickDecrementButton() {
    Actions.decrement(this.props.caption);
  }

  render() {
    const {caption} = this.props;
    return (

        <button style={buttonStyle} onClick={this.onClickIncrementButton}>+</button>
        <button style={buttonStyle} onClick={this.onClickDecrementButton}>-</button>
        {caption} count: {this.state.count}

    );
  }
}

Counter.propTypes = {
  caption: PropTypes.string.isRequired,
  onUpdate: PropTypes.func
};

Counter.defaultProps = {
  onUpdate: f => f //什么都不做的函数
};

export default Counter;

<|endoftext|>


<commit_before>'use strict';
var fs = require('fs');
var util = require('util');
var path = require('path');
var fs = require('fs');
var yeoman = require('yeoman-generator');
var exec = require('child_process').exec;
var chalk = require('chalk');

var MaryoGenerator = module.exports = function MaryoGenerator(args, options, config) {
    yeoman.generators.Base.apply(this, arguments);

    this.on('end', function () {
        this.installDependencies({ skipInstall: options['skip-install'] });
    });

    this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
}

util.inherits(MaryoGenerator, yeoman.generators.Base);

MaryoGenerator.prototype.askFor = function askFor() {
    var cb = this.async();

    // Generate from a config file or prompt the user.
    if (this.options['config']) {
        var path = this.options['config'];
        if (path.substr(0,1) === '~') {
            path = process.env.HOME + path.substr(1);
        }

        fs.readFile(path, function (err, data) {
            var config = JSON.parse(data);

            this.styleFormat = config.styleFormat;
            this.templateFormat = config.templateFormat;
            this.testFramework = config.testFramework;
            this.includeBootstrap = config.includeBootstrap;

            cb();
        }.bind(this));
    } else {
        var styleFormat = ['css', 'sass', 'less'],
            templateFormat = ['_', 'dust'],
            testFramework = ['none', 'jasmine', 'mocha'],
            prompts = [{
                name: 'styleFormat',
                message: 'Which style format would you like to use ('+styleFormat.join("/")+')?',
                choices: styleFormat
            },
            {
                name: 'templateFormat',
                message: 'Which template library would you like to use ('+templateFormat.join("/")+')?',
                choices: templateFormat
            },
            {
                name: 'testFramework',
                message: 'Which test framework would you like to use ('+testFramework.join("/")+')?',
                choices: testFramework
            },
            {
                name: 'includeBootstrap',
                message: 'Would you like to include Twitter Bootstrap (y)?',
                type: 'confirm'
            }];

        // Be polite
        console.log(
            '\n     _-----_' +
            '\n    |       |' +
            '\n    |' + chalk.red('--(o)--') + '|   .--------------------------.' +
            '\n   `---------´  |    ' + chalk.yellow.bold('Welcome to Yeoman') + ',    |' +
            '\n    ' + chalk.yellow('(') + ' _' + chalk.yellow('´U`') + '_ ' + chalk.yellow(')') + '   |   ' + chalk.yellow.bold('ladies and gentlemen!') + '  |' +
            '\n    /___A___\\   \'__________________________\'' +
            '\n     ' + chalk.yellow('|  ~  |') +
            '\n   __' + chalk.yellow('\'.___.\'') + '__' +
            '\n ´   ' + chalk.red('`  |') + '° ' + chalk.red('´ Y') + ' `\n' +
            'Let\'s dance with Marionette.\n\n'
        );

        // Prompt the user and handle the user responses
        this.prompt(prompts, function (err, props) {
            this.styleFormat = props.styleFormat || styleFormat[0];
            this.templateFormat = props.templateFormat || templateFormat[0];
            this.testFramework = props.testFramework || testFramework[0];
            this.includeBootstrap = props.includeBootstrap;

            cb();
        }.bind(this));
    }
}

MaryoGenerator.prototype.app = function app () {
    var self = this;

    // TODO: Set up user input to configure server. Template
    // has access to this object.
    this.connect = {
        options: {
            port: 8888
        }
    };

    // Create the application directory structure
    this.mkdir('app');
    this.mkdir('app/scripts');
    this.mkdir('app/scripts/collections');
    this.mkdir('app/scripts/models');
    this.mkdir('app/scripts/views');
    this.mkdir('app/scripts/routers');
    this.mkdir('app/scripts/templates');
    this.mkdir('app/scripts/layouts');
    this.mkdir('app/scripts/regions');
    this.mkdir('app/scripts/test');
    this.mkdir('app/styles');
    this.mkdir('app/images');

    // Copy files
    this.copy('app.js', 'app/scripts/app.js');
    this.copy('main.js', 'app/scripts/main.js');
    this.copy('index.html', 'app/index.html');
    this.copy('editorconfig', '.editorconfig');
    this.copy('jshintrc', '.jshintrc');
    this.copy('gitattributes', '.gitattributes');
    this.copy('gitignore', '.gitignore');
    this.copy('bowerrc', '.bowerrc');

    // TODO: Add in a base test file and test runner

    // Template files dependent on options
    this.template('_config.js', 'app/scripts/config.js');
    this.template('_package.json', 'package.json');
    this.template('_bower.json', 'bower.json');
    this.template('_Gruntfile.js', 'Gruntfile.js');
}

MaryoGenerator.prototype.h5bp = function h5bp () {
    var ext = this.styleFormat,
        cb = this.async();

    this.remote('h5bp', 'html5-boilerplate', function (err, remote) {
        remote.copy('./css/normalize.css', 'app/styles/normalize.css');
        remote.copy('./css/main.css', 'app/styles/main.css');
        cb();
    }.bind(this));
}
<commit_msg>Addresses further issues in #2<commit_after>'use strict';
var fs = require('fs');
var util = require('util');
var path = require('path');
var fs = require('fs');
var yeoman = require('yeoman-generator');
var exec = require('child_process').exec;
var chalk = require('chalk');

var MaryoGenerator = module.exports = function MaryoGenerator(args, options, config) {
    yeoman.generators.Base.apply(this, arguments);

    this.on('end', function () {
        this.installDependencies({ skipInstall: options['skip-install'] });
    });

    this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
}

util.inherits(MaryoGenerator, yeoman.generators.Base);

MaryoGenerator.prototype.askFor = function askFor() {
    var cb = this.async();

    // Generate from a config file or prompt the user.
    if (this.options['config']) {
        var path = this.options['config'];
        if (path.substr(0,1) === '~') {
            path = process.env.HOME + path.substr(1);
        }

        fs.readFile(path, function (err, data) {
            var config = JSON.parse(data);

            this.styleFormat = config.styleFormat;
            this.templateFormat = config.templateFormat;
            this.testFramework = config.testFramework;
            this.includeBootstrap = config.includeBootstrap;

            cb();
        }.bind(this));
    } else {
        var styleFormat = ['css', 'sass', 'less'],
            templateFormat = ['_', 'dust'],
            testFramework = ['none', 'jasmine', 'mocha'],
            prompts = [{
                name: 'styleFormat',
                message: 'Which style format would you like to use ('+styleFormat.join("/")+')?',
                choices: styleFormat
            },
            {
                name: 'templateFormat',
                message: 'Which template library would you like to use ('+templateFormat.join("/")+')?',
                choices: templateFormat
            },
            {
                name: 'testFramework',
                message: 'Which test framework would you like to use ('+testFramework.join("/")+')?',
                choices: testFramework
            },
            {
                name: 'includeBootstrap',
                message: 'Would you like to include Twitter Bootstrap (y)?',
                type: 'confirm'
            }];

        // Be polite
        console.log(
            '\n     _-----_' +
            '\n    |       |' +
            '\n    |' + chalk.red('--(o)--') + '|   .--------------------------.' +
            '\n   `---------´  |    ' + chalk.yellow.bold('Welcome to Yeoman') + ',    |' +
            '\n    ' + chalk.yellow('(') + ' _' + chalk.yellow('´U`') + '_ ' + chalk.yellow(')') + '   |   ' + chalk.yellow.bold('ladies and gentlemen!') + '  |' +
            '\n    /___A___\\   \'__________________________\'' +
            '\n     ' + chalk.yellow('|  ~  |') +
            '\n   __' + chalk.yellow('\'.___.\'') + '__' +
            '\n ´   ' + chalk.red('`  |') + '° ' + chalk.red('´ Y') + ' `\n' +
            'Let\'s dance with Marionette.\n\n'
        );

        // Prompt the user and handle the user responses
        this.prompt(prompts, function (props, err) {
            this.styleFormat = props.styleFormat || styleFormat[0];
            this.templateFormat = props.templateFormat || templateFormat[0];
            this.testFramework = props.testFramework || testFramework[0];
            this.includeBootstrap = props.includeBootstrap;

            cb();
        }.bind(this));
    }
}

MaryoGenerator.prototype.app = function app () {
    var self = this;

    // TODO: Set up user input to configure server. Template
    // has access to this object.
    this.connect = {
        options: {
            port: 8888
        }
    };

    // Create the application directory structure
    this.mkdir('app');
    this.mkdir('app/scripts');
    this.mkdir('app/scripts/collections');
    this.mkdir('app/scripts/models');
    this.mkdir('app/scripts/views');
    this.mkdir('app/scripts/routers');
    this.mkdir('app/scripts/templates');
    this.mkdir('app/scripts/layouts');
    this.mkdir('app/scripts/regions');
    this.mkdir('app/scripts/test');
    this.mkdir('app/styles');
    this.mkdir('app/images');

    // Copy files
    this.copy('app.js', 'app/scripts/app.js');
    this.copy('main.js', 'app/scripts/main.js');
    this.copy('index.html', 'app/index.html');
    this.copy('editorconfig', '.editorconfig');
    this.copy('jshintrc', '.jshintrc');
    this.copy('gitattributes', '.gitattributes');
    this.copy('gitignore', '.gitignore');
    this.copy('bowerrc', '.bowerrc');

    // TODO: Add in a base test file and test runner

    // Template files dependent on options
    this.template('_config.js', 'app/scripts/config.js');
    this.template('_package.json', 'package.json');
    this.template('_bower.json', 'bower.json');
    this.template('_Gruntfile.js', 'Gruntfile.js');
}

MaryoGenerator.prototype.h5bp = function h5bp () {
    var ext = this.styleFormat,
        cb = this.async();

    this.remote('h5bp', 'html5-boilerplate', function (err, remote) {
        remote.copy('./css/normalize.css', 'app/styles/normalize.css');
        remote.copy('./css/main.css', 'app/styles/main.css');
        cb();
    }.bind(this));
}
<|endoftext|>


<commit_before>/**
 * @license Apache-2.0
 * Copyright 2020 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview
 * Crawl over all test/com/google/.../runtime_tests/*_test.html files and
 * execute them in a JSDOM context, fail the test if any do not succeed.
 */

const { JSDOM, VirtualConsole } = require('jsdom');
const { fail } = require('assert');
const chalk = require('chalk');
const fs = require('fs');
const FutureEvent = require('future-event');
const glob = require('glob');
const path = require('path');

const TEST_FILES = glob.sync(path.resolve(
    __dirname,
    '../../test/com/google/javascript/jscomp/runtime_tests/**/build/*_test.html',
));

describe('Runtime tests', () => {
  for (const testUrl of TEST_FILES) {
    const logs = [];
    const passed = /PASSED/i;
    const failed = /FAILED/i;

    const allLogs = () => logs.join('\n');
    const chalkMsg = (msg) => {
      const isPass = passed.test(msg);
      const isFail = failed.test(msg);

      if (isPass || isFail) {
        return msg.replace(
            passed, chalk.green('PASSED'),
        ).replace(
            failed, chalk.red('FAILED'),
        );
      } else return msg;
    };

    const testName = path.basename(testUrl);
    const TestIsFinished = new FutureEvent();
    const virtualConsole = new VirtualConsole()
        .on('log', (msg) => {
          logs.push(chalkMsg(msg));
          if (/Tests complete/i.test(msg)) TestIsFinished.ready(allLogs());
          else if (/Tests failed/i.test(msg)) TestIsFinished.cancel(allLogs());
        });

    const TEST_DOC = fs.readFileSync(
        path.resolve(
            __dirname,
            '../../',
            testUrl,
        ),
        'utf-8',
    );

    it(`should pass test suite ${path.basename(testUrl)}`, async () => {
      new JSDOM(TEST_DOC, {
        /**
         * This does not actually run a server of any kind, it only informs the
         * DOM what to put in `window.location.origin`. By default, this is
         * `null`, and any non-HTTPS URL field here will throw an error in the
         * test suite due to unsafe URL.
         */
        url: 'https://localhost:42',
        /**
         * This flag will allow the execution of `<script>` tags that are added
         * to the DOM after the `onload` event, i.e., those that are added by
         * `goog.module` and `goog.require`.
         */
        runScripts: 'dangerously',
        /**
         * Pipe `console.log` to our virtual console.
         */
        virtualConsole,
      });

      try {
        await TestIsFinished;
      } catch (e) {
        fail(`Failed test in suite ${testName}: \n${e}\n`);
      }
      console.log(`Passed all tests in suite ${testName}`);
    });
  }
});
<commit_msg>Formatting update<commit_after>/**
 * @license Apache-2.0
 * Copyright 2020 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview
 * Crawl over all test/com/google/.../runtime_tests/*_test.html files and
 * execute them in a JSDOM context, fail the test if any do not succeed.
 */

const { JSDOM, VirtualConsole } = require('jsdom');
const { fail } = require('assert');
const chalk = require('chalk');
const fs = require('fs');
const FutureEvent = require('future-event');
const glob = require('glob');
const path = require('path');

const TEST_FILES = glob.sync(path.resolve(
    __dirname,
    '../../test/com/google/javascript/jscomp/'
    + 'runtime_tests/**/build/*_test.html',
));

describe('Runtime tests', () => {
  for (const testUrl of TEST_FILES) {
    const logs = [];
    const passed = /PASSED/i;
    const failed = /FAILED/i;

    const allLogs = () => logs.join('\n');
    const chalkMsg = (msg) => {
      const isPass = passed.test(msg);
      const isFail = failed.test(msg);

      if (isPass || isFail) {
        return msg.replace(
            passed, chalk.green('PASSED'),
        ).replace(
            failed, chalk.red('FAILED'),
        );
      } else return msg;
    };

    const testName = path.basename(testUrl);
    const TestIsFinished = new FutureEvent();
    const virtualConsole = new VirtualConsole()
        .on('log', (msg) => {
          logs.push(chalkMsg(msg));
          if (/Tests complete/i.test(msg)) TestIsFinished.ready(allLogs());
          else if (/Tests failed/i.test(msg)) TestIsFinished.cancel(allLogs());
        });

    const TEST_DOC = fs.readFileSync(
        path.resolve(
            __dirname,
            '../../',
            testUrl,
        ),
        'utf-8',
    );

    it(`should pass test suite ${path.basename(testUrl)}`, async () => {
      new JSDOM(TEST_DOC, {
        /**
         * This does not actually run a server of any kind, it only informs the
         * DOM what to put in `window.location.origin`. By default, this is
         * `null`, and any non-HTTPS URL field here will throw an error in the
         * test suite due to unsafe URL.
         */
        url: 'https://localhost:42',
        /**
         * This flag will allow the execution of `<script>` tags that are added
         * to the DOM after the `onload` event, i.e., those that are added by
         * `goog.module` and `goog.require`.
         */
        runScripts: 'dangerously',
        /**
         * Pipe `console.log` to our virtual console.
         */
        virtualConsole,
      });

      try {
        await TestIsFinished;
      } catch (e) {
        fail(`Failed test in suite ${testName}: \n${e}\n`);
      }
      console.log(`Passed all tests in suite ${testName}`);
    });
  }
});
<|endoftext|>