<commit_before>OBJS = ['deployment', 'image', 'networkTemplate', 'network', 'networkSliver', 'networkDeployment', 'node', 'service', 'site', 'slice', 'sliceDeployment', 'slicePrivilege', 'sliver', 'user', 'sliceRole', 'userDeployment'];
NAV_OBJS = ['deployment', 'site', 'slice', 'user'];

REWRITES = {"/admin/core/deployment/": "#deployments",
            "/admin/core/site/" : "#sites",
            "/admin/core/slice/" : "#slices",
            "/admin/core/user/" : "#users"};

XOSAdminApp = new XOSApplication({
    logTableId: "#logTable",
    statusMsgId: "#statusMsg",
    hideTabsByDefault: true
});

XOSAdminApp.addRegions({
    navigation: "#navigationPanel",

    detail: "#detail",
    linkedObjs1: "#linkedObjs1",
    linkedObjs2: "#linkedObjs2",
    linkedObjs3: "#linkedObjs3",
    linkedObjs4: "#linkedObjs4",

    addChildDetail: "#xos-addchild-detail",

    rightButtonPanel: "#rightButtonPanel"
});

XOSAdminApp.navigate = function(what, modelName, modelId) {
    console.log("XOSAsminApp.navigate");
    collection_name = modelName + "s";
    if (what=="list") {
        XOSAdminApp.Router.navigate(collection_name, {trigger: true})
    } else if (what=="detail") {
        XOSAdminApp.Router.navigate(collection_name + "/" + modelId, {trigger: true})
    } else if (what=="add") {
        XOSAdminApp.Router.navigate("add" + firstCharUpper(modelName), {trigger: true, force: true})
    }
}

ICON_CLASSES = {home: "icon-home", deployments: "icon-deployment", sites: "icon-site", slices: "icon-slice", users: "icon-user"};

XOSAdminApp.updateNavigationPanel = function() {
    buttonTemplate=$("#xos-navbutton").html();
    assert(buttonTemplate != undefined, "buttonTemplate is undefined");
    html="

";
    for (var index in NAV_OBJS) {
        name = NAV_OBJS[index];
        collection_name = name+"s";
        nav_url = "#" + collection_name;
        id = "nav-"+name;
        icon_class = ICON_CLASSES[collection_name] || "icon-cog";

        html = html + _.template(buttonTemplate, {name: collection_name, router: "XOSAdminApp.Router", routeUrl: nav_url, iconClass: icon_class});
    }

    html = html + "
";

    $("#navigationPanel").html(html);
};

XOSAdminApp.buildViews = function() {
     genericAddChildClass = XOSDetailView.extend({template: "#xos-add-template",
                                                        app: XOSAdminApp});
     XOSAdminApp["genericAddChildView"] = genericAddChildClass;

     genericDetailClass = XOSDetailView.extend({template: "#xos-detail-template",
                                                           app: XOSAdminApp});
     XOSAdminApp["genericDetailView"] = genericDetailClass;

     genericItemViewClass = XOSItemView.extend({template: "#xos-listitem-template",
                                                app: XOSAdminApp});
     XOSAdminApp["genericItemView"] = genericItemViewClass;

     genericListViewClass = XOSListView.extend({template: "#xos-list-template",
                                                app: XOSAdminApp});
     XOSAdminApp["genericListView"] = genericListViewClass;

     for (var index in OBJS) {
         name = OBJS[index];
         tr_template = '#xosAdmin-' + name + '-listitem-template';
         table_template = '#xosAdmin-' + name + '-list-template';
         detail_template = '#xosAdmin-' + name + '-detail-template';
         add_child_template = '#xosAdmin-' + name + '-add-child-template';
         collection_name = name + "s";
         region_name = name + "List";

         if ($(detail_template).length) {
             detailClass = XOSDetailView.extend({
                template: detail_template,
                app: XOSAdminApp,
             });
         } else {
             detailClass = genericDetailClass;
         }
         XOSAdminApp[collection_name + "DetailView"] = detailClass;

         if ($(add_child_template).length) {
             addClass = XOSDetailView.extend({
                template: add_child_template,
                app: XOSAdminApp,
             });
         } else {
             addClass = genericAddChildClass;
         }
         XOSAdminApp[collection_name + "AddChildView"] = addClass;

         if ($(tr_template).length) {
             itemViewClass = XOSItemView.extend({
                 template: tr_template,
                 app: XOSAdminApp,
             });
         } else {
             itemViewClass = genericItemViewClass;
         }

         if ($(table_template).length) {
             listViewClass = XOSListView.extend({
                 childView: itemViewClass,
                 template: table_template,
                 collection: xos[collection_name],
                 title: name + "s",
                 app: XOSAdminApp,
             });
         } else {
             listViewClass = genericListViewClass.extend( { childView: itemViewClass,
                                                            collection: xos[collection_name],
                                                            title: name + "s",
                                                           } );
         }

         XOSAdminApp[collection_name + "ListView"] = listViewClass;

         xos[collection_name].fetch(); //startPolling();
     }
};

XOSAdminApp.initRouter = function() {
    router = XOSRouter;
    var api = {};
    var routes = {};

    for (var index in OBJS) {
        name = OBJS[index];
        collection_name = name + "s";
        nav_url = collection_name;
        api_command = "list" + firstCharUpper(collection_name);
        listViewName = collection_name + "ListView";
        detailViewName = collection_name + "DetailView";
        addChildViewName = collection_name + "AddChildView";

        api[api_command] = XOSAdminApp.createListHandler(listViewName, collection_name, "detail", collection_name);
        routes[nav_url] = api_command;

        nav_url = collection_name + "/:id";
        api_command = "detail" + firstCharUpper(collection_name);

        api[api_command] = XOSAdminApp.createDetailHandler(detailViewName, collection_name, "detail", name);
        routes[nav_url] = api_command;

        nav_url = "add" + firstCharUpper(name);
        api_command = "add" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createAddHandler(detailViewName, collection_name, "detail", name);
        routes[nav_url] = api_command;

        nav_url = "addChild" + firstCharUpper(name) + "/:parentModel/:parentField/:parentId";
        api_command = "addChild" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createAddChildHandler(addChildViewName, collection_name);
        routes[nav_url] = api_command;

        nav_url = "delete" + firstCharUpper(name) + "/:id";
        api_command = "delete" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createDeleteHandler(collection_name, name);
        routes[nav_url] = api_command;
    };

    XOSAdminApp.Router = new router({ appRoutes: routes, controller: api });
};

/* rewriteLinks

   Rewrite the links in the suit navbar from django-links to marionette
   links. This let's us intercept the navbar and make it function within
   this view rather than jumping back out to a django view.
*/

XOSAdminApp.rewriteLinks = function () {
    $("a").each(function() {
        href=$(this).attr("href");
        rewrite_href=REWRITES[href];
        if (rewrite_href) {
            $(this).attr("href", rewrite_href);
        }
    });
};

XOSAdminApp.startNavigation = function() {
    Backbone.history.start();
    XOSAdminApp.navigationStarted = true;
}

XOSAdminApp.collectionLoadChange = function() {
    stats = xos.getCollectionStatus();

    if (!XOSAdminApp.navigationStarted) {
        if (stats["isLoaded"] + stats["failedLoad"] >= stats["startedLoad"]) {
            XOSAdminApp.startNavigation();
        } else {
            $("#detail").html("
Loading...

");
            $("#xos-startup-progress").progressbar({value: stats["completedLoad"], max: stats["startedLoad"]});
        }
    }
};

XOSAdminApp.on("start", function() {
     XOSAdminApp.buildViews();

     XOSAdminApp.initRouter();

     XOSAdminApp.updateNavigationPanel();

     XOSAdminApp.rewriteLinks();

     // fire it once to initially show the progress bar
     XOSAdminApp.collectionLoadChange();

     // fire it each time the collection load status is updated
     Backbone.on("xoslib:collectionLoadChange", XOSAdminApp.collectionLoadChange);
});

$(document).ready(function(){
    XOSAdminApp.start();
});

<commit_msg>replace the CompositeView list with the DataTable list<commit_after>OBJS = ['deployment', 'image', 'networkTemplate', 'network', 'networkSliver', 'networkDeployment', 'node', 'service', 'site', 'slice', 'sliceDeployment', 'slicePrivilege', 'sliver', 'user', 'sliceRole', 'userDeployment'];
NAV_OBJS = ['deployment', 'site', 'slice', 'user'];

REWRITES = {"/admin/core/deployment/": "#deployments",
            "/admin/core/site/" : "#sites",
            "/admin/core/slice/" : "#slices",
            "/admin/core/user/" : "#users"};

XOSAdminApp = new XOSApplication({
    logTableId: "#logTable",
    statusMsgId: "#statusMsg",
    hideTabsByDefault: true
});

XOSAdminApp.addRegions({
    navigation: "#navigationPanel",

    detail: "#detail",
    linkedObjs1: "#linkedObjs1",
    linkedObjs2: "#linkedObjs2",
    linkedObjs3: "#linkedObjs3",
    linkedObjs4: "#linkedObjs4",

    addChildDetail: "#xos-addchild-detail",

    rightButtonPanel: "#rightButtonPanel"
});

XOSAdminApp.navigate = function(what, modelName, modelId) {
    console.log("XOSAsminApp.navigate");
    collection_name = modelName + "s";
    if (what=="list") {
        XOSAdminApp.Router.navigate(collection_name, {trigger: true})
    } else if (what=="detail") {
        XOSAdminApp.Router.navigate(collection_name + "/" + modelId, {trigger: true})
    } else if (what=="add") {
        XOSAdminApp.Router.navigate("add" + firstCharUpper(modelName), {trigger: true, force: true})
    }
}

ICON_CLASSES = {home: "icon-home", deployments: "icon-deployment", sites: "icon-site", slices: "icon-slice", users: "icon-user"};

XOSAdminApp.updateNavigationPanel = function() {
    buttonTemplate=$("#xos-navbutton").html();
    assert(buttonTemplate != undefined, "buttonTemplate is undefined");
    html="

";
    for (var index in NAV_OBJS) {
        name = NAV_OBJS[index];
        collection_name = name+"s";
        nav_url = "#" + collection_name;
        id = "nav-"+name;
        icon_class = ICON_CLASSES[collection_name] || "icon-cog";

        html = html + _.template(buttonTemplate, {name: collection_name, router: "XOSAdminApp.Router", routeUrl: nav_url, iconClass: icon_class});
    }

    html = html + "
";

    $("#navigationPanel").html(html);
};

XOSAdminApp.buildViews = function() {
     genericAddChildClass = XOSDetailView.extend({template: "#xos-add-template",
                                                        app: XOSAdminApp});
     XOSAdminApp["genericAddChildView"] = genericAddChildClass;

     genericDetailClass = XOSDetailView.extend({template: "#xos-detail-template",
                                                           app: XOSAdminApp});
     XOSAdminApp["genericDetailView"] = genericDetailClass;

     genericItemViewClass = XOSItemView.extend({template: "#xos-listitem-template",
                                                app: XOSAdminApp});
     XOSAdminApp["genericItemView"] = genericItemViewClass;

     //genericListViewClass = XOSListView.extend({template: "#xos-list-template",
     //                                           app: XOSAdminApp});

     genericListViewClass = XOSDataTableView.extend({template: "#xos-list-template", app: XOSAdminApp});
     XOSAdminApp["genericListView"] = genericListViewClass;

     for (var index in OBJS) {
         name = OBJS[index];
         tr_template = '#xosAdmin-' + name + '-listitem-template';
         table_template = '#xosAdmin-' + name + '-list-template';
         detail_template = '#xosAdmin-' + name + '-detail-template';
         add_child_template = '#xosAdmin-' + name + '-add-child-template';
         collection_name = name + "s";
         region_name = name + "List";

         if ($(detail_template).length) {
             detailClass = XOSDetailView.extend({
                template: detail_template,
                app: XOSAdminApp,
             });
         } else {
             detailClass = genericDetailClass;
         }
         XOSAdminApp[collection_name + "DetailView"] = detailClass;

         if ($(add_child_template).length) {
             addClass = XOSDetailView.extend({
                template: add_child_template,
                app: XOSAdminApp,
             });
         } else {
             addClass = genericAddChildClass;
         }
         XOSAdminApp[collection_name + "AddChildView"] = addClass;

         if ($(tr_template).length) {
             itemViewClass = XOSItemView.extend({
                 template: tr_template,
                 app: XOSAdminApp,
             });
         } else {
             itemViewClass = genericItemViewClass;
         }

         if ($(table_template).length) {
             listViewClass = XOSListView.extend({
                 childView: itemViewClass,
                 template: table_template,
                 collection: xos[collection_name],
                 title: name + "s",
                 app: XOSAdminApp,
             });
         } else {
             listViewClass = genericListViewClass.extend( { childView: itemViewClass,
                                                            collection: xos[collection_name],
                                                            title: name + "s",
                                                           } );
         }

         XOSAdminApp[collection_name + "ListView"] = listViewClass;

         xos[collection_name].fetch(); //startPolling();
     }
};

XOSAdminApp.initRouter = function() {
    router = XOSRouter;
    var api = {};
    var routes = {};

    for (var index in OBJS) {
        name = OBJS[index];
        collection_name = name + "s";
        nav_url = collection_name;
        api_command = "list" + firstCharUpper(collection_name);
        listViewName = collection_name + "ListView";
        detailViewName = collection_name + "DetailView";
        addChildViewName = collection_name + "AddChildView";

        api[api_command] = XOSAdminApp.createListHandler(listViewName, collection_name, "detail", collection_name);
        routes[nav_url] = api_command;

        nav_url = collection_name + "/:id";
        api_command = "detail" + firstCharUpper(collection_name);

        api[api_command] = XOSAdminApp.createDetailHandler(detailViewName, collection_name, "detail", name);
        routes[nav_url] = api_command;

        nav_url = "add" + firstCharUpper(name);
        api_command = "add" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createAddHandler(detailViewName, collection_name, "detail", name);
        routes[nav_url] = api_command;

        nav_url = "addChild" + firstCharUpper(name) + "/:parentModel/:parentField/:parentId";
        api_command = "addChild" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createAddChildHandler(addChildViewName, collection_name);
        routes[nav_url] = api_command;

        nav_url = "delete" + firstCharUpper(name) + "/:id";
        api_command = "delete" + firstCharUpper(name);
        api[api_command] = XOSAdminApp.createDeleteHandler(collection_name, name);
        routes[nav_url] = api_command;
    };

    XOSAdminApp.Router = new router({ appRoutes: routes, controller: api });
};

/* rewriteLinks

   Rewrite the links in the suit navbar from django-links to marionette
   links. This let's us intercept the navbar and make it function within
   this view rather than jumping back out to a django view.
*/

XOSAdminApp.rewriteLinks = function () {
    $("a").each(function() {
        href=$(this).attr("href");
        rewrite_href=REWRITES[href];
        if (rewrite_href) {
            $(this).attr("href", rewrite_href);
        }
    });
};

XOSAdminApp.startNavigation = function() {
    Backbone.history.start();
    XOSAdminApp.navigationStarted = true;
}

XOSAdminApp.collectionLoadChange = function() {
    stats = xos.getCollectionStatus();

    if (!XOSAdminApp.navigationStarted) {
        if (stats["isLoaded"] + stats["failedLoad"] >= stats["startedLoad"]) {
            XOSAdminApp.startNavigation();
        } else {
            $("#detail").html("
Loading...

");
            $("#xos-startup-progress").progressbar({value: stats["completedLoad"], max: stats["startedLoad"]});
        }
    }
};

XOSAdminApp.on("start", function() {
     XOSAdminApp.buildViews();

     XOSAdminApp.initRouter();

     XOSAdminApp.updateNavigationPanel();

     XOSAdminApp.rewriteLinks();

     // fire it once to initially show the progress bar
     XOSAdminApp.collectionLoadChange();

     // fire it each time the collection load status is updated
     Backbone.on("xoslib:collectionLoadChange", XOSAdminApp.collectionLoadChange);
});

$(document).ready(function(){
    XOSAdminApp.start();
});

<|endoftext|>


<commit_before>exports.run = async function (Elga, msg) {
    await msg.edit({ embed: {
        color: Elga.config.embedColor,
        author: { name: 'Rebooting...', icon_url: 'http://i.imgur.com/81nH7vJ.gif' }
    } });

    const res = await Elga.db.get('SELECT * FROM reboot');
    if (!res) {
        await Elga.db.run('INSERT INTO reboot (channelID, messageID, startTime) VALUES (?, ?, ?)', msg.channel.id, msg.id, Date.now());
    } else if (res) {
        await Elga.db.run('UPDATE reboot SET channelID = ?, messageID = ?, startTime = ?', msg.channel.id, msg.id, Date.now());
    }
    process.exit();
};

exports.boot = async function (Elga) {
    const res = await Elga.db.get('SELECT * FROM reboot LIMIT 1');
    if (!Elga.channels.get(res.channelID)) {
        return;
    }
    Elga.channels.get(res.channelID).fetchMessage(res.messageID).then(msg => {
        const tStamp = Date.now() - res.startTime > 1000 ? `${(Date.now() - res.startTime) / 1000}s` : `${Date.now() - res.startTime}ms`;
        msg.edit({ embed: {
            color: Elga.config.embedColor,
            description: 'Rebooted.',
            footer: { text: `Rebooted in ${tStamp}.` }
        } });
    }).catch(() => {});
};

exports.props = {
    name        : 'reboot',
    usage       : '{command}',
    aliases     : ['restart'],
    description : 'Reboots Elga.'
};
<commit_msg>Check for existence of res before continuing<commit_after>exports.run = async function (Elga, msg) {
    await msg.edit({ embed: {
        color: Elga.config.embedColor,
        author: { name: 'Rebooting...', icon_url: 'http://i.imgur.com/81nH7vJ.gif' }
    } });

    const res = await Elga.db.get('SELECT * FROM reboot');
    if (!res) {
        await Elga.db.run('INSERT INTO reboot (channelID, messageID, startTime) VALUES (?, ?, ?)', msg.channel.id, msg.id, Date.now());
    } else if (res) {
        await Elga.db.run('UPDATE reboot SET channelID = ?, messageID = ?, startTime = ?', msg.channel.id, msg.id, Date.now());
    }
    process.exit();
};

exports.boot = async function (Elga) {
    const res = await Elga.db.get('SELECT * FROM reboot LIMIT 1');
    if (!res || !Elga.channels.get(res.channelID)) {
        return;
    }
    Elga.channels.get(res.channelID).fetchMessage(res.messageID).then(msg => {
        const tStamp = Date.now() - res.startTime > 1000 ? `${(Date.now() - res.startTime) / 1000}s` : `${Date.now() - res.startTime}ms`;
        msg.edit({ embed: {
            color: Elga.config.embedColor,
            description: 'Rebooted.',
            footer: { text: `Rebooted in ${tStamp}.` }
        } });
    }).catch(() => {});
};

exports.props = {
    name        : 'reboot',
    usage       : '{command}',
    aliases     : ['restart'],
    description : 'Reboots Elga.'
};
<|endoftext|>


<commit_before>import React from 'react';
import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';
import { formatNumber } from 'common/format';
import AbilityTracker from 'parser/shared/modules/AbilityTracker';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import Events from 'parser/core/Events';
import SpellUsable from 'parser/shared/modules/SpellUsable';

const debug = false;

class CombustionSpellUsage extends Analyzer {
  static dependencies = {
    spellUsable: SpellUsable,
    abilityTracker: AbilityTracker,
  };

  badCastsStarted = 0;
  badCastsCompleted = 0;

  constructor(...args) {
    super(...args);
    this.hasBlasterMaster = this.selectedCombatant.hasTrait(SPELLS.BLASTER_MASTER.id);
    this.hasPhoenixFlames = this.selectedCombatant.hasTalent(SPELLS.PHOENIX_FLAMES_TALENT.id);
    this.addEventListener(Events.begincast.by(SELECTED_PLAYER).spell([SPELLS.FIREBALL,SPELLS.SCORCH]), this.checkChargeCounts);
    this.addEventListener(Events.cast.by(SELECTED_PLAYER).spell([SPELLS.FIREBALL,SPELLS.SCORCH]), this.checkChargeCounts);
  }

  //Check to see if the player cast (or started to cast) Fireball or Scorch during Combustion while they had Fire Blast or Phoenix Flames charges available.
  checkChargeCounts(event) {
    const hasCombustion = this.selectedCombatant.hasBuff(SPELLS.COMBUSTION.id);
    const fireBlastCharges = this.spellUsable.chargesAvailable(SPELLS.FIRE_BLAST.id);
    const phoenixFlamesCharges = (this.spellUsable.chargesAvailable(SPELLS.PHOENIX_FLAMES_TALENT.id) || 0);
    //If the player has the Blaster Master trait, it is acceptable to cast Scorch during Combustion
    if (!hasCombustion || (this.hasBlasterMaster && event.ability.guid === SPELLS.SCORCH.id)) {
      return;
    }

    if (event.type === "cast" && (fireBlastCharges > 0 || phoenixFlamesCharges > 0)) {
      this.badCastsCompleted += 1;
      this.lastCastEvent.meta = this.lastCastEvent.meta || {};
      this.lastCastEvent.meta.isInefficientCast = true;
      this.lastCastEvent.meta.inefficientCastReason = `This spell was cast during Combustion while an instant cast ability like Fire Blast ${this.hasPhoenixFlames ? 'or Phoenix Flames' : '' } was available. Make sure you are using your instant abilities first before hard casting Fireball ${this.hasBlasterMaster ? 'or Scorch' : '' }. `;
      debug && this.log("Cast completed with instants available");
    }

    if (event.type === "begincast" && (fireBlastCharges > 0 || phoenixFlamesCharges > 0)) {
      this.badCastsStarted += 1;
      debug && this.log("Cast started with instants available");
    }
  }

  get castsWithInstantsPerCombustion() {
    return this.badCastsStarted / this.abilityTracker.getAbility(SPELLS.COMBUSTION.id).casts;
  }

  get suggestionThresholds() {
    return {
      actual: this.castsWithInstantsPerCombustion,
      isGreaterThan: {
        minor: 0,
        average: 1,
        major: 2,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    when(this.suggestionThresholds)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(<>You started to cast <SpellLink id={SPELLS.FIREBALL.id} /> {!this.hasBlasterMaster ? <> or <SpellLink id={SPELLS.SCORCH.id} /></> : '' } {this.badCastsStarted} times ({this.castsWithInstantsPerCombustion.toFixed(2)} per Combustion), and completed {this.badCastsCompleted} casts, while you had charges of <SpellLink id={SPELLS.FIRE_BLAST.id} /> {this.hasPhoenixFlames ? <> or <SpellLink id={SPELLS.PHOENIX_FLAMES_TALENT.id} /> </> : '' } available. Make sure you are using up all of your charges of Fire Blast {this.hasPhoenixFlames ? ' and Phoenix Flames' : '' } before using Fireball {!this.hasBlasterMaster ? 'or Scorch' : '' } during Combustion.</>)
          .icon(SPELLS.COMBUSTION.icon)
          .actual(`${this.castsWithInstantsPerCombustion.toFixed(2)} Casts Per Combustion`)
          .recommended(`${formatNumber(recommended)} is recommended`);
      });
  }
}
export default CombustionSpellUsage;
<commit_msg>Update CombustionSpellUsage.js<commit_after>import React from 'react';
import SPELLS from 'common/SPELLS';
import SpellLink from 'common/SpellLink';
import { formatNumber } from 'common/format';
import AbilityTracker from 'parser/shared/modules/AbilityTracker';
import Analyzer, { SELECTED_PLAYER } from 'parser/core/Analyzer';
import Events from 'parser/core/Events';
import SpellUsable from 'parser/shared/modules/SpellUsable';

const debug = false;

class CombustionSpellUsage extends Analyzer {
  static dependencies = {
    spellUsable: SpellUsable,
    abilityTracker: AbilityTracker,
  };

  badCastsStarted = 0;
  badCastsCompleted = 0;

  constructor(...args) {
    super(...args);
    this.hasBlasterMaster = this.selectedCombatant.hasTrait(SPELLS.BLASTER_MASTER.id);
    this.hasPhoenixFlames = this.selectedCombatant.hasTalent(SPELLS.PHOENIX_FLAMES_TALENT.id);
    this.addEventListener(Events.begincast.by(SELECTED_PLAYER).spell([SPELLS.FIREBALL,SPELLS.SCORCH]), this.checkChargeCounts);
    this.addEventListener(Events.cast.by(SELECTED_PLAYER).spell([SPELLS.FIREBALL,SPELLS.SCORCH]), this.checkChargeCounts);
  }

  //Check to see if the player cast (or started to cast) Fireball or Scorch during Combustion while they had Fire Blast or Phoenix Flames charges available.
  checkChargeCounts(event) {
    const hasCombustion = this.selectedCombatant.hasBuff(SPELLS.COMBUSTION.id);
    const fireBlastCharges = this.spellUsable.chargesAvailable(SPELLS.FIRE_BLAST.id);
    const phoenixFlamesCharges = (this.spellUsable.chargesAvailable(SPELLS.PHOENIX_FLAMES_TALENT.id) || 0);
    //If the player has the Blaster Master trait, it is acceptable to cast Scorch during Combustion
    if (!hasCombustion || (this.hasBlasterMaster && event.ability.guid === SPELLS.SCORCH.id)) {
      return;
    }

    if (event.type === "cast" && (fireBlastCharges > 0 || phoenixFlamesCharges > 0)) {
      this.badCastsCompleted += 1;
      this.event.meta = this.lastCastEvent.meta || {};
      this.event.meta.isInefficientCast = true;
      this.event.meta.inefficientCastReason = `This spell was cast during Combustion while an instant cast ability like Fire Blast ${this.hasPhoenixFlames ? 'or Phoenix Flames' : '' } was available. Make sure you are using your instant abilities first before hard casting Fireball ${this.hasBlasterMaster ? 'or Scorch' : '' }. `;
      debug && this.log("Cast completed with instants available");
    }

    if (event.type === "begincast" && (fireBlastCharges > 0 || phoenixFlamesCharges > 0)) {
      this.badCastsStarted += 1;
      debug && this.log("Cast started with instants available");
    }
  }

  get castsWithInstantsPerCombustion() {
    return this.badCastsStarted / this.abilityTracker.getAbility(SPELLS.COMBUSTION.id).casts;
  }

  get suggestionThresholds() {
    return {
      actual: this.castsWithInstantsPerCombustion,
      isGreaterThan: {
        minor: 0,
        average: 1,
        major: 2,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    when(this.suggestionThresholds)
      .addSuggestion((suggest, actual, recommended) => {
        return suggest(<>You started to cast <SpellLink id={SPELLS.FIREBALL.id} /> {!this.hasBlasterMaster ? <> or <SpellLink id={SPELLS.SCORCH.id} /></> : '' } {this.badCastsStarted} times ({this.castsWithInstantsPerCombustion.toFixed(2)} per Combustion), and completed {this.badCastsCompleted} casts, while you had charges of <SpellLink id={SPELLS.FIRE_BLAST.id} /> {this.hasPhoenixFlames ? <> or <SpellLink id={SPELLS.PHOENIX_FLAMES_TALENT.id} /> </> : '' } available. Make sure you are using up all of your charges of Fire Blast {this.hasPhoenixFlames ? ' and Phoenix Flames' : '' } before using Fireball {!this.hasBlasterMaster ? 'or Scorch' : '' } during Combustion.</>)
          .icon(SPELLS.COMBUSTION.icon)
          .actual(`${this.castsWithInstantsPerCombustion.toFixed(2)} Casts Per Combustion`)
          .recommended(`${formatNumber(recommended)} is recommended`);
      });
  }
}
export default CombustionSpellUsage;
<|endoftext|>


<commit_before>class Session {

  constructor(host, scopes, ssl) {
    this._host = host;
    this._scopes = scopes;
    this._clientId = null;
    this._token = null;
    this._webSocket = null;
    this._ssl = ssl || false;
    this._port = 4035;
    this._connected = false;
    this._pendingOffers = [];
  }

  get connected() {
    return this._connected;
  }

  get host() {
    return this._host;
  }

  get services() {
    return this._services;
  }

  get clientId() {
    return this._clientId;
  }
  set clientId(id) {
    this._clientId = id;
  }

  get accessToken() {
    return this._token;
  }
  set accessToken(token) {
    this._token = token;
  }

  connect() {
    return new Promise((resolve, reject) => {
      if (this._connected) {
        resolve({ result: 0 });
        return;
      }

      const scheme = (this._ssl === false) ? 'ws' : 'wss';
      const host = this._host;
      const url = scheme + '://' + host + ':4035/gotapi/websocket';
      const token = this._token;
      const session = this;
      console.log('Connecting Websocket: url=' + url);

      try {
        const socket = new WebSocket(url);
        socket.onopen = function(event) {
          console.log(host + ' - open - ' + event);
          const json = '{accessToken:"' + token + '"}';
          socket.send(json);
          console.log(host + ' - send JSON: ' + json);
        };
        socket.onmessage = function(event) {
          const message = event.data;
          console.log(host + ' - message: ' + message);

          const json = JSON.parse(message);
          if (json.result !== undefined) {
            if (json.result === 0) {
              session._connected = true;
              console.log('onmessage: this=', this);
              resolve(json);
            } else {
              reject({ what:'ws', code:json.errorCode });
            }
          }
        };
        socket.onclose = function(event) {
          console.log(host + ' - close', event);
          session._webSocket = null;
          session._connected = false;
        };
        this._webSocket = socket;
      } catch (e) {
        reject();
      }
    });
  }

  disconnect() {
    if (this._webSocket !== null) {
      this._webSocket.close();
      this._webSocket = null;
    }
    this._connected = false;
  }

  getRestScheme() {
    return this._ssl ? 'https' : 'http';
  }

  uri(path) {
    const scheme = this.getRestScheme();
    return scheme + '://' + this._host + ':' + this._port + path;
  }

  offer(func, params) {
    if (this._connected === true) {
      return func(this, params);
    } else {
      return new Promise((resolve, reject) => {
        this._pendingOffers.push({func, params, resolve, reject});
      });
    }
  }

  // processPendingOffers() {
  //   const session = this;
  //   this._pendingOffers.forEach(offer => {
  //     func(session, offer.params).then(r => { offer.resolve(r) }).cache(e => { offer.reject(e) })
  //   })
  // }

  request(args) {
    const method = args.method.toUpperCase();
    const path = args.path;

    const params = args.params || {};
    params.accessToken = this.accessToken;

    const headers = {};
    headers['Origin'] = location.origin;

    const query = new URLSearchParams();
    for (let key in params) {
      query.set(key, params[key]);
    }

    let uri = this.uri(path);
    let body = null;
    if (method === 'POST' || method === 'PUT') {
      body = query.toString();
      headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
    } else if (method === 'GET' || method === 'DELETE') {
      uri += '?' + query.toString();
    }

    return fetch(uri, {
      method,
      headers,
      body,
      mode: 'cors',
      cache: 'no-cache'
    }).then(res => res.json());
  }

  fetch() {
    const scheme = this.getRestScheme();
    const host = this._host;
    const params = new URLSearchParams();
    params.set('accessToken', this.accessToken);
    const query = params.toString();

    return fetch(scheme + "://" + host + ":" + this._port + "/gotapi/serviceDiscovery?" + query, {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }
}

/**
 * Device Connect Client SDK for Javascript.
 */
class DeviceConnectClient {

  constructor(op) {
    this.appName = op.appName || 'Application';
    this._sessions = {};
    this._pendingOffers = {};
  }

  get sessions() {
    return this._sessions;
  }

  isConnected(host) {
    let session = this._sessions[host];
    if (!session) {
      return false;
    }
    return session.connected;
  }

  addSession(args) {
    const host = args.host;
    const session = new Session(args.host, args.scopes);
    session.accessToken = args.accessToken;
    this._sessions[host] = session;
  }

  deleteSession(host) {
    if (this._sessions[host]) {
      this._sessions[host].disconnect();
    }
    this._sessions[host] = undefined;
  }

  isAndroid() {
    var userAgent = window.navigator.userAgent.toLowerCase();
    return (userAgent.indexOf('android') != -1);
  }

  isChrome() {
    var userAgent = window.navigator.userAgent.toLowerCase();
    return (userAgent.indexOf('chrome') != -1);
  }

  startDeviceConnect(option) {
    let scheme = 'gotapi';
    let uriHost = 'start';
    let path = '/server';
    let packageName = 'org.deviceconnect.android.manager';
    let uri;
    if (this.isChrome()) {
      uri = `intent://${uriHost}${path}#Intent;scheme=${scheme};package=${packageName};end;`;
    } else {
      uri = `${scheme}://${uriHost}${path}?package=${packageName}`;
    }
    location.href = uri;
    this.waitAvailable(option);
  }

  waitAvailable(option) {
    option.oncheck = option.oncheck || function() {};
    option.count = option.count || 10;

    option.oncheck(option.count);
    option.count--;
    this.checkAvailability(option.host)
    .then((json) => {
      option.onstart(json);
    })
    .catch((err) => {
      console.log("Error: checkAvailability", err);
      if (option.count <= 0) {
        option.onerror();
      } else {
        setTimeout(function(op) {
          this.waitAvailable(op);
        }.bind(this, option), option.interval || 1000);
      }
    })
  }

  /**
   * DeviceConnect システムに接続する.
   *
   * @param {object} option -
   * @return {Promise} DeviceConnect システムへの接続処理の Promise
   */
  connect(option) {
    const host = option.host || 'localhost';
    const scopes = option.scopes || ['serviceDiscovery', 'serviceInformation'];
    const ssl = option.ssl || false;

    return new Promise((resolve, reject) => {
      let session = this._sessions[host];
      if (!session) {
        session = new Session(host, scopes, ssl);
        this._sessions[host] = session;
      }

      // Authorization
      this.authorize(session, host, scopes)

      // Establish WebSokcet
      .then(json => {
        console.log('Response:', json);

        const result = json.result;
        const accessToken = json.accessToken;
        if (result === 0 && accessToken) {
          console.log('Got Access Token: accessToken=' + accessToken);
          const session = this._sessions[host];
          session.accessToken = accessToken;

          console.log('Connecting to host=' + host);
          return session.connect();
        } else {
          reject({ what: 'connect', reason: 'no-access-token', errorMessage: '本アプリの使用が認可されませんでした。' });
        }
      })
      .catch(err => {
        if (err.code === 4) {
          reject({ what: 'connect', reason: 'ws-duplicated', errorMessage: '別ブラウザで既にWebSocketが接続されています。' });
        } else if (err.code === 3) {
          reject({ what: 'connect', reason: 'ws-invalid-access-token', errorMessage: 'アクセストークンが不正のためにWebSocketを接続できませんでした。' });
        } else {
          reject({ what: 'connect', reason: 'ws-unknown--error', errorMessage: '不明なエラーによりWebSocketを接続できませんでした。' });
        }
      })

      // Service Discovery
      .then(json => {
        console.log(json);
        this.processPendingOffers(session);

        return this.fetchServices(host);
      })

      .then(json => {
        console.log('Fetched services:', json.services);
        const result = json.result;
        if (result === 0) {
          resolve({session, services:json.services});
        } else {
          reject({ what: 'connect', reason: 'no-service', errorMessage: 'サービス検索に失敗しました。' });
        }
      })
    });
  }

  checkAvailability(host) {
    return fetch("http://" + host + ":4035/gotapi/availability", {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  authorize(session, host, scopes) {
    if (session.accessToken !== null) {
      console.log('AccessToken: ' + session.accessToken);
      return Promise.resolve({ result:0, accessToken:session.accessToken });
    }
    return this.createClient(host)
    .then((json) => {
      console.log('clientId: ' + json.clientId);
      const result = json.result;
      const clientId = json.clientId;
      if (result === 0) {
        console.log('Created client: clientId=' + clientId);

        this._sessions[host].clientId = clientId;
        return this.requestAccessToken(host, scopes);
      } else {
        console.warn('authorize: createClient: erroCode=' + json.errorCode);
        if (json.errorCode === 2) {
          // LocalOAuth が OFF の場合は形式的なアクセストークンとして以下の文字列を返す.
          // WebSocket 接続確立時に任意の文字列を送信する必要がある.
          return Promise.resolve({ result:0, accessToken:'placeHolder' });
        }
        return Promise.reject({ what: 'connect', reason: 'no-client', errorMessage: 'クライアントIDを取得できませんでした。' });
      }
    })
  }

  createClient(host) {
    return fetch("http://" + host + ":4035/gotapi/authorization/grant", {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  requestAccessToken(host, scopes) {
    const session = this._sessions[host];
    const params = new URLSearchParams();
    params.set('clientId', session.clientId);
    params.set('applicationName', this.appName);
    params.set('scope', scopes.join(','));
    const query = params.toString();
    console.log('requestAccessToken: query=' + query)

    return fetch("http://" + host + ":4035/gotapi/authorization/accessToken?" + query, {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  fetchServices(host) {
    const session = this._sessions[host];
    return session.fetch();
  }

  offer(host, api, params) {
    const session = this._sessions[host];
    console.log('offer: session=', session);
    if (session) {
      console.log('offer: connected=' + session.connected);
      if (session.connected) {
        return session.offer(api, params);
      }
    }

    let offers = this._pendingOffers[host];
    if (!offers) {
      offers = [];
      this._pendingOffers[host] = offers;
    }
    return new Promise((resolve, reject) => {
      offers.push({func:api, params, resolve, reject});
    });
  }

  processPendingOffers(session) {
    let offers = this._pendingOffers[session.host];
    if (!offers) {
      return;
    }
    offers.forEach(offer => {
      offer.func(session, offer.params).then(r => { offer.resolve(r) }).catch(e => { offer.reject(e) })
    })
    this._pendingOffers[session.host] = null;
  }
}

export default function(op) {
  return new DeviceConnectClient(op);
}<commit_msg>デモページ読み込み時にアクセストークンが無効であれば取得し直す。<commit_after>class Session {

  constructor(host, scopes, ssl, useWebSocket) {
    this._host = host;
    this._scopes = scopes;
    this._clientId = null;
    this._token = null;
    this._webSocket = null;
    this._useWebSocket = (useWebSocket === false) ? false : true;
    this._ssl = ssl || false;
    this._port = 4035;
    this._wsEstablished = false;
    this._pendingOffers = [];
  }

  get connected() {
    if (this._useWebSocket && !this._wsEstablished) {
      return false;
    }
    return true;
  }

  get host() {
    return this._host;
  }

  get services() {
    return this._services;
  }

  get clientId() {
    return this._clientId;
  }
  set clientId(id) {
    this._clientId = id;
  }

  get accessToken() {
    return this._token;
  }
  set accessToken(token) {
    this._token = token;
  }

  connect() {
    return new Promise((resolve, reject) => {
      if (this.connected) {
        resolve({ result: 0 });
        return;
      }

      const scheme = (this._ssl === false) ? 'ws' : 'wss';
      const host = this._host;
      const url = scheme + '://' + host + ':4035/gotapi/websocket';
      const token = this._token;
      const session = this;
      console.log('Connecting Websocket: url=' + url);

      try {
        const socket = new WebSocket(url);
        socket.onopen = function(event) {
          console.log(host + ' - open - ' + event);
          const json = '{accessToken:"' + token + '"}';
          socket.send(json);
          console.log(host + ' - send JSON: ' + json);
        };
        socket.onmessage = function(event) {
          const message = event.data;
          console.log(host + ' - message: ' + message);

          const json = JSON.parse(message);
          if (json.result !== undefined) {
            if (json.result === 0) {
              session._wsEstablished = true;
              console.log('onmessage: this=', this);
              resolve(json);
            } else {
              reject({ what:'ws', code:json.errorCode });
            }
          }
        };
        socket.onclose = function(event) {
          console.log(host + ' - close', event);
          session._webSocket = null;
          session._wsEstablished = false;
        };
        this._webSocket = socket;
      } catch (e) {
        reject();
      }
    });
  }

  disconnect() {
    if (this._webSocket !== null) {
      this._webSocket.close();
      this._webSocket = null;
    }
    this._wsEstablished = false;
  }

  getRestScheme() {
    return this._ssl ? 'https' : 'http';
  }

  uri(path) {
    const scheme = this.getRestScheme();
    return scheme + '://' + this._host + ':' + this._port + path;
  }

  offer(func, params) {
    if (this.connected === true) {
      return func(this, params);
    } else {
      return new Promise((resolve, reject) => {
        this._pendingOffers.push({func, params, resolve, reject});
      });
    }
  }

  request(args) {
    const method = args.method.toUpperCase();
    const path = args.path;

    const params = args.params || {};
    params.accessToken = this.accessToken;

    const headers = {};
    headers['Origin'] = location.origin;

    const query = new URLSearchParams();
    for (let key in params) {
      query.set(key, params[key]);
    }

    let uri = this.uri(path);
    let body = null;
    if (method === 'POST' || method === 'PUT') {
      body = query.toString();
      headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
    } else if (method === 'GET' || method === 'DELETE') {
      uri += '?' + query.toString();
    }

    return fetch(uri, {
      method,
      headers,
      body,
      mode: 'cors',
      cache: 'no-cache'
    }).then(res => res.json());
  }

  fetch() {
    const scheme = this.getRestScheme();
    const host = this._host;
    const params = new URLSearchParams();
    params.set('accessToken', this.accessToken);
    const query = params.toString();

    return fetch(scheme + "://" + host + ":" + this._port + "/gotapi/serviceDiscovery?" + query, {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }
}

class DeviceConnectClient {

  constructor(op) {
    this.appName = op.appName || 'Application';
    this._sessions = {};
    this._pendingOffers = {};
  }

  get sessions() {
    return this._sessions;
  }

  isConnected(host) {
    let session = this._sessions[host];
    if (!session) {
      return false;
    }
    return session.connected;
  }

  addSession(args) {
    const host = args.host;
    const session = new Session(args.host, args.scopes, args.ssl, false);
    session.accessToken = args.accessToken;
    this._sessions[host] = session;
  }

  deleteSession(host) {
    if (this._sessions[host]) {
      this._sessions[host].disconnect();
    }
    this._sessions[host] = undefined;
  }

  isAndroid() {
    var userAgent = window.navigator.userAgent.toLowerCase();
    return (userAgent.indexOf('android') != -1);
  }

  isChrome() {
    var userAgent = window.navigator.userAgent.toLowerCase();
    return (userAgent.indexOf('chrome') != -1);
  }

  startDeviceConnect(option) {
    let scheme = 'gotapi';
    let uriHost = 'start';
    let path = '/server';
    let packageName = 'org.deviceconnect.android.manager';
    let uri;
    if (this.isChrome()) {
      uri = `intent://${uriHost}${path}#Intent;scheme=${scheme};package=${packageName};end;`;
    } else {
      uri = `${scheme}://${uriHost}${path}?package=${packageName}`;
    }
    location.href = uri;
    this.waitAvailable(option);
  }

  waitAvailable(option) {
    option.oncheck = option.oncheck || function() {};
    option.count = option.count || 10;

    option.oncheck(option.count);
    option.count--;
    this.checkAvailability(option.host)
    .then((json) => {
      option.onstart(json);
    })
    .catch((err) => {
      console.log("Error: checkAvailability", err);
      if (option.count <= 0) {
        option.onerror();
      } else {
        setTimeout(function(op) {
          this.waitAvailable(op);
        }.bind(this, option), option.interval || 1000);
      }
    })
  }

  /**
   * DeviceConnect システムに接続する.
   *
   * @param {object} option -
   * @return {Promise} DeviceConnect システムへの接続処理の Promise
   */
  connect(option) {
    const host = option.host || 'localhost';
    const scopes = option.scopes || ['serviceDiscovery', 'serviceInformation'];
    const ssl = option.ssl || false;

    return new Promise((resolve, reject) => {
      let session = this._sessions[host];
      if (!session) {
        session = new Session(host, scopes, ssl, false);
        this._sessions[host] = session;
      }

      // Authorization
      this.authorize(session, host, scopes)
      .then(json => {
        console.log(json);
        let result = json.result;
        if (result === 0) {
          session.accessToken = json.accessToken;

          this.processPendingOffers(session);
          return this.fetchServices(host);
        } else {
          reject({ what: 'connect', reason: 'no-auth', errorMessage: '本アプリケーションの認可に失敗しました。' });
        }
      })

      // Service Discovery Result
      .then(json => {
        if (!json) {
          return;
        }
        const result = json.result;
        if (result === 0) {
          resolve({session, services:json.services});
        } else {
          let errorCode = json.errorCode;
          if (11 <= errorCode && errorCode <= 15) {
            // 再認可
            session.clientId = null;
            session.accessToken = null;
            this.connect(option)
            .then(json => resolve(json))
            .catch(err => reject(err));
          } else {
            reject({ what: 'connect', reason: 'no-service', errorMessage: 'サービス検索に失敗しました。' });
          }
        }
      })
    });
  }

  checkAvailability(host) {
    return fetch("http://" + host + ":4035/gotapi/availability", {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  authorize(session, host, scopes) {
    if (session.accessToken !== null) {
      return Promise.resolve({ result:0, accessToken:session.accessToken });
    }

    return this.createClient(host)
    .then(json => {
      const result = json.result;
      const clientId = json.clientId;
      if (result === 0) {
        session.clientId = clientId;
        return this.requestAccessToken(session, host, scopes);
      } else {
        if (json.errorCode === 2) {
          // LocalOAuth が OFF の場合は形式的なアクセストークンとして以下の文字列を返す.
          // WebSocket 接続確立時に任意の文字列を送信する必要がある.
          return Promise.resolve({ result:0, accessToken:'placeHolder' });
        }
        return Promise.reject({ what: 'connect', reason: 'no-client', errorMessage: 'クライアントIDを取得できませんでした。' });
      }
    })
  }

  createClient(host) {
    return fetch("http://" + host + ":4035/gotapi/authorization/grant", {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  requestAccessToken(session, host, scopes) {
    const params = new URLSearchParams();
    params.set('clientId', session.clientId);
    params.set('applicationName', this.appName);
    params.set('scope', scopes.join(','));
    const query = params.toString();

    return fetch("http://" + host + ":4035/gotapi/authorization/accessToken?" + query, {
      method: 'GET',
      mode: 'cors',
      cache: 'no-cache',
      headers: {
        "Origin": location.origin
      }
    }).then(res => {
      return res.json();
    });
  }

  fetchServices(host) {
    const session = this._sessions[host];
    return session.fetch();
  }

  offer(host, api, params) {
    const session = this._sessions[host];
    console.log('offer: session=', session);
    if (session) {
      console.log('offer: connected=' + session.connected);
      if (session.connected) {
        return session.offer(api, params);
      }
    }

    let offers = this._pendingOffers[host];
    if (!offers) {
      offers = [];
      this._pendingOffers[host] = offers;
    }
    return new Promise((resolve, reject) => {
      offers.push({func:api, params, resolve, reject});
    });
  }

  processPendingOffers(session) {
    let offers = this._pendingOffers[session.host];
    if (!offers) {
      return;
    }
    offers.forEach(offer => {
      offer.func(session, offer.params).then(r => { offer.resolve(r) }).catch(e => { offer.reject(e) })
    })
    this._pendingOffers[session.host] = null;
  }
}

export default function(op) {
  return new DeviceConnectClient(op);
}<|endoftext|>


<commit_before>import SPELLS from 'common/SPELLS';
import BaseHealerAzerite from './BaseHealerAzerite';

const HALF_HP = 0.5;

class SurgingTides extends BaseHealerAzerite {
  static TRAIT = SPELLS.SURGING_TIDES.id;
  static HEAL = SPELLS.SURGING_TIDES_ABSORB.id;

  potentialSurgingTideProcs = 0;
  currentAbsorbSize = 0;

  constructor(...args) {
    super(...args);
    this.active = this.hasTrait;
    if (!this.active) {
      return;
    }
  }

  on_byPlayer_absorbed(event) {
    super.on_byPlayer_heal(event);
  }

  on_byPlayer_applybuff(event) {
    if (event.ability.guid !== SPELLS.SURGING_TIDES_ABSORB.id) {
      return;
    }
    this.currentAbsorbSize = event.absorb || 0;
  }

  on_byPlayer_removebuff(event) {
    if (event.ability.guid !== SPELLS.SURGING_TIDES_ABSORB.id) {
      return;
    }

    let absorb = event.absorb || 0;
    const healPerTrait = this.azerite.map((trait) => (this.currentAbsorbSize) * trait.healingFactor);
    for (const [index, trait] of Object.entries(this.azerite)) {
      const overhealingValue = Math.min(healPerTrait[index], absorb);
      trait.overhealing += overhealingValue;
      absorb -= overhealingValue;
    }
  }

  on_byPlayer_heal(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.RIPTIDE.id) {
      return;
    }
    if (event.tick) {
      return;
    }

    const currentHealth = Math.max(0, (event.hitPoints - event.amount) / event.maxHitPoints);
    if (currentHealth >= HALF_HP) {
      return;
    }
    this.potentialSurgingTideProcs += 1;
  }

  get surgingTideProcsPerMinute() {
    return (this.potentialSurgingTideProcs / (this.owner.fightDuration / 1000 / 60)).toFixed(2);
  }
}

export default SurgingTides;
<commit_msg>disable statistic box<commit_after>import SPELLS from 'common/SPELLS';
import BaseHealerAzerite from './BaseHealerAzerite';

const HALF_HP = 0.5;

class SurgingTides extends BaseHealerAzerite {
  static TRAIT = SPELLS.SURGING_TIDES.id;
  static HEAL = SPELLS.SURGING_TIDES_ABSORB.id;

  potentialSurgingTideProcs = 0;
  currentAbsorbSize = 0;

  constructor(...args) {
    super(...args);
    this.disableStatistic = !this.hasTrait;
  }

  on_byPlayer_absorbed(event) {
    super.on_byPlayer_heal(event);
  }

  on_byPlayer_applybuff(event) {
    if (event.ability.guid !== SPELLS.SURGING_TIDES_ABSORB.id) {
      return;
    }
    this.currentAbsorbSize = event.absorb || 0;
  }

  on_byPlayer_removebuff(event) {
    if (event.ability.guid !== SPELLS.SURGING_TIDES_ABSORB.id) {
      return;
    }

    let absorb = event.absorb || 0;
    const healPerTrait = this.azerite.map((trait) => (this.currentAbsorbSize) * trait.healingFactor);
    for (const [index, trait] of Object.entries(this.azerite)) {
      const overhealingValue = Math.min(healPerTrait[index], absorb);
      trait.overhealing += overhealingValue;
      absorb -= overhealingValue;
    }
  }

  on_byPlayer_heal(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.RIPTIDE.id) {
      return;
    }
    if (event.tick) {
      return;
    }

    const currentHealth = Math.max(0, (event.hitPoints - event.amount) / event.maxHitPoints);
    if (currentHealth >= HALF_HP) {
      return;
    }
    this.potentialSurgingTideProcs += 1;
  }

  get surgingTideProcsPerMinute() {
    return (this.potentialSurgingTideProcs / (this.owner.fightDuration / 1000 / 60)).toFixed(2);
  }
}

export default SurgingTides;
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react';
import find from 'lodash/find';
import {connect as connectToDocumentation} from '../../behaviours/documentation';
import {connect as connectToForm } from '../../behaviours/form';
import {connect as connectToMetadata} from '../../behaviours/metadata';
import {connect as connectToFieldHelpers} from '../../behaviours/field';
import {connect as connectToMasterData} from '../../behaviours/master-data';
import {loadUserAction, saveUserAction} from '../actions/user-actions';

import Panel from '../../components/panel';
import compose from 'lodash/flowRight';

class UserDisplayOnly extends Component {
    componentWillMount() {
        const {id, load, loadMasterData} = this.props;
        load({id});
        loadMasterData();
    }
    render() {
        const {editing, fields, fieldFor, selectFor} = this.props;
        const civilityField = find(fields, {name: 'civility', entityPath: 'user'});
        return (
            <Panel title='Display only user page' >
                {fieldFor('uuid', {entityPath: 'user'})}
                {fieldFor('date', {entityPath: 'user'})}
            </Panel>
        );
    }
};

UserDisplayOnly.displayName = 'UserDisplayOnly';

const formConfig = {
    formKey: 'userDisplay',
    entityPathArray: ['user', 'address'],
    loadAction: loadUserAction,
    saveAction: saveUserAction,
    nonValidatedFields: ['user.firstName']
};
export const tuto = `
  ## Comment faire une page de consultation pure

  \`const lol = 'lol';\`

`;
//Connect the component to all its behaviours (respect the order for store, store -> props, helper)
const ConnectedDisplayUser = compose(
    connectToMetadata(['user']),
    connectToMasterData(['civility']),
    connectToForm(formConfig),
    connectToFieldHelpers(),
    connectToDocumentation(tuto)
  )(UserDisplayOnly);

export default ConnectedDisplayUser;
<commit_msg>[Display only]<commit_after>import React, {Component, PropTypes} from 'react';
import find from 'lodash/find';
import {connect as connectToDocumentation} from '../../behaviours/documentation';
import {connect as connectToForm } from '../../behaviours/form';
import {connect as connectToMetadata} from '../../behaviours/metadata';
import {connect as connectToFieldHelpers} from '../../behaviours/field';
import {connect as connectToMasterData} from '../../behaviours/master-data';
import {loadUserAction, saveUserAction} from '../actions/user-actions';

import Panel from '../../components/panel';
import compose from 'lodash/flowRight';

class UserDisplayOnly extends Component {
    componentWillMount() {
        const {id, load, loadMasterData} = this.props;
        load({id});
        loadMasterData();
    }
    render() {
        const {editing, fields, fieldFor, selectFor} = this.props;
        const civilityField = find(fields, {name: 'civility', entityPath: 'user'});
        return (
            <Panel title='Display only user page' >
                {fieldFor('uuid', {entityPath: 'user'})}
                {fieldFor('date', {entityPath: 'user'})}
            </Panel>
        );
    }
};

UserDisplayOnly.displayName = 'UserDisplayOnly';

const formConfig = {
    formKey: 'userDisplay',
    entityPathArray: ['user', 'address'],
    // The loading action, it will be passed as a props to the child
    loadAction: loadUserAction,
    /*The fields you want to exclude from the valiation if they are in your domain*/
    nonValidatedFields: ['user.firstName']
};

export const tuto = `
  ## How can you build a pure consultation page
  - You have a component which can be pure or not, but it needs to be connected to the providers to have .
  - First you need to provide the meta data informations that is the role of the \`connectToMetadata\` informations. You can pass the informations to it .
  - Then if you need master data you need to be connected to them. Here we need the \`civility\`
  - Then you need to be connected to the form provider with the connect to form data, a form need a \`formKey\`, then

`;
//Connect the component to all its behaviours (respect the order for store, store -> props, helper)
const ConnectedDisplayUser = compose(
    connectToMetadata(['user']),
    connectToMasterData(['civility']),
    connectToForm(formConfig),
    connectToFieldHelpers(),
    connectToDocumentation(tuto)
  )(UserDisplayOnly);

export default ConnectedDisplayUser;
<|endoftext|>


<commit_before>/**
 * Created by thomas on 14/06/17.
 */
function ajaxExportData() {
        $("#resultat").html("<p> Teste </p>");

        var nom_ecole = $("#ecole").val();
        var nom_classe = $("#classe").val();
        var date_journee = $("#date_journee").text();
        var data = {nom_ecole: nom_ecole, nom_classe: nom_classe, date_journee: date_journee};
    $.ajax({
        type: 'POST',
        url: '/exportData',
        data: data,
        dataType: 'json'
    }).done(function (response) {
        var events = [];
        $.each(response, function (k) {
            events.push(response[k]);
        });

    });
}
<commit_msg>Retour message d'erreur si argmuent invalide<commit_after>/**
 * Created by thomas on 14/06/17.
 */
function ajaxExportData() {
        $("#resultat").html("<p> Teste </p>");
        var nom_ecole = $("#ecole").val();
        var nom_classe = $("#classe").val();
        var date_journee = $("#date_journee").text();
        var data = {nom_ecole: nom_ecole, nom_classe: nom_classe, date_journee: date_journee};
    $.ajax({
        type: 'POST',
        url: '/exportData',
        data: data,
        dataType: 'json'
    }).done(function (response) {
        var events = [];
        $.each(response, function (k) {
            events.push(response[k]);
        });

    });
}
<|endoftext|>


<commit_before>define([
	'utils/warn',
	'config/namespaces',
	'render/StringFragment/_StringFragment',
	'render/DomFragment/Element/shared/getMatchingStaticNodes',
	'circular'
], function (
	warn,
	namespaces,
	StringFragment,
	getMatchingStaticNodes,
	circular
) {

	'use strict';

	var DomFragment, updateCss, updateScript;

	circular.push( function () {
		DomFragment = circular.DomFragment;
	});

	updateCss = function () {
		var node = this.node, content = this.fragment.toString();

		if ( node.styleSheet ) {
			node.styleSheet.cssText = content;
		} else {
			node.innerHTML = content;
		}

	};

	updateScript = function () {
		if ( !this.node.type || this.node.type === 'text/javascript' ) {
			warn( 'Script tag was updated. This does not cause the code to be re-evaluated!' );
			// As it happens, we ARE in a position to re-evaluate the code if we wanted
			// to - we could eval() it, or insert it into a fresh (temporary) script tag.
			// But this would be a terrible idea with unpredictable results, so let's not.
		}

		this.node.text = this.fragment.toString();
	};

	return function appendElementChildren ( element, node, descriptor, docFrag ) {
		// Special case - script and style tags
		if ( element.lcName === 'script' || element.lcName === 'style' ) {
			element.fragment = new StringFragment({
				descriptor:   descriptor.f,
				root:         element.root,
				owner:        element
			});

			if ( docFrag ) {
				if ( element.lcName === 'script' ) {
					element.bubble = updateScript;
					element.node.text = element.fragment.toString(); // bypass warning initially
				} else {
					element.bubble = updateCss;
					element.bubble();
				}
			}

			return;
		}

		if ( typeof descriptor.f === 'string' && ( !node || ( !node.namespaceURI || node.namespaceURI === namespaces.html ) ) ) {
			// great! we can use innerHTML
			element.html = descriptor.f;

			if ( docFrag ) {
				node.innerHTML = element.html;

				// Update live queries, if applicable
				element.matchingStaticNodes = {}; // so we can remove matches made with querySelectorAll at teardown time
				updateLiveQueries( element );
			}
		}

		else {
			element.fragment = new DomFragment({
				descriptor:    descriptor.f,
				root:          element.root,
				pNode:         node,
				owner:         element,
				pElement:      element,
			});

			if ( docFrag ) {
				node.appendChild( element.fragment.docFrag );
			}
		}
	};

	function updateLiveQueries ( element ) {
		var instance, liveQueries, node, selector, query, matchingStaticNodes, i;

		node = element.node;
		instance = element.root;

		do {
			liveQueries = instance._liveQueries;

			i = liveQueries.length;
			while ( i-- ) {
				selector = liveQueries[i];
				query = liveQueries[ selector ];

				matchingStaticNodes = getMatchingStaticNodes( element, selector );
				query.push.apply( query, matchingStaticNodes );
			}
		} while ( instance = instance._parent );
	}

});
<commit_msg>try suggestions for append rather than innerHTML<commit_after>define([
	'utils/warn',
	'config/namespaces',
	'render/StringFragment/_StringFragment',
	'render/DomFragment/Element/shared/getMatchingStaticNodes',
	'circular'
], function (
	warn,
	namespaces,
	StringFragment,
	getMatchingStaticNodes,
	circular
) {

	'use strict';

	var DomFragment, updateCss, updateScript;

	circular.push( function () {
		DomFragment = circular.DomFragment;
	});

	updateCss = function () {
		var node = this.node, content = this.fragment.toString();

		if ( node.styleSheet ) {
			node.styleSheet.cssText = content;
		} else {
			node.innerHTML = content;
		}

	};

	updateScript = function () {
		if ( !this.node.type || this.node.type === 'text/javascript' ) {
			warn( 'Script tag was updated. This does not cause the code to be re-evaluated!' );
			// As it happens, we ARE in a position to re-evaluate the code if we wanted
			// to - we could eval() it, or insert it into a fresh (temporary) script tag.
			// But this would be a terrible idea with unpredictable results, so let's not.
		}

		this.node.text = this.fragment.toString();
	};

	return function appendElementChildren ( element, node, descriptor, docFrag ) {
		// Special case - script and style tags
		if ( element.lcName === 'script' || element.lcName === 'style' ) {
			element.fragment = new StringFragment({
				descriptor:   descriptor.f,
				root:         element.root,
				owner:        element
			});

			if ( docFrag ) {
				if ( element.lcName === 'script' ) {
					element.bubble = updateScript;
					element.node.text = element.fragment.toString(); // bypass warning initially
				} else {
					element.bubble = updateCss;
					element.bubble();
				}
			}

			return;
		}

		if ( typeof descriptor.f === 'string' && ( !node || ( !node.namespaceURI || node.namespaceURI === namespaces.html ) ) ) {
			// great! we can use innerHTML
			element.html = descriptor.f;

			if ( docFrag ) {
				node.innerHTML = element.html;
			    /*
			    var newTextNode = document.createTextNode(element.html);
			    while ( node.firstChild ) {
			        node.removeChild( node.firstChild );
			    }
			    node.appendChild( newTextNode);
				*/

				// Update live queries, if applicable
				element.matchingStaticNodes = {}; // so we can remove matches made with querySelectorAll at teardown time
				updateLiveQueries( element );
			}
		}

		else {
			element.fragment = new DomFragment({
				descriptor:    descriptor.f,
				root:          element.root,
				pNode:         node,
				owner:         element,
				pElement:      element,
			});

			if ( docFrag ) {
				node.appendChild( element.fragment.docFrag );
			}
		}
	};

	function updateLiveQueries ( element ) {
		var instance, liveQueries, node, selector, query, matchingStaticNodes, i;

		node = element.node;
		instance = element.root;

		do {
			liveQueries = instance._liveQueries;

			i = liveQueries.length;
			while ( i-- ) {
				selector = liveQueries[i];
				query = liveQueries[ selector ];

				matchingStaticNodes = getMatchingStaticNodes( element, selector );
				query.push.apply( query, matchingStaticNodes );
			}
		} while ( instance = instance._parent );
	}

});
<|endoftext|>


<commit_before>function toggle_hide_show_with_smart_loading( id_to_show, ids_to_hide ) {
	id_to_show = $(id_to_show);
	if( id_to_show.visible() ) {
		new Effect.BlindUp( id_to_show, { duration: 0.3 } );
		return false;
	} else if( id_to_show.innerHTML != '' ) {
		ids_to_hide.each(
			function( id_to_hide ) {
				new Effect.BlindUp( id_to_hide, { duration: 0.3 } );
			}
		);

		new Effect.Parallel(
			[	new Effect.BlindDown( id_to_show, { sync: true } ),
				new Effect.ScrollPage( id_to_show, { syne: true } ) ],
			{ duration: 0.3 }
		);

		if( arguments[2] ) {
			Selector.findChildElements( id_to_show, $A( [ "form" ] ) ).each(
				function( form ) {
					setTimeout(
						function() {
							form.focusFirstElement();
						}, 500 );
					}
			);
		}
		return false;
	}
	return true;
}

Effect.ScrollPage = Class.create();
Object.extend(Object.extend(Effect.ScrollPage.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = $(element);
		this.start(arguments[1] || {});
	},
	update: function(position) {
		var window_top =  window.pageYOffset
				|| document.documentElement.scrollTop
				|| document.body.scrollTop
				|| 0;

		var window_height = window.innerHeight
			|| document.body.innerHeight
			|| 0;

		var element_top = Position.cumulativeOffset( this.element )[1];
		var element_height = this.element.getHeight();

		var y_target = ( element_top + element_height ) - window_height;

		if( element_top + element_height > window_top + window_height ) {
			if( Position.cumulativeOffset( this.element.parentNode )[1] < y_target ) {
				y_target = Position.cumulativeOffset( this.element.parentNode )[1];
			}
			window.scrollTo( 0, y_target );
		}
	}
});<commit_msg>Updated the hide/show JS to perform all effects in parallel<commit_after>function toggle_hide_show_with_smart_loading( id_to_show, ids_to_hide ) {
	id_to_show = $(id_to_show);
	if( id_to_show.visible() ) {
		new Effect.BlindUp( id_to_show, { duration: 0.3 } );
		return false;
	} else if( id_to_show.innerHTML != '' ) {
		effects = [
			new Effect.BlindDown( id_to_show, { sync: true } ),
			new Effect.ScrollPage( id_to_show, { syne: true } )
		];
		ids_to_hide.each(
			function( id_to_hide ) {
				effects.unshift( new Effect.BlindUp( id_to_hide, { sync: true } ) );
			}
		);

		new Effect.Parallel( effects, { duration: 0.3 } );

		if( arguments[2] ) {
			Selector.findChildElements( id_to_show, $A( [ "form" ] ) ).each(
				function( form ) {
					setTimeout(
						function() {
							form.focusFirstElement();
						}, 500 );
					}
			);
		}
		return false;
	}
	return true;
}

Effect.ScrollPage = Class.create();
Object.extend(Object.extend(Effect.ScrollPage.prototype, Effect.Base.prototype), {
	initialize: function(element) {
		this.element = $(element);
		this.start(arguments[1] || {});
	},
	update: function(position) {
		var window_top =  window.pageYOffset
				|| document.documentElement.scrollTop
				|| document.body.scrollTop
				|| 0;

		var window_height = window.innerHeight
			|| document.body.innerHeight
			|| 0;

		var element_top = Position.cumulativeOffset( this.element )[1];
		var element_height = this.element.getHeight();

		var y_target = ( element_top + element_height ) - window_height;

		if( element_top + element_height > window_top + window_height ) {
			if( Position.cumulativeOffset( this.element.parentNode )[1] < y_target ) {
				y_target = Position.cumulativeOffset( this.element.parentNode )[1];
			}
			window.scrollTo( 0, y_target );
		}
	}
});<|endoftext|>


<commit_before>window.cls || (window.cls = {});

window.cls.FriendlyPrinter = function()
{
  const
  VALUE_LIST = 2,
  OBJECT_VALUE = 1,
  OBJECT_ID = 0,
  MAX_ARGS = 60;

  this._friendly_print = function(obj_list, rt_id, thread_id, frame_id, fallback)
  {
    var obj_ids = obj_list.map(this._obj2obj_id_list);
    var queue_cb = this._friendly_print_chunked_cb.bind(this, obj_list, rt_id,
                                                        obj_ids, fallback);
    var queue = [], queue_length = 0, processed_queue = [];
    // chunk the request, Eval is currently limited to 64 arguments
    // CORE-35198
    while (obj_ids.length > MAX_ARGS * queue_length)
    {
      queue.push(obj_ids.slice(queue_length++ * MAX_ARGS,
                               queue_length * MAX_ARGS));
    }
    queue.forEach(function(obj_ids, index)
    {
      var call_list = obj_ids.map(this._obj_id2str).join(',');
      var arg_list = obj_ids.reduce(this._create_arg_list, []);
      var tag = this._tagman.set_callback(this,
                                          this._handle_queue,
                                          [
                                            processed_queue,
                                            index,
                                            queue_length,
                                            queue_cb
                                          ]);
      var script = this._friendly_print_host_str.replace("%s", call_list);
      var msg = [rt_id, thread_id, frame_id, script, arg_list];
      this._service.requestEval(tag, msg);
    }, this);
  };

  this._friendly_print_chunked_cb = function(obj_list, rt_id, obj_ids,
                                             fallback, queue)
  {
    const
    STATUS = 0,
    MESSAGE = 1,
    VALUE = 2,
    VALUE_LIST = 2,
    DF_INTERN_TYPE = 3,
    FRIENDLY_PRINTED = 6,
    OBJECT_VALUE = 1;

    var ret = queue.reduce(function(list, response)
    {
      var status = response[STATUS], msg = response[MESSAGE];
      if (status || msg[STATUS] != "completed")
      {
        opera.postError('Pretty printing failed: ' + JSON.stringify(msg));
        return null;
      }
      if(list)
      {
        list.extend(JSON.parse(msg[VALUE]));
      }
      return list;
    }, []);

    if (ret)
    {
      obj_list.forEach(function(value, index)
      {
        value[FRIENDLY_PRINTED] = ret[index];
      });
    }
    fallback();
  };

  this._handle_queue = function(status, message, queue, index, queue_length, cb)
  {
    queue[index] = [status, message];
    if (queue.filter(Boolean).length == queue_length)
    {
      cb(queue);
    }
  };

  this._friendly_print_host = function(list)
  {
    const ELEMENT = 1;
    var ret = list.map(function(item)
    {
      var _class = item === null ? "" : Object.prototype.toString.call(item);
      if (/Element\]$/.test(_class))
      {
        return (
        [
          ELEMENT,
          item.nodeName.toLowerCase(),
          item.id,
          item.className,
          item.getAttribute('href'),
          item.getAttribute('src')
        ]);
      }
      return null;
    });
    return JSON.stringify(ret);
  };

  this.templates = function()
  {
    const
    ELEMENT_NAME = 1,
    ELEMENT_ID = 2,
    ELEMENT_CLASS = 3,
    ELEMENT_HREF = 4,
    ELEMENT_SRC = 5;

    var classes = {};
    classes[ELEMENT_NAME] = 'element-name';
    classes[ELEMENT_ID] = 'element-id';
    classes[ELEMENT_CLASS] = 'element-class';
    classes[ELEMENT_HREF] = 'element-href';
    classes[ELEMENT_SRC] = 'element-src';

    var print_values = {};
    print_values[ELEMENT_NAME] = function(val)
    {
      return val;
    };
    print_values[ELEMENT_ID] = function(val)
    {
      return '#' + val;
    };
    print_values[ELEMENT_CLASS] = function(val)
    {
      return '.' + val.replace(/\s+/g, '.');
    };
    print_values[ELEMENT_HREF] = function(val)
    {
      return ' ' + val;
    };
    print_values[ELEMENT_SRC] = function(val)
    {
      return ' ' + val;
    };

    this._friendly_print_element = function(value_list)
    {
      return value_list.reduce(function(list, prop, index)
      {
        if (index in classes && prop)
        {
          list.push(['span', print_values[index](prop), 'class', classes[index]]);
        }
        return list
      }, []);
    };

    this.friendly_print = function(value_list)
    {
      const
      TYPE = 0,
      ELEMENT = 1;

      var ret = [];
      switch (value_list[TYPE])
      {
        case ELEMENT:
        {
          return this._friendly_print_element(value_list);
        }
      }
    };

  };

  this._obj2obj_id_list = function(obj, index)
  {
    return obj[OBJECT_ID];
  };

  this._obj_id2str = function(object_id)
  {
    return object_id && "$_" + object_id || null;
  };

  this._create_arg_list = function(list, obj_id)
  {
    if (obj_id)
    {
      list.push(["$_" + obj_id, obj_id]);
    }
    return list;
  };

  this.value2objlist = function(list, item)
  {
    const OBJECT_VALUE = 1;
    if (item[OBJECT_VALUE])
    {
      list.push(item[OBJECT_VALUE]);
    }
    return list;
  };

  this.init = function()
  {
    this._tagman = window.tagManager;
    this._service = window.services['ecmascript-debugger'];
    this.templates.apply(window.templates || (window.tempoates = {}));
    this._friendly_print_host_str = "(" +
                                    this._friendly_print_host.toString() +
                                    ")([%s])";
  };

  this.init();

}
<commit_msg>Fixed friendly printing of class names.<commit_after>window.cls || (window.cls = {});

window.cls.FriendlyPrinter = function()
{
  const
  VALUE_LIST = 2,
  OBJECT_VALUE = 1,
  OBJECT_ID = 0,
  MAX_ARGS = 60;

  this._friendly_print = function(obj_list, rt_id, thread_id, frame_id, fallback)
  {
    var obj_ids = obj_list.map(this._obj2obj_id_list);
    var queue_cb = this._friendly_print_chunked_cb.bind(this, obj_list, rt_id,
                                                        obj_ids, fallback);
    var queue = [], queue_length = 0, processed_queue = [];
    // chunk the request, Eval is currently limited to 64 arguments
    // CORE-35198
    while (obj_ids.length > MAX_ARGS * queue_length)
    {
      queue.push(obj_ids.slice(queue_length++ * MAX_ARGS,
                               queue_length * MAX_ARGS));
    }
    queue.forEach(function(obj_ids, index)
    {
      var call_list = obj_ids.map(this._obj_id2str).join(',');
      var arg_list = obj_ids.reduce(this._create_arg_list, []);
      var tag = this._tagman.set_callback(this,
                                          this._handle_queue,
                                          [
                                            processed_queue,
                                            index,
                                            queue_length,
                                            queue_cb
                                          ]);
      var script = this._friendly_print_host_str.replace("%s", call_list);
      var msg = [rt_id, thread_id, frame_id, script, arg_list];
      this._service.requestEval(tag, msg);
    }, this);
  };

  this._friendly_print_chunked_cb = function(obj_list, rt_id, obj_ids,
                                             fallback, queue)
  {
    const
    STATUS = 0,
    MESSAGE = 1,
    VALUE = 2,
    VALUE_LIST = 2,
    DF_INTERN_TYPE = 3,
    FRIENDLY_PRINTED = 6,
    OBJECT_VALUE = 1;

    var ret = queue.reduce(function(list, response)
    {
      var status = response[STATUS], msg = response[MESSAGE];
      if (status || msg[STATUS] != "completed")
      {
        opera.postError('Pretty printing failed: ' + JSON.stringify(msg));
        return null;
      }
      if(list)
      {
        list.extend(JSON.parse(msg[VALUE]));
      }
      return list;
    }, []);

    if (ret)
    {
      obj_list.forEach(function(value, index)
      {
        value[FRIENDLY_PRINTED] = ret[index];
      });
    }
    fallback();
  };

  this._handle_queue = function(status, message, queue, index, queue_length, cb)
  {
    queue[index] = [status, message];
    if (queue.filter(Boolean).length == queue_length)
    {
      cb(queue);
    }
  };

  this._friendly_print_host = function(list)
  {
    const ELEMENT = 1;
    var ret = list.map(function(item)
    {
      var _class = item === null ? "" : Object.prototype.toString.call(item);
      if (/Element\]$/.test(_class))
      {
        return (
        [
          ELEMENT,
          item.nodeName.toLowerCase(),
          item.id,
          item.className,
          item.getAttribute('href'),
          item.getAttribute('src')
        ]);
      }
      return null;
    });
    return JSON.stringify(ret);
  };

  this.templates = function()
  {
    const
    ELE_NAME = 1,
    ELE_ID = 2,
    ELE_CLASS = 3,
    ELE_HREF = 4,
    ELE_SRC = 5;

    var classes = {};
    classes[ELE_NAME] = 'element-name';
    classes[ELE_ID] = 'element-id';
    classes[ELE_CLASS] = 'element-class';
    classes[ELE_HREF] = 'element-href';
    classes[ELE_SRC] = 'element-src';

    var print_val = {};
    print_val[ELE_NAME] = function(val) {return val;};
    print_val[ELE_ID] = function(val) {return '#' + val;};
    print_val[ELE_CLASS] = function(val)
    {
      return (' ' + val).replace(/\s+/g, '.');
    };
    print_val[ELE_HREF] = function(val) {return ' ' + val;};
    print_val[ELE_SRC] = function(val) {return ' ' + val;};

    this._friendly_print_element = function(value_list)
    {
      return value_list.reduce(function(list, prop, index)
      {
        if (index in classes && prop)
        {
          list.push(['span', print_values[index](prop), 'class', classes[index]]);
        }
        return list
      }, []);
    };

    this.friendly_print = function(value_list)
    {
      const
      TYPE = 0,
      ELEMENT = 1;

      var ret = [];
      switch (value_list[TYPE])
      {
        case ELEMENT:
        {
          return this._friendly_print_element(value_list);
        }
      }
    };

  };

  this._obj2obj_id_list = function(obj, index)
  {
    return obj[OBJECT_ID];
  };

  this._obj_id2str = function(object_id)
  {
    return object_id && "$_" + object_id || null;
  };

  this._create_arg_list = function(list, obj_id)
  {
    if (obj_id)
    {
      list.push(["$_" + obj_id, obj_id]);
    }
    return list;
  };

  this.value2objlist = function(list, item)
  {
    const OBJECT_VALUE = 1;
    if (item[OBJECT_VALUE])
    {
      list.push(item[OBJECT_VALUE]);
    }
    return list;
  };

  this.init = function()
  {
    this._tagman = window.tagManager;
    this._service = window.services['ecmascript-debugger'];
    this.templates.apply(window.templates || (window.tempoates = {}));
    this._friendly_print_host_str = "(" +
                                    this._friendly_print_host.toString() +
                                    ")([%s])";
  };

  this.init();

}
<|endoftext|>


<commit_before>// Move this to a configuration script file.
//var timeStep = 1.0; // Time in seconds.
//var gravityForce = Force("Gravity", [0, 0, -9.8]); // Force of gravity within the environment, in Newtons per Kilogram.
//var bigG = 6.674e-11; // The Gravitational Constant.

// Main logic module for ISAAC Physics.

function displayProperties (obj) {
	for(name in obj) {
		console.log("Property: " + name + " Value: " + obj[name]);
	}
	console.log("\n");
}

// Movement Module.
// Calls all other modules to modify an object's properties with regard to motion.
function movementModule (obj) {
	if(obj.switches.motionEnabled) {
		var gravityChanged = gravityModule(obj);
		var forceChanged = forceModule(obj);
		var accelerationChanged = accelerationModule(obj);
		var velocityChanged = velocityModule(obj);
		if (velocityChanged || accelerationChanged || gravityChanged || forceChanged) {
			return true;
		}
	}
	return false;
}

// Velocity Module.
// Adjusts the position of the object, based on the velocity vector.
function velocityModule (obj) {
	if (obj.switches.motionEnabled) {
		//		obj.Position.posX += (obj.Position.velX * timeStep);
		//		obj.Position.posY += (obj.Position.velY * timeStep);
		//		obj.Position.posZ += (obj.Position.velZ * timeStep);
		var basic = addVector(obj.motion.position, scaleVector(obj.motion.velocity, timeStep));
		obj.motion.position = addVector(basic, scaleVector(obj.motion.acceleration, Math.pow(timeStep, 2)));
		return true;
	}
	return false;
}

// Acceleration Module.
// Adjusts the velocity of the object, based on the acceleration vector.
function accelerationModule (obj) {
	if (obj.switches.accelerationEnabled) {
		//		obj.Position.velX += (obj.Position.accelX * timeStep);
		//		obj.Position.velY += (obj.Position.accelY * timeStep);
		//		obj.Position.velZ += (obj.Position.accelZ * timeStep);
		obj.motion.velocity = addVector(obj.motion.velocity, scaleVector(obj.motion.acceleration, timeStep));
		return true;
	}
	return false;
}

// Gravity Module.
// Adjusts the acceleration vector of the object to reflect the force of gravity.
// For the object to be affected by gravity, both gravityEnabled and accelerationEnabled must be true.
function gravityModule (obj) {
	if(obj.switches.gravityEnabled) {
		gravityForce.act(obj);
	}
	return true;
}
// Force Module.
// Calculates the acceleration of an object based on the resultant forces on it.
function forceModule (obj) {
	if (obj.switches.motionEnabled && obj.switches.forceChanged) {
		// Create a blank array for the resultant force.
		var newResultant = [0, 0, 0];

		// Iterate through the forces acting on the object and add them
		// to the resultant force.
		for(force in obj.forceStore) {
			for(var i = 0; i < 3; i++) {
				newResultant[i] += obj.forceStore[force][i];
			}
		}

		// Set the resultant force.
		obj.resultantForce = newResultant;

		// Adjust the object's acceleration based on the resultant force.
		for(var i = 0; i < 3; i++) {
			obj.motion.acceleration[i] = obj.resultantForce[i] / obj.physical.mass;
		}

		// Reset the forceChanged switch.
		obj.switches.forceChanged = false;
		return true;
	}
	return false;
}

// Contact function
// Given two objects, determines whether or not they are in contact
function contactBetween (obj1, obj2) {
	var distance = vectorLength(subtractVector(obj1.motion.position, obj2.motion.position));

	var radiiSum = obj1.physical.maxRadius + obj2.physical.maxRadius;

	// PS (Thu 19 Jan 2012 08:19:49 PM SGT) I feel this may be a better approach
	// var dSquare = sqrNormVector(distance);
	// var rSumSquare = sqr(radiiSum);
	// if (dSquare > rSumSquare) {

	if (distance > radiisum) {
		return false;
	}
	if (obj1.physical.shape + obj2.physical.shape === 2) { // Both are spheres
		return true; // If the sum of radii is <= distance between spheres, they are in contact
	}
	if (obj1.physical.shape + obj2.physical.shape === 8) { // Both are cuboids
		for (var i = 0; i < 6; i++) {
			if(obj2.physical.containsPoint(obj1.physical.corners[i]) ||
			obj1.physical.containsPoint(obj2.physical.corners[i])) {
				return true;
			}
		}
		return false;
	}
}

// Gravitational Attraction Function.
// Given two objects, calculate and return the magnitude of the force of gravitational attraction between them.
function gravitationalAttraction (obj1, obj2) {
	var distance = vectorLength(subtractVector(obj1.motion.position, obj2.motion.position));

	// Find r^2.

	// PS (Thu 19 Jan 2012 08:24:11 PM SGT) - See if the sqrNormVector approach is faster

	var rSquared = Math.pow(distance, 2);

	// Get the masses of the two objects.
	var mass1 = obj1.physical.mass;
	var mass2 = obj2.physical.mass;

	// Return the force between them.
	return bigG * ((mass1 * mass2) / rSquared);
}

// Gravitational Force Function.
// Given two objects, returns the vector of gravitational force between them, from the first object
// to the second.
function gravitationalForce (obj1, obj2) {
	// Get the force between the two objects.
	var force = gravitationalAttraction(obj1, obj2);

	// Get the direction vector from the first object to the second.
	var directionVector = subtractVector(obj1, obj2);

	// Scale the direction vector to be the same magnitude as the force.
	directionVector = vectorFitToLength(directionVector, force);

	return directionVector;
}<commit_msg>Minor fix to equation.<commit_after>// Move this to a configuration script file.
//var timeStep = 1.0; // Time in seconds.
//var gravityForce = Force("Gravity", [0, 0, -9.8]); // Force of gravity within the environment, in Newtons per Kilogram.
//var bigG = 6.674e-11; // The Gravitational Constant.

// Main logic module for ISAAC Physics.

function displayProperties (obj) {
	for(name in obj) {
		console.log("Property: " + name + " Value: " + obj[name]);
	}
	console.log("\n");
}

// Movement Module.
// Calls all other modules to modify an object's properties with regard to motion.
function movementModule (obj) {
	if(obj.switches.motionEnabled) {
		var gravityChanged = gravityModule(obj);
		var forceChanged = forceModule(obj);
		var accelerationChanged = accelerationModule(obj);
		var velocityChanged = velocityModule(obj);
		if (velocityChanged || accelerationChanged || gravityChanged || forceChanged) {
			return true;
		}
	}
	return false;
}

// Velocity Module.
// Adjusts the position of the object, based on the velocity vector.
function velocityModule (obj) {
	if (obj.switches.motionEnabled) {
		//		obj.Position.posX += (obj.Position.velX * timeStep);
		//		obj.Position.posY += (obj.Position.velY * timeStep);
		//		obj.Position.posZ += (obj.Position.velZ * timeStep);
		var basic = addVector(obj.motion.position, scaleVector(obj.motion.velocity, timeStep));
		obj.motion.position = addVector(basic, scaleVector(scaleVector(obj.motion.acceleration, Math.pow(timeStep, 2)), 0.5));
		return true;
	}
	return false;
}

// Acceleration Module.
// Adjusts the velocity of the object, based on the acceleration vector.
function accelerationModule (obj) {
	if (obj.switches.accelerationEnabled) {
		//		obj.Position.velX += (obj.Position.accelX * timeStep);
		//		obj.Position.velY += (obj.Position.accelY * timeStep);
		//		obj.Position.velZ += (obj.Position.accelZ * timeStep);
		obj.motion.velocity = addVector(obj.motion.velocity, scaleVector(obj.motion.acceleration, timeStep));
		return true;
	}
	return false;
}

// Gravity Module.
// Adjusts the acceleration vector of the object to reflect the force of gravity.
// For the object to be affected by gravity, both gravityEnabled and accelerationEnabled must be true.
function gravityModule (obj) {
	if(obj.switches.gravityEnabled) {
		gravityForce.act(obj);
	}
	return true;
}
// Force Module.
// Calculates the acceleration of an object based on the resultant forces on it.
function forceModule (obj) {
	if (obj.switches.motionEnabled && obj.switches.forceChanged) {
		// Create a blank array for the resultant force.
		var newResultant = [0, 0, 0];

		// Iterate through the forces acting on the object and add them
		// to the resultant force.
		for(force in obj.forceStore) {
			for(var i = 0; i < 3; i++) {
				newResultant[i] += obj.forceStore[force][i];
			}
		}

		// Set the resultant force.
		obj.resultantForce = newResultant;

		// Adjust the object's acceleration based on the resultant force.
		for(var i = 0; i < 3; i++) {
			obj.motion.acceleration[i] = obj.resultantForce[i] / obj.physical.mass;
		}

		// Reset the forceChanged switch.
		obj.switches.forceChanged = false;
		return true;
	}
	return false;
}

// Contact function
// Given two objects, determines whether or not they are in contact
function contactBetween (obj1, obj2) {
	var distance = vectorLength(subtractVector(obj1.motion.position, obj2.motion.position));

	var radiiSum = obj1.physical.maxRadius + obj2.physical.maxRadius;

	// PS (Thu 19 Jan 2012 08:19:49 PM SGT) I feel this may be a better approach
	// var dSquare = sqrNormVector(distance);
	// var rSumSquare = sqr(radiiSum);
	// if (dSquare > rSumSquare) {

	if (distance > radiisum) {
		return false;
	}
	if (obj1.physical.shape + obj2.physical.shape === 2) { // Both are spheres
		return true; // If the sum of radii is <= distance between spheres, they are in contact
	}
	if (obj1.physical.shape + obj2.physical.shape === 8) { // Both are cuboids
		for (var i = 0; i < 6; i++) {
			if(obj2.physical.containsPoint(obj1.physical.corners[i]) ||
			obj1.physical.containsPoint(obj2.physical.corners[i])) {
				return true;
			}
		}
		return false;
	}
}

// Gravitational Attraction Function.
// Given two objects, calculate and return the magnitude of the force of gravitational attraction between them.
function gravitationalAttraction (obj1, obj2) {
	var distance = vectorLength(subtractVector(obj1.motion.position, obj2.motion.position));

	// Find r^2.

	// PS (Thu 19 Jan 2012 08:24:11 PM SGT) - See if the sqrNormVector approach is faster

	var rSquared = Math.pow(distance, 2);

	// Get the masses of the two objects.
	var mass1 = obj1.physical.mass;
	var mass2 = obj2.physical.mass;

	// Return the force between them.
	return bigG * ((mass1 * mass2) / rSquared);
}

// Gravitational Force Function.
// Given two objects, returns the vector of gravitational force between them, from the first object
// to the second.
function gravitationalForce (obj1, obj2) {
	// Get the force between the two objects.
	var force = gravitationalAttraction(obj1, obj2);

	// Get the direction vector from the first object to the second.
	var directionVector = subtractVector(obj1, obj2);

	// Scale the direction vector to be the same magnitude as the force.
	directionVector = vectorFitToLength(directionVector, force);

	return directionVector;
}<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react'
import { each, omit, findIndex, map, last } from 'lodash'

import TreeFolder from '../../components/TreeFolder'
import TreeFile from '../../components/TreeFile'
import CircularProgress from 'material-ui/CircularProgress'
import classes from './TreeView.scss'

// redux-devsharev3
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { actions as TabActions } from '../../modules/tabs'
import { devshare, helpers } from 'redux-devshare'
const { isLoaded, isEmpty, dataToJS } = helpers

const fileEntityBlackList = ['.DS_Store', 'node_modules']

@devshare(
  ({ project }) =>
    ([
      `files/${project.owner}/${project.name}`
    ])
)
@connect(
  ({ devshare, tabs }, { project: { name, owner } }) =>
    ({
      tabs: tabs[`${owner}/${name}`] && tabs[`${owner}/${name}`].list ? tabs[`${owner}/${name}`].list : [],
      files: map(
        dataToJS(devshare, `files/${owner}/${name}`),
        (file, key) => Object.assign(file, { key })
      )
    }),
  // Map dispatch to props
  (dispatch) =>
    bindActionCreators(TabActions, dispatch)
)
export default class TreeView extends Component {

  static propTypes = {
    project: PropTypes.object.isRequired,
    files: PropTypes.array,
    tabs: PropTypes.array.isRequired,
    openTab: PropTypes.func.isRequired,
    navigateToTab: PropTypes.func.isRequired,
    fileStructure: PropTypes.arrayOf(PropTypes.shape({
      meta: PropTypes.shape({
        name: PropTypes.string.isRequired,
        path: PropTypes.string.isRequired
      })
    })),
    onRightClick: PropTypes.func
  }

  openFile = file => {
    const { project, tabs } = this.props
    const tabData = {
      title: file.name || file.path.split('/')[file.path.split('/').length - 1],
      type: 'file',
      file
    }

    // Search for already matching path
    const matchingInd = findIndex(tabs, (t) => t.file.path === tabData.file.path)
    // console.log('matching index:', tabs, tabData, matchingInd, )
    // Only open tab if file is not already open
    if (matchingInd === -1) {
      this.props.openTab(project, tabData)
      this.props.navigateToTab(project) // Select last tab
    } else {
      this.props.navigateToTab(project, matchingInd)
    }
  }

  onFilesAdd = (e) => {
    e.preventDefault()
    each(e.target.files, item => {
      if (fileEntityBlackList.indexOf(last(item.webkitRelativePath.split('/'))) === -1) {
        this.readAndSaveFileEntry(item)
      }
    })
  }

  getStructure = () => {
    if (!this.props.files || !this.props.files.length) {
      return null
    }
    return this.props.files.map((entry, i) => {
      // no metadata
      if (!entry.meta) {
        const firstChildPath = entry[Object.keys(entry)[0]].meta.path
        const childPathSplit = firstChildPath.split('/')
        entry.meta = {
          entityType: 'folder',
          name: entry.key,
          path: childPathSplit.slice(0, -1).join('/')
        }
      }

      // Folder
      if (entry.meta && (entry.meta.entityType === 'folder')) {
        const children = Object.assign({}, omit(entry, ['key', 'meta']))
        return (
          <TreeFolder
            key={`child-Folder-${i}-${entry.meta.name}`}
            index={i}
            data={entry.meta}
            isCollapsed={entry.isCollapsed}
            children={children}
            onFileClick={this.openFile}
            onRightClick={this.props.onRightClick}
          />
        )
      }

      // File
      return (
        <TreeFile
          key={`child-File-${i}-${entry.meta.name || entry.meta.path.split('/')[0]}`}
          index={i}
          data={entry.meta}
          active={entry.active}
          onClick={this.openFile}
          onRightClick={this.props.onRightClick}
          users={entry.users}
        />
      )
    })
  }

  render () {
    const { files } = this.props
    const structure = this.getStructure()
    if (!isLoaded(files)) {
      return (

              <CircularProgress size={0.75} />

      )
    }

    return (

          {
            !isEmpty(files)
            ? (

                {structure}

              )
            : (

                  Right click
                  OR
                  Drop files
                  to get started

                  Touch the Plus to get started

              )
          }

    )
  }
}
<commit_msg>fix(#131700877): opening new tab activates that tab<commit_after>import React, { PropTypes, Component } from 'react'
import { each, omit, findIndex, map, last } from 'lodash'

import TreeFolder from '../../components/TreeFolder'
import TreeFile from '../../components/TreeFile'
import CircularProgress from 'material-ui/CircularProgress'
import classes from './TreeView.scss'

// redux-devsharev3
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { actions as TabActions } from '../../modules/tabs'
import { devshare, helpers } from 'redux-devshare'
const { isLoaded, isEmpty, dataToJS, toJS } = helpers

const fileEntityBlackList = ['.DS_Store', 'node_modules']

@devshare(
  ({ project }) =>
    ([
      `files/${project.owner}/${project.name}`
    ])
)
@connect(
  ({devshare, tabs}, { project: { owner, name } }) => ({
      tabs: toJS(tabs)[`${owner}/${name}`] || { list: [], currentIndex: 0 },
      files: map(
        dataToJS(devshare, `files/${owner}/${name}`),
        (file, key) => Object.assign(file, { key })
      )
    }),
  // Map dispatch to props
  (dispatch) =>
    bindActionCreators(TabActions, dispatch)
)
export default class TreeView extends Component {

  static propTypes = {
    project: PropTypes.object.isRequired,
    files: PropTypes.array,
    tabs: PropTypes.object.isRequired,
    openTab: PropTypes.func.isRequired,
    navigateToTab: PropTypes.func.isRequired,
    fileStructure: PropTypes.arrayOf(PropTypes.shape({
      meta: PropTypes.shape({
        name: PropTypes.string.isRequired,
        path: PropTypes.string.isRequired
      })
    })),
    onRightClick: PropTypes.func
  }

  openFile = file => {
    const { project, tabs } = this.props
    const tabData = {
      title: file.name || file.path.split('/')[file.path.split('/').length - 1],
      type: 'file',
      file
    }

    // check if tab is already open
    let tabIndex = findIndex(tabs.list, (t) => t.file.path === tabData.file.path)

    // Only open tab if file is not already open
    if (tabIndex < 0) {
      this.props.openTab(project, tabData)
      tabIndex = tabs.list.length
    }

    // activate selected tab
    this.props.navigateToTab(project, tabIndex)
  }

  onFilesAdd = (e) => {
    e.preventDefault()
    each(e.target.files, item => {
      if (fileEntityBlackList.indexOf(last(item.webkitRelativePath.split('/'))) === -1) {
        this.readAndSaveFileEntry(item)
      }
    })
  }

  getStructure = () => {
    if (!this.props.files || !this.props.files.length) {
      return null
    }
    return this.props.files.map((entry, i) => {
      // no metadata
      if (!entry.meta) {
        const firstChildPath = entry[Object.keys(entry)[0]].meta.path
        const childPathSplit = firstChildPath.split('/')
        entry.meta = {
          entityType: 'folder',
          name: entry.key,
          path: childPathSplit.slice(0, -1).join('/')
        }
      }

      // Folder
      if (entry.meta && (entry.meta.entityType === 'folder')) {
        const children = Object.assign({}, omit(entry, ['key', 'meta']))
        return (
          <TreeFolder
            key={`child-Folder-${i}-${entry.meta.name}`}
            index={i}
            data={entry.meta}
            isCollapsed={entry.isCollapsed}
            children={children}
            onFileClick={this.openFile}
            onRightClick={this.props.onRightClick}
          />
        )
      }

      // File
      return (
        <TreeFile
          key={`child-File-${i}-${entry.meta.name || entry.meta.path.split('/')[0]}`}
          index={i}
          data={entry.meta}
          active={entry.active}
          onClick={this.openFile}
          onRightClick={this.props.onRightClick}
          users={entry.users}
        />
      )
    })
  }

  render () {
    const { files } = this.props
    const structure = this.getStructure()
    if (!isLoaded(files)) {
      return (

              <CircularProgress size={0.75} />

      )
    }

    return (

          {
            !isEmpty(files)
            ? (

                {structure}

              )
            : (

                  Right click
                  OR
                  Drop files
                  to get started

                  Touch the Plus to get started

              )
          }

    )
  }
}
<|endoftext|>