<commit_before>exports.run = async function(client, repository) {
  const repoName = repository.name;
  const repoOwner = repository.owner.login;

  const func = client.pullRequests.getAll({
    owner: repoOwner, repo: repoName, per_page: 100
  });
  const pullRequests = await client.getAll(client, [], func);

  pullRequests.forEach(async(p, index) => {
    setTimeout(() => {
      exports.check(client, p.number, repoName, repoOwner);
    }, index * 500);
  });
};

exports.check = async function(client, number, repoName, repoOwner) {
  const pull = await client.pullRequests.get({
    owner: repoOwner, repo: repoName, number: number
  });

  const mergeable = pull.data.mergeable;
  const author = pull.data.user.login;

  const comment = client.templates.get("mergeConflictWarning")
    .replace("[username]", author).replace("[repoOwner]", repoOwner)
    .replace("[repoName]", repoName);

  const comments = await client.issues.getComments({
    owner: repoOwner, repo: repoName, number: number, per_page: 100
  });

  const warnings = comments.data.filter(com => {
    // Use end of line comments to check if comment is from template
    const warn = com.body.endsWith("<!-- checkMergeConflictWarning -->");
    const fromClient = com.user.login === client.cfg.username;
    return warn && fromClient;
  });

  // Use a strict false check; unknown merge conflict statuses return undefined
  if (mergeable === false) {
    const commits = await client.pullRequests.getCommits({
      owner: repoOwner, repo: repoName, number: number, per_page: 100
    });
    const lastCommitTime = commits.data.slice(-1).pop().commit.committer.date;

    const labelComment = warnings.find(c => {
      return Date.parse(lastCommitTime) < Date.parse(c.created_at);
    });

    const labels = await client.issues.getIssueLabels({
      owner: repoOwner, repo: repoName, number: number
    });
    const inactive = labels.data.find(l => l.name === client.cfg.inactiveLabel);

    if (!labelComment && !inactive) {
      client.newComment(pull.data, pull.data.base.repo, comment);
    }
  } else if (mergeable && warnings.length) {
    warnings.forEach(c => {
      client.issues.deleteComment({
        owner: repoOwner, repo: repoName, id: c.id
      });
    });
  }
};
<commit_msg>pull requests: Fix merge conflict warning comment filter.<commit_after>exports.run = async function(client, repository) {
  const repoName = repository.name;
  const repoOwner = repository.owner.login;

  const func = client.pullRequests.getAll({
    owner: repoOwner, repo: repoName, per_page: 100
  });
  const pullRequests = await client.getAll(client, [], func);

  pullRequests.forEach(async(p, index) => {
    setTimeout(() => {
      exports.check(client, p.number, repoName, repoOwner);
    }, index * 500);
  });
};

exports.check = async function(client, number, repoName, repoOwner) {
  const pull = await client.pullRequests.get({
    owner: repoOwner, repo: repoName, number: number
  });

  const mergeable = pull.data.mergeable;
  const author = pull.data.user.login;

  const comment = client.templates.get("mergeConflictWarning")
    .replace("[username]", author).replace("[repoOwner]", repoOwner)
    .replace("[repoName]", repoName);

  const comments = await client.issues.getComments({
    owner: repoOwner, repo: repoName, number: number, per_page: 100
  });

  const warnings = comments.data.filter(com => {
    // Use end of line comments to check if comment is from template
    const warn = com.body.endsWith("<!-- mergeConflictWarning -->");
    const fromClient = com.user.login === client.cfg.username;
    return warn && fromClient;
  });

  // Use a strict false check; unknown merge conflict statuses return undefined
  if (mergeable === false) {
    const commits = await client.pullRequests.getCommits({
      owner: repoOwner, repo: repoName, number: number, per_page: 100
    });
    const lastCommitTime = commits.data.slice(-1).pop().commit.committer.date;

    const labelComment = warnings.find(c => {
      return Date.parse(lastCommitTime) < Date.parse(c.created_at);
    });

    const labels = await client.issues.getIssueLabels({
      owner: repoOwner, repo: repoName, number: number
    });
    const inactive = labels.data.find(l => l.name === client.cfg.inactiveLabel);

    if (!labelComment && !inactive) {
      client.newComment(pull.data, pull.data.base.repo, comment);
    }
  } else if (mergeable && warnings.length) {
    warnings.forEach(c => {
      client.issues.deleteComment({
        owner: repoOwner, repo: repoName, id: c.id
      });
    });
  }
};
<|endoftext|>


<commit_before>'use strict';
var React = require('react');
var globals = require('./globals');
var mixins = require('./mixins');
var navigation = require('../libs/bootstrap/navigation');
var jsonScriptEscape = require('../libs/jsonScriptEscape');
var url = require('url');

var NavbarMixin = navigation.NavbarMixin;
var Navbar = navigation.Navbar;
var Nav = navigation.Nav;
var NavItem = navigation.NavItem;

var routes = {
    'curator': require('./curator').Curator
};

// Site information, including navigation
var portal = {
    portal_title: 'ClinGen',
    navUser: [
        {id: 'dashboard', title: 'Dashboard', icon: 'icon-home', url: '/dashboard/'},
        //{id: 'account', title: 'Account', url: '/account/'},
        {id: 'loginout', title: 'Login'}
    ]
};

// Renders HTML common to all pages.
var App = module.exports = React.createClass({
    mixins: [mixins.Persona, mixins.HistoryAndTriggers],

    triggers: {
        login: 'triggerLogin',
        logout: 'triggerLogout',
    },

    getInitialState: function() {
        return {
            errors: [],
            portal: portal
        };
    },

    render: function() {
        var content;
        var context = this.props.context;
        var href_url = url.parse(this.props.href);
        var hash = href_url.hash || '';
        var name;
        var context_actions = [];
        if (hash.slice(0, 2) === '#!') {
            name = hash.slice(2);
        }

        var key = context && context['@id'];
        if (context) {
            Array.prototype.push.apply(context_actions, context.actions || []);
            if (!name && context.default_page) {
                context = context.default_page;
                var actions = context.actions || [];
                for (var i = 0; i < actions.length; i++) {
                    var action = actions[i];
                    if (action.href[0] == '#') {
                        action.href = context['@id'] + action.href;
                    }
                    context_actions.push(action);
                }
            }

            var ContentView = globals.content_views.lookup(context, name);
            content = <ContentView {...this.props} context={context}
                loadingComplete={this.state.loadingComplete} session={this.state.session}
                portal={this.state.portal} navigate={this.navigate} />;
        }
        var errors = this.state.errors.map(function (error) {
            return

;
        });

        var canonical = this.props.href;
        if (context.canonical_uri) {
            if (href_url.host) {
                canonical = (href_url.protocol || '') + '//' + href_url.host + context.canonical_uri;
            } else {
                canonical = context.canonical_uri;
            }
        }

        return (

                    <meta charSet="utf-8" />
                    <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                    <title>ClinGen</title>
                    <link rel="canonical" href={canonical} />

                    <link rel="stylesheet" href="/static/css/style.css" />

                        <Notice noticeType='danger' noticeMessage={Note: This is a demo version of the site. Any data you enter will not be permanently saved.} />
                        {content}

        );
    },

    statics: {
        // Get data to display from page

                    <link rel="stylesheet" href="/static/css/style.css" />

                        <Notice noticeType='danger' noticeMessage={Note: This is a demo version of the site. Any data you enter will not be permanently saved.} />
                        {content}

        );
    },

    statics: {
        // Get data to display from page


<commit_before>'use strict';
var React = require('react');
var globals = require('./globals');
var mixins = require('./mixins');
var navigation = require('../libs/bootstrap/navigation');
var jsonScriptEscape = require('../libs/jsonScriptEscape');
var url = require('url');

var NavbarMixin = navigation.NavbarMixin;
var Navbar = navigation.Navbar;
var Nav = navigation.Nav;
var NavItem = navigation.NavItem;

var routes = {
    'curator': require('./curator').Curator
};

// Site information, including navigation
var portal = {
    portal_title: 'ClinGen',
    navUser: [
        {id: 'help', title: 'Curation Help', icon: 'icon-question-circle',
            url: '/static/help/clingen-variant-curation-help.pdf', target: '_blank'}, // link to Curation Help
        {id: 'variant', title: 'New Variant Curation', url: '/select-variant/'}, // link to VCI page /select-variant/
        {id: 'gene', title: 'New Gene Curation', url: '/create-gene-disease/'}, // link to GCI page /create-gene-disease/
        {id: 'space', title: 'space'}, // white space between
        {id: 'dashboard', title: 'Dashboard', icon: 'icon-home', url: '/dashboard/'},
        {id: 'demo', title: 'Demo Login'},
        {id: 'loginout', title: 'Login'}
        //{id: 'account', title: 'Account', url: '/account/'},
    ]
};

// Renders HTML common to all pages.
var App = module.exports = React.createClass({
    mixins: [mixins.Auth0, mixins.HistoryAndTriggers],

    triggers: {
        demo: 'triggerAutoLogin',
        login: 'triggerLogin',
        logout: 'triggerLogout'
    },

    // Note on context. state.context set from initial props. Navigating to other pages sets this state.
    // This state gets passed as a property to ContentView, so it should be referenced as props.context
    // from there.
    getInitialState: function() {
        var demoWarning = false;
        var productionWarning = false;
        if (/production.clinicalgenome.org/.test(url.parse(this.props.href).hostname)) {
            // check if production URL. Enable productionWarning if it is.
            productionWarning = true;
        } else if (!/^(www\.)?curation.clinicalgenome.org/.test(url.parse(this.props.href).hostname)) {
            // if neither production nor curation URL, enable demoWarning.
            demoWarning = true;
        }
        return {
            context: this.props.context, // Close to anti-pattern, but puts *initial* context into state
            slow: this.props.slow,
            href: this.props.href,
            errors: [],
            portal: portal,
            demoWarning: demoWarning,
            productionWarning: productionWarning
        };
    },

    currentAction: function() {
        var href_url = url.parse(this.state.href);
        var hash = href_url.hash || '';
        var name;
        if (hash.slice(0, 2) === '#!') {
            name = hash.slice(2);
        }
        return name;
    },

    render: function() {
        var content;
        var context = this.state.context;
        var href_url = url.parse(this.state.href);
        // Switching between collections may leave component in place
        var key = context && context['@id'];
        var current_action = this.currentAction();
        if (!current_action && context.default_page) {
            context = context.default_page;
        }
        if (context) {
            var ContentView = globals.content_views.lookup(context, current_action);
            content = <ContentView {...this.props} context={context} href={this.state.href}
                loadingComplete={this.state.loadingComplete} session={this.state.session}
                portal={this.state.portal} navigate={this.navigate} href_url={href_url}
                demoVersion={this.state.demoWarning} />;
        }
        var errors = this.state.errors.map(function (error) {
            return

;
        });

        var appClass = 'done';
        if (this.state.slow) {
            appClass = 'communicating';
        }

        var title = context.title || context.name || context.accession || context['@id'];
        if (title && title != 'Home') {
            title = title + ' – ' + portal.portal_title;
        } else {
            title = portal.portal_title;
        }

        var canonical = this.props.href;
        if (context.canonical_uri) {
            if (href_url.host) {
                canonical = (href_url.protocol || '') + '//' + href_url.host + context.canonical_uri;
            } else {
                canonical = context.canonical_uri;
            }
        }

        return (

                    <meta charSet="utf-8" />
                    <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
                    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                    <title>ClinGen</title>
                    <link rel="canonical" href={canonical} />

                    <link rel="stylesheet" href="@@cssFile" />

                        {this.state.demoWarning ?
                        <Notice noticeType='demo' noticeMessage={Note: This is a demo version of the site. Any data you enter will not be permanently saved.} />
                        : null}
                        {this.state.productionWarning ?
                        <Notice noticeType='production' noticeMessage={Do not use this URL for entering data. Please use curation.clinicalgenome.org instead.} />
                        : null}
                        {content}

        );
    },

    statics: {
        // Get data to display from page

                    <link rel="stylesheet" href="@@cssFile" />

                        {this.state.demoWarning ?
                        <Notice noticeType='demo' noticeMessage={Note: This is a demo version of the site. Any data you enter will not be permanently saved.} />
                        : null}
                        {this.state.productionWarning ?
                        <Notice noticeType='production' noticeMessage={Do not use this URL for entering data. Please use curation.clinicalgenome.org instead.} />
                        : null}
                        {content}

        );
    },

    statics: {
        // Get data to display from page


<commit_before>(function () {
    'use strict';
    /*jslint nomen: true, browser: true*/
    /*global _,console,d3*/

    var lifeline = [],
        util = {},
        treeLifeline = [],  // tree-like representation of the lifeline
        buckets = [],       // nodes per level
        timePeriod = 1;

    // Vertex: a process thread; Edge: the event of sending/recieving a tag
    function Vertex(pid, tid, time) {
        this.pid = pid;
        this.tid = tid;
        this.time = time;
    }

    function Node(vertex, children) {
        this.vertex = vertex;
        this.children = children;

        this.addChild = function addChild(childVertex) {
            var childNode = new Node(childVertex, []);
            children.push(childNode);
        };
    }

    function BucketNode(vertex, treeNum) {
        this.vertex = vertex;
        this.treeNum = treeNum;
    }

    function loadLifeline() {
        util.ajaxget('/lifeline.json', function (response) {
            lifeline = JSON.parse(response);
        }, false);
    }

    // return tree, time
    // finding a parent - check all vertices on the level
    function findParent(vertex, bucket) {
        _.each(bucket, function (bNode) {
            if (vertex.pid === bNode.vertex.pid && vertex.tid === bNode.vertex.tid) {
                return bNode;
            }
        });
        return 0;
    }

    function addTreeChild(tree, curLevel, goalLevel, parentVertex, childVertex) {
        if (curLevel === goalLevel) {
            var vertex = tree.vertex;
            if (vertex.pid === parentVertex.pid && vertex.tid === parentVertex.tid && vertex.time === parentVertex.time) {
                tree.addChild(childVertex);
                return;
            }
        } else {
            _.each(tree.children, function (child) {
                addTreeChild(child, curLevel + 1, goalLevel, parentVertex, childVertex);
            });
        }
    }

    function addToBucket(level, vertex, treeNum) {
        var bucket = buckets[level] || [],
            bNode;
        if (bucket.length > 0) {
            _.each(bucket, function (bNode) {
                if (vertex.pid === bNode.vertex.pid && vertex.tid === bNode.vertex.tid) { // check if similar node is already in the bucket
                    bNode.treeNum = treeNum;
                    bNode.vertex.time = vertex.time;
                    return;
                }
            });
        } else {
            buckets[level] = [];
        }
        bNode = new BucketNode(vertex, treeNum);
        buckets[level].push(bNode);
    }

    function parseLifelineData() {
        _.each(lifeline, function (node) {
            var vert = new Vertex(node.dstProcessId, node.dstThreadId, node.time),
                parent = new Vertex(node.srcProcessId, node.srcThreadId, node.time),
                parentBucketNode,
                level = Math.floor(node.time / timePeriod),                           // actual tree level based on time
                tree,
                rootNode,
                bucket;

            // find parent process: look through each level down to roots
            while (level >= 0) {
                bucket = buckets[level] || [];
                parentBucketNode = findParent(parent, bucket);
                if (parentBucketNode) {
                    break;
                }
                level -= 1;
            }

            // have a parent, go to parent in identified tree and add the child -- update parent in bucket
            if (parentBucketNode) {
                tree = treeLifeline[parentBucketNode.treeNum];                 // a root Node
                addTreeChild(tree, 0, level, parentBucketNode.vertex, vert);
                addToBucket(level + 1, vert, parentBucketNode.treeNum);              // add child to the right bucket

                // do not have a parent in our current trees, create a new root == level 0
            } else {
                rootNode = new Node(parent, []);
                rootNode.addChild(vert);
                treeLifeline.push(rootNode);
                addToBucket(0, parent, treeLifeline.length - 1);
                addToBucket(1, vert, treeLifeline.length - 1);
            }
        });
    }

    /**
     * Updates the tree visualization
     * @param {Object} root - The root node of the tree
     * @param {Object} source - The source node of the update
    */
    function update(root, source, diagonal, tree, animationDuration, vis) {
        // Toggle children on click.
        function click(d) {
            if (d.children) {
                d._children = d.children;
                d.children = null;
            } else {
                d.children = d._children;
                d._children = null;
            }
            update(root, d, diagonal, tree, animationDuration, vis);
        }

        var nodes = tree.nodes(source).reverse(), // result is an array of objs with x and y locations (+vertex info)
            nodeIdentifier,
            nodeEnter,  // the enter set of node elements (i.e. all new nodes on screen)
            link,
            node;

        // when we have more than 1 tree, needs more support in other parts of code
        /*for (var i=0; i<source.length; i++) {
            if (nodes) {
                _.each(tree.nodes(source[i]).reverse(), function(node) { nodes.push(node) });
            } else {
                nodes = tree.nodes(source[i]).reverse();
            }
        }*/

        // creates as many g.node as vertices in tree
        nodeIdentifier = 0;
        node = vis.selectAll("g.node")    // selects elements that don't exist in order to create new ones == empty selection
            .data(nodes, function (d) {   // all nodes data ends up as placeholder nodes for missing elements in enter()
                nodeIdentifier += 1;
                if (!d.id) {
                    d.id = nodeIdentifier;
                }
                return d.id;
            });

        /****** Dealing will all new node elements ******/

        // for every node placeholder in enter set, add the missing elements to the SVG
        // returns a list of SVG g elements (with node object in their data attrib)
        nodeEnter = node.enter()
            .append("svg:g")
            .attr("class", "node");

        // to each g elements add a SVG circle element (~~ as a child)
        nodeEnter.append("svg:circle")
            .attr("r", 4.5)
            .style("fill", function (d) { return d._children ? "lightsteelblue" : "#fff"; })
            .on("click", click);

        // to each g element add a SVG text element (~~ another child)
        nodeEnter.append("svg:text")
            .attr("x", -5)//function(d) { return d._children ? -8 : 8; }) --> used by original
            .attr("y", 18)
            .text(function (d) {
                return "process : " + d.pid + " thread : " + d.tid;
            });

        // Transition the g elements to their new position (duration controls speed: higher == slower)
        nodeEnter.transition()
            .duration(animationDuration)
            .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; }) // translate to nodes x & y pos.
            .style("opacity", 1)
            .select("circle")
            .style("fill", "lightsteelblue");

        /****** done with new node elements ******/

        // the update set (I believe)
        node.transition()
            .duration(animationDuration)
            .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; })
            .style("opacity", 1);

        // The exit set -- remove any elements we don't need from screen
        node.exit().transition()
            .duration(animationDuration)
            .attr("transform", function () { return "translate(" + source.y + "," + source.x + ")"; })
            .style("opacity", 1e-6)
            .remove();

        /****** Vertex connection edges ******/

        // returns an array of objects representing the links from parent to child for each node ({source, target})
        link = vis.selectAll("path.link")
            .data(tree.links(nodes), function (d) { return d.target.id; });

        // form any new links
        link.enter().insert("svg:path", "g")
            .attr("class", "link")
            .attr("d", function () {
                var o = {x: source.x0, y: source.y0};
                return diagonal({source: o, target: o});
            })
            .transition()
            .duration(animationDuration)
            .attr("d", diagonal);

        // Transition links to their new position.
        link.transition()
            .duration(animationDuration)
            .attr("d", diagonal);

        // remove any of the links that are no longer necessary
        link.exit().transition()
            .duration(animationDuration)
            .attr("d", function () {
                var o = {x: source.x, y: source.y};
                return diagonal({source: o, target: o});
            })
            .remove();

        /****** done with link construction ******/

        // Stash the old positions for transition.
        nodes.forEach(function (d) {
            d.x0 = d.x;
            d.y0 = d.y;
        });
    }

    function drawLifelineTree() {
        // want to draw from treeLifeline structure
        d3.json("tree_example.json", function (json) {
            _.each(json, function (tree) {

                var w = 800,//960,  the width and height of the whole svg arrea
                    h = 700,//2000;
                    tree = d3.layout.tree().size([h, w - 160]),
                    animationDuration = 500,
                    diagonal,
                    vis;

                diagonal = d3.svg.diagonal().projection(function (d) {
                    return [d.y, d.x];
                });

                // creates an SVG canvas
                vis = d3.select("#lifeline")
                    .append("svg:svg")
                    .attr("width", w)
                    .attr("height", h)
                    .append("svg:g")
                    .attr("transform", "translate(20,0)"); //moves the initial position of the svg:g element

                tree.x0 = 300;//800;
                tree.y0 = 0;
                update(tree, tree, diagonal, tree, animationDuration, vis);
            });
        });
    }

    function windowLoadHandler() {
        loadLifeline();
        parseLifelineData();
        drawLifelineTree();
    }

    window.addEventListener('load', windowLoadHandler, false);

    /* Utilities */

    util.ajaxget = function (url, callback, async) {
        var r = util.getAjaxRequest(callback);
        r.open("GET", url, async);
        r.send(null);
    };

    util.getAjaxRequest = function (callback) {
        var ajaxRequest;

        try {
            ajaxRequest = new XMLHttpRequest();
        } catch (e) {
            /*global ActiveXObject*/
            try {
                ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e2) {
                try {
                    ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e3) {
                    return null;
                }
            }
        }

        ajaxRequest.onreadystatechange = function () {
            if (ajaxRequest.readyState === 4) {
                // TODO error response checking
                callback(ajaxRequest.responseText);
            }
        };

        return ajaxRequest;
    };

}());

<commit_msg>fix bug: json was being overwritten by tree<commit_after>(function () {
    'use strict';
    /*jslint nomen: true, browser: true*/
    /*global _,console,d3*/

    var lifeline = [],
        util = {},
        treeLifeline = [],  // tree-like representation of the lifeline
        buckets = [],       // nodes per level
        timePeriod = 1;

    // Vertex: a process thread; Edge: the event of sending/recieving a tag
    function Vertex(pid, tid, time) {
        this.pid = pid;
        this.tid = tid;
        this.time = time;
    }

    function Node(vertex, children) {
        this.vertex = vertex;
        this.children = children;

        this.addChild = function addChild(childVertex) {
            var childNode = new Node(childVertex, []);
            children.push(childNode);
        };
    }

    function BucketNode(vertex, treeNum) {
        this.vertex = vertex;
        this.treeNum = treeNum;
    }

    function loadLifeline() {
        util.ajaxget('/lifeline.json', function (response) {
            lifeline = JSON.parse(response);
        }, false);
    }

    // return tree, time
    // finding a parent - check all vertices on the level
    function findParent(vertex, bucket) {
        _.each(bucket, function (bNode) {
            if (vertex.pid === bNode.vertex.pid && vertex.tid === bNode.vertex.tid) {
                return bNode;
            }
        });
        return 0;
    }

    function addTreeChild(tree, curLevel, goalLevel, parentVertex, childVertex) {
        if (curLevel === goalLevel) {
            var vertex = tree.vertex;
            if (vertex.pid === parentVertex.pid && vertex.tid === parentVertex.tid && vertex.time === parentVertex.time) {
                tree.addChild(childVertex);
                return;
            }
        } else {
            _.each(tree.children, function (child) {
                addTreeChild(child, curLevel + 1, goalLevel, parentVertex, childVertex);
            });
        }
    }

    function addToBucket(level, vertex, treeNum) {
        var bucket = buckets[level] || [],
            bNode;
        if (bucket.length > 0) {
            _.each(bucket, function (bNode) {
                if (vertex.pid === bNode.vertex.pid && vertex.tid === bNode.vertex.tid) { // check if similar node is already in the bucket
                    bNode.treeNum = treeNum;
                    bNode.vertex.time = vertex.time;
                    return;
                }
            });
        } else {
            buckets[level] = [];
        }
        bNode = new BucketNode(vertex, treeNum);
        buckets[level].push(bNode);
    }

    function parseLifelineData() {
        _.each(lifeline, function (node) {
            var vert = new Vertex(node.dstProcessId, node.dstThreadId, node.time),
                parent = new Vertex(node.srcProcessId, node.srcThreadId, node.time),
                parentBucketNode,
                level = Math.floor(node.time / timePeriod),                           // actual tree level based on time
                tree,
                rootNode,
                bucket;

            // find parent process: look through each level down to roots
            while (level >= 0) {
                bucket = buckets[level] || [];
                parentBucketNode = findParent(parent, bucket);
                if (parentBucketNode) {
                    break;
                }
                level -= 1;
            }

            // have a parent, go to parent in identified tree and add the child -- update parent in bucket
            if (parentBucketNode) {
                tree = treeLifeline[parentBucketNode.treeNum];                 // a root Node
                addTreeChild(tree, 0, level, parentBucketNode.vertex, vert);
                addToBucket(level + 1, vert, parentBucketNode.treeNum);              // add child to the right bucket

                // do not have a parent in our current trees, create a new root == level 0
            } else {
                rootNode = new Node(parent, []);
                rootNode.addChild(vert);
                treeLifeline.push(rootNode);
                addToBucket(0, parent, treeLifeline.length - 1);
                addToBucket(1, vert, treeLifeline.length - 1);
            }
        });
    }

    /**
     * Updates the tree visualization
     * @param {Object} root - The root node of the tree
     * @param {Object} source - The source node of the update
    */
    function update(root, source, diagonal, tree, animationDuration, vis) {
        // Toggle children on click.
        function click(d) {
            if (d.children) {
                d._children = d.children;
                d.children = null;
            } else {
                d.children = d._children;
                d._children = null;
            }
            update(root, d, diagonal, tree, animationDuration, vis);
        }

        var nodes = tree.nodes(source).reverse(), // result is an array of objs with x and y locations (+vertex info)
            nodeIdentifier,
            nodeEnter,  // the enter set of node elements (i.e. all new nodes on screen)
            link,
            node;

        // when we have more than 1 tree, needs more support in other parts of code
        /*for (var i=0; i<source.length; i++) {
            if (nodes) {
                _.each(tree.nodes(source[i]).reverse(), function(node) { nodes.push(node) });
            } else {
                nodes = tree.nodes(source[i]).reverse();
            }
        }*/

        // creates as many g.node as vertices in tree
        nodeIdentifier = 0;
        node = vis.selectAll("g.node")    // selects elements that don't exist in order to create new ones == empty selection
            .data(nodes, function (d) {   // all nodes data ends up as placeholder nodes for missing elements in enter()
                nodeIdentifier += 1;
                if (!d.id) {
                    d.id = nodeIdentifier;
                }
                return d.id;
            });

        /****** Dealing will all new node elements ******/

        // for every node placeholder in enter set, add the missing elements to the SVG
        // returns a list of SVG g elements (with node object in their data attrib)
        nodeEnter = node.enter()
            .append("svg:g")
            .attr("class", "node");

        // to each g elements add a SVG circle element (~~ as a child)
        nodeEnter.append("svg:circle")
            .attr("r", 4.5)
            .style("fill", function (d) { return d._children ? "lightsteelblue" : "#fff"; })
            .on("click", click);

        // to each g element add a SVG text element (~~ another child)
        nodeEnter.append("svg:text")
            .attr("x", -5)//function(d) { return d._children ? -8 : 8; }) --> used by original
            .attr("y", 18)
            .text(function (d) {
                return "process : " + d.pid + " thread : " + d.tid;
            });

        // Transition the g elements to their new position (duration controls speed: higher == slower)
        nodeEnter.transition()
            .duration(animationDuration)
            .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; }) // translate to nodes x & y pos.
            .style("opacity", 1)
            .select("circle")
            .style("fill", "lightsteelblue");

        /****** done with new node elements ******/

        // the update set (I believe)
        node.transition()
            .duration(animationDuration)
            .attr("transform", function (d) { return "translate(" + d.y + "," + d.x + ")"; })
            .style("opacity", 1);

        // The exit set -- remove any elements we don't need from screen
        node.exit().transition()
            .duration(animationDuration)
            .attr("transform", function () { return "translate(" + source.y + "," + source.x + ")"; })
            .style("opacity", 1e-6)
            .remove();

        /****** Vertex connection edges ******/

        // returns an array of objects representing the links from parent to child for each node ({source, target})
        link = vis.selectAll("path.link")
            .data(tree.links(nodes), function (d) { return d.target.id; });

        // form any new links
        link.enter().insert("svg:path", "g")
            .attr("class", "link")
            .attr("d", function () {
                var o = {x: source.x0, y: source.y0};
                return diagonal({source: o, target: o});
            })
            .transition()
            .duration(animationDuration)
            .attr("d", diagonal);

        // Transition links to their new position.
        link.transition()
            .duration(animationDuration)
            .attr("d", diagonal);

        // remove any of the links that are no longer necessary
        link.exit().transition()
            .duration(animationDuration)
            .attr("d", function () {
                var o = {x: source.x, y: source.y};
                return diagonal({source: o, target: o});
            })
            .remove();

        /****** done with link construction ******/

        // Stash the old positions for transition.
        nodes.forEach(function (d) {
            d.x0 = d.x;
            d.y0 = d.y;
        });
    }

    function drawLifelineTree() {
        // want to draw from treeLifeline structure
        d3.json("tree_example.json", function (json) {
            _.each(json, function (jsonTree) {

                var w = 800,//960,  the width and height of the whole svg arrea
                    h = 700,//2000;
                    tree = d3.layout.tree().size([h, w - 160]),
                    animationDuration = 500,
                    diagonal,
                    vis;

                diagonal = d3.svg.diagonal().projection(function (d) {
                    return [d.y, d.x];
                });

                // creates an SVG canvas
                vis = d3.select("#lifeline")
                    .append("svg:svg")
                    .attr("width", w)
                    .attr("height", h)
                    .append("svg:g")
                    .attr("transform", "translate(20,0)"); //moves the initial position of the svg:g element

                jsonTree.x0 = 300;//800;
                jsonTree.y0 = 0;
                update(jsonTree, jsonTree, diagonal, tree, animationDuration, vis);
            });
        });
    }

    function windowLoadHandler() {
        loadLifeline();
        parseLifelineData();
        drawLifelineTree();
    }

    window.addEventListener('load', windowLoadHandler, false);

    /* Utilities */

    util.ajaxget = function (url, callback, async) {
        var r = util.getAjaxRequest(callback);
        r.open("GET", url, async);
        r.send(null);
    };

    util.getAjaxRequest = function (callback) {
        var ajaxRequest;

        try {
            ajaxRequest = new XMLHttpRequest();
        } catch (e) {
            /*global ActiveXObject*/
            try {
                ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e2) {
                try {
                    ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e3) {
                    return null;
                }
            }
        }

        ajaxRequest.onreadystatechange = function () {
            if (ajaxRequest.readyState === 4) {
                // TODO error response checking
                callback(ajaxRequest.responseText);
            }
        };

        return ajaxRequest;
    };

}());

<|endoftext|>


<commit_before>import React, {Component} from 'react';
import * as T from "prop-types";
import './styles.scss';
import {cssClassName} from 'utils'
const cn = cssClassName('SE_Ambassadors')
import Meta from './meta'
import A_Container from 'A_Container'
import O_Hero from 'O_Hero'
import A_H from 'A_H'
import A_P from 'A_P'
import A_Image from 'A_Image'
import A_Btn from 'A_Btn'
import M_Dropdown from 'M_Dropdown'
import M_Tooltip from 'M_Tooltip'
import A_Link from 'A_Link'
import O_TextUsHere from 'O_TextUsHere'

class SE_Ambassadors  extends Component {

  state = {
    filter: 'All',
  }

  nodes = []

  componentDidMount() {
    document.addEventListener('resize', this.forceUpdate);
    this.forceUpdate()
  }

  componentWillUnmount() {
    document.removeEventListener('resize', this.forceUpdate);
  }

  getAmbassadors(entities, filter) {
    let filtered
    if (filter == 'All') {
      filtered = entities
    } else {
      filtered = entities.filter(entity => entity.country === filter)
    }

    let _renderedAmbassadors = filtered.map((partner, i) => {
      let tooltipPlace;
      if (
        this.nodes[0]
        && this.nodes[i + 1]
        && (this.nodes[0].offsetLeft + this.nodes[i + 1].offsetLeft > 200)
      ) {
        tooltipPlace = 'left'
      } else {
        tooltipPlace = 'right'
      }

      return (

 this.nodes[i + 1] = node}
        >

          <A_Image
            src={partner.logoLink2x}
            alt={partner.name}
          />

            <M_Tooltip type={tooltipPlace}>
              <A_H type='tooltip'>{partner.name}</A_H>
               this.setState({filter: partner.country})} style={{cursor: 'pointer'}}>
                <A_H type='tooltip-sub'>{partner.country}</A_H>

              {partner.bio}
            </M_Tooltip>

            <A_Link to={partner.link} external type="block" >{' '}</A_Link>

      )
    })

    for (let i = 0; i < 7; i++) {
      _renderedAmbassadors.push(

      )
    }
    return _renderedAmbassadors
  }

  render() {
    const {countries, entities} = this.props
    const options = ['All', ...countries]

    const {filter} = this.state
    return (

        <Meta />
        <A_Container type="section">
          <O_Hero img={{src: "/img/illustrations/ambassadors.svg", alt: "ambassadors"}}>
            <A_H type="hero">Our Global Team</A_H>
            <A_P type="hero">At Humaniq, everything we do is motivated by our wish to provide the most widespread access to banking possible.</A_P>
          </O_Hero>
          <A_H type="section">Ever growing network</A_H>
          <A_P type="third">We want to communicate directly with the people we wish to serve: the unbanked. People without access to banking live in very rural areas. This is why we’ve started our Ambassador Program. Our ambassadors live in these developing countries and know the culture well. They are helping to promote cryptocurrencies in the Global South, as well as explaining the Humaniq project and app to the people in their countries.</A_P>

              <M_Dropdown
                selected={filter}
                options={options}
                onChange={filter => this.setState({filter})}
              />

            <A_Btn
              type="material-r-link"
              to='/form/ambassadors'
            >Join Ambassadors Program</A_Btn>

 this.nodes[0] = node}
            >
              {this.getAmbassadors(entities, filter)}

        </A_Container>
        <A_Container type="equal">

          <O_TextUsHere
            {...{
              title: 'Join Ambassadors',
              text: 'If you believe you can help your community, join Humaniq global Ambassador\'s programme.',
              link: {
                linkText: 'Join Humaniq Network',
                url: 'mailto:info@humaniq.com'
              }
            }}
          />
        </A_Container>

    )
  }
}

SE_Ambassadors .propTypes = {
  entities: T.array.isRequired,
  countries: T.array.isRequired
};

export default SE_Ambassadors
<commit_msg>[update] hide last block on ambasador page<commit_after>import React, {Component} from 'react';
import * as T from "prop-types";
import './styles.scss';
import {cssClassName} from 'utils'
const cn = cssClassName('SE_Ambassadors')
import Meta from './meta'
import A_Container from 'A_Container'
import O_Hero from 'O_Hero'
import A_H from 'A_H'
import A_P from 'A_P'
import A_Image from 'A_Image'
import A_Btn from 'A_Btn'
import M_Dropdown from 'M_Dropdown'
import M_Tooltip from 'M_Tooltip'
import A_Link from 'A_Link'
import O_TextUsHere from 'O_TextUsHere'

class SE_Ambassadors  extends Component {

  state = {
    filter: 'All',
  }

  nodes = []

  componentDidMount() {
    document.addEventListener('resize', this.forceUpdate);
    this.forceUpdate()
  }

  componentWillUnmount() {
    document.removeEventListener('resize', this.forceUpdate);
  }

  getAmbassadors(entities, filter) {
    let filtered
    if (filter == 'All') {
      filtered = entities
    } else {
      filtered = entities.filter(entity => entity.country === filter)
    }

    let _renderedAmbassadors = filtered.map((partner, i) => {
      let tooltipPlace;
      if (
        this.nodes[0]
        && this.nodes[i + 1]
        && (this.nodes[0].offsetLeft + this.nodes[i + 1].offsetLeft > 200)
      ) {
        tooltipPlace = 'left'
      } else {
        tooltipPlace = 'right'
      }

      return (

 this.nodes[i + 1] = node}
        >

          <A_Image
            src={partner.logoLink2x}
            alt={partner.name}
          />

            <M_Tooltip type={tooltipPlace}>
              <A_H type='tooltip'>{partner.name}</A_H>
               this.setState({filter: partner.country})} style={{cursor: 'pointer'}}>
                <A_H type='tooltip-sub'>{partner.country}</A_H>

              {partner.bio}
            </M_Tooltip>

            <A_Link to={partner.link} external type="block" >{' '}</A_Link>

      )
    })

    for (let i = 0; i < 7; i++) {
      _renderedAmbassadors.push(

      )
    }
    return _renderedAmbassadors
  }

  render() {
    const {countries, entities} = this.props
    const options = ['All', ...countries]

    const {filter} = this.state
    return (

        <Meta />
        <A_Container type="equal">
          <O_Hero img={{src: "/img/illustrations/ambassadors.svg", alt: "ambassadors"}}>
            <A_H type="hero">Our Global Team</A_H>
            <A_P type="hero">At Humaniq, everything we do is motivated by our wish to provide the most widespread access to banking possible.</A_P>
          </O_Hero>
          <A_H type="section">Ever growing network</A_H>
          <A_P type="third">We want to communicate directly with the people we wish to serve: the unbanked. People without access to banking live in very rural areas. This is why we’ve started our Ambassador Program. Our ambassadors live in these developing countries and know the culture well. They are helping to promote cryptocurrencies in the Global South, as well as explaining the Humaniq project and app to the people in their countries.</A_P>

              <M_Dropdown
                selected={filter}
                options={options}
                onChange={filter => this.setState({filter})}
              />

            <A_Btn
              type="material-r-link"
              to='/form/ambassadors'
            >Join Ambassadors Program</A_Btn>

 this.nodes[0] = node}
            >
              {this.getAmbassadors(entities, filter)}

        </A_Container>
        {/*<A_Container type="equal">*/}

          {/*<O_TextUsHere*/}
            {/*{...{*/}
              {/*title: 'Join Ambassadors',*/}
              {/*text: 'If you believe you can help your community, join Humaniq global Ambassador\'s programme.',*/}
              {/*link: {*/}
                {/*linkText: 'Join Humaniq Network',*/}
                {/*url: 'mailto:info@humaniq.com'*/}
              {/*}*/}
            {/*}}*/}
          {/*/>*/}
        {/*</A_Container>*/}

    )
  }
}

SE_Ambassadors .propTypes = {
  entities: T.array.isRequired,
  countries: T.array.isRequired
};

export default SE_Ambassadors
<|endoftext|>


<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import theme from './theme.css';
import cx from 'classnames';
import { TransitionGroup, CSSTransition } from 'react-transition-group';

class ToastContainer extends PureComponent {
  render() {
    const { children, className } = this.props;
    const classNames = cx(theme['container'], className);

    return (

        <TransitionGroup component="li">
          {React.Children.map(children, (child) => {
            return (
              <CSSTransition
                timeout={1000}
                key={child.key}
                classNames={{
                  appear: cx(theme['appear']),
                  appearActive: cx(theme['appear-active']),
                  enter: cx(theme['enter']),
                  enterActive: cx(theme['enter-active']),
                  enterDone: cx(theme['enter-done']),
                  exit: cx(theme['exit']),
                  exitActive: cx(theme['exit-active']),
                  exitDone: cx(theme['exit-done']),
                }}
              >
                {child}
              </CSSTransition>
            );
          })}
        </TransitionGroup>

    );
  }
}

ToastContainer.propTypes = {
  /** The content to display inside the ToastContainer */
  children: PropTypes.any,
  /** A custom class name for custom styling */
  className: PropTypes.string,
};

export default ToastContainer;
<commit_msg>:sparkles: pass on the style prop to the container<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import theme from './theme.css';
import cx from 'classnames';
import { TransitionGroup, CSSTransition } from 'react-transition-group';

class ToastContainer extends PureComponent {
  render() {
    const { children, className, style } = this.props;
    const classNames = cx(theme['container'], className);

    return (

        <TransitionGroup component="li">
          {React.Children.map(children, (child) => {
            return (
              <CSSTransition
                timeout={1000}
                key={child.key}
                classNames={{
                  appear: cx(theme['appear']),
                  appearActive: cx(theme['appear-active']),
                  enter: cx(theme['enter']),
                  enterActive: cx(theme['enter-active']),
                  enterDone: cx(theme['enter-done']),
                  exit: cx(theme['exit']),
                  exitActive: cx(theme['exit-active']),
                  exitDone: cx(theme['exit-done']),
                }}
              >
                {child}
              </CSSTransition>
            );
          })}
        </TransitionGroup>

    );
  }
}

ToastContainer.propTypes = {
  /** The content to display inside the ToastContainer */
  children: PropTypes.any,
  /** A custom class name for custom styling */
  className: PropTypes.string,
  /** Custom style properties for the container */
  style: PropTypes.object,
};

export default ToastContainer;
<|endoftext|>


<commit_before>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var React = require('react');
var MatrixClientPeg = require("../../../MatrixClientPeg");
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var ObjectUtils = require('../../../ObjectUtils');

module.exports = React.createClass({
    displayName: 'AuxPanel',

    propTypes: {
        // js-sdk room object
        room: React.PropTypes.object.isRequired,

        // Conference Handler implementation
        conferenceHandler: React.PropTypes.object,

        // set to true to show the file drop target
        draggingFile: React.PropTypes.bool,

        // set to true to show the 'active conf call' banner
        displayConfCallNotification: React.PropTypes.bool,

        // maxHeight attribute for the aux panel and the video
        // therein
        maxHeight: React.PropTypes.number,

        // a callback which is called when the content of the aux panel changes
        // content in a way that is likely to make it change size.
        onResize: React.PropTypes.func,
    },

    shouldComponentUpdate: function(nextProps, nextState) {
        return (!ObjectUtils.shallowEqual(this.props, nextProps) ||
                !ObjectUtils.shallowEqual(this.state, nextState));
    },

    componentDidUpdate: function(prevProps, prevState) {
        // most changes are likely to cause a resize
        if (this.props.onResize) {
            this.props.onResize();
        }
    },

    onConferenceNotificationClick: function(type) {
        dis.dispatch({
            action: 'place_call',
            type: type,
            room_id: this.props.room.roomId,
        });
    },

    render: function() {
        var CallView = sdk.getComponent("voip.CallView");
        var TintableSvg = sdk.getComponent("elements.TintableSvg");

        var fileDropTarget = null;
        if (this.props.draggingFile) {
            fileDropTarget = (

                        <TintableSvg src="img/upload-big.svg" width="45" height="59"/>

                        Drop file here to upload

            );
        }

        var conferenceCallNotification = null;
        if (this.props.displayConfCallNotification) {
            var supportedText, joinText;
            if (!MatrixClientPeg.get().supportsVoip()) {
                supportedText = " (unsupported)";
            }
            else {
                joinText = (
                    Join as voice or video.
                );

            }
            conferenceCallNotification = (

                    Ongoing conference call{ supportedText }. { joinText }

            );
        }

        var callView = (
            <CallView ref="callView" room={this.props.room}
                ConferenceHandler={this.props.conferenceHandler}
                onResize={this.props.onResize}
                maxVideoHeight={this.props.maxHeight}
            />
        );

        return (

                { fileDropTarget }
                { callView }
                { conferenceCallNotification }
                { this.props.children }

        );
    },
});
<commit_msg>let users join confs as voice or video<commit_after>/*
Copyright 2015, 2016 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var React = require('react');
var MatrixClientPeg = require("../../../MatrixClientPeg");
var sdk = require('../../../index');
var dis = require("../../../dispatcher");
var ObjectUtils = require('../../../ObjectUtils');

module.exports = React.createClass({
    displayName: 'AuxPanel',

    propTypes: {
        // js-sdk room object
        room: React.PropTypes.object.isRequired,

        // Conference Handler implementation
        conferenceHandler: React.PropTypes.object,

        // set to true to show the file drop target
        draggingFile: React.PropTypes.bool,

        // set to true to show the 'active conf call' banner
        displayConfCallNotification: React.PropTypes.bool,

        // maxHeight attribute for the aux panel and the video
        // therein
        maxHeight: React.PropTypes.number,

        // a callback which is called when the content of the aux panel changes
        // content in a way that is likely to make it change size.
        onResize: React.PropTypes.func,
    },

    shouldComponentUpdate: function(nextProps, nextState) {
        return (!ObjectUtils.shallowEqual(this.props, nextProps) ||
                !ObjectUtils.shallowEqual(this.state, nextState));
    },

    componentDidUpdate: function(prevProps, prevState) {
        // most changes are likely to cause a resize
        if (this.props.onResize) {
            this.props.onResize();
        }
    },

    onConferenceNotificationClick: function(ev, type) {
        dis.dispatch({
            action: 'place_call',
            type: type,
            room_id: this.props.room.roomId,
        });
        ev.stopPropagation();
        ev.preventDefault();
    },

    render: function() {
        var CallView = sdk.getComponent("voip.CallView");
        var TintableSvg = sdk.getComponent("elements.TintableSvg");

        var fileDropTarget = null;
        if (this.props.draggingFile) {
            fileDropTarget = (

                        <TintableSvg src="img/upload-big.svg" width="45" height="59"/>

                        Drop file here to upload

            );
        }

        var conferenceCallNotification = null;
        if (this.props.displayConfCallNotification) {
            var supportedText, joinText;
            if (!MatrixClientPeg.get().supportsVoip()) {
                supportedText = " (unsupported)";
            }
            else {
                joinText = (
                    Join as { this.onConferenceNotificationClick(event, 'voice')}} href="#">voice
                    or { this.onConferenceNotificationClick(event, 'video') }} href="#">video.
                );

            }
            conferenceCallNotification = (

                    Ongoing conference call{ supportedText }. { joinText }

            );
        }

        var callView = (
            <CallView ref="callView" room={this.props.room}
                ConferenceHandler={this.props.conferenceHandler}
                onResize={this.props.onResize}
                maxVideoHeight={this.props.maxHeight}
            />
        );

        return (

                { fileDropTarget }
                { callView }
                { conferenceCallNotification }
                { this.props.children }

        );
    },
});
<|endoftext|>


<commit_before>/*! resol-vbus | Copyright (c) 2013-2018, Daniel Wippermann | MIT license */
'use strict';

const _ = require('./lodash');

const optimizerClasses = [

    // ======================================================================
    // RESOL
    // ======================================================================

    // DeltaSol BS4 v2
    require('./configuration-optimizers/resol-deltasol-bs4v2-103-configuration-optimizer'),

    // DeltaSol BX Plus
    require('./configuration-optimizers/resol-deltasol-bx-plus-xxx-configuration-optimizer'),

    // DeltaSol C
    require('./configuration-optimizers/resol-deltasol-c-104-configuration-optimizer'),

    // DeltaSol CS Plus
    require('./configuration-optimizers/resol-deltasol-cs-plus-xxx-configuration-optimizer'),

    // DeltaSol E V2
    require('./configuration-optimizers/resol-deltasol-e-v2-100-configuration-optimizer'),

    // DeltaSol MX
    require('./configuration-optimizers/resol-deltasol-mx-112-configuration-optimizer'),

    // DeltaSol SLT
    require('./configuration-optimizers/resol-deltasol-slt-102-configuration-optimizer'),

    // DeltaTherm HC
    require('./configuration-optimizers/resol-deltatherm-hc-xxx-configuration-optimizer'),

];

const ConfigurationOptimizerFactory = {

    /**
     * Find a `ConfigurationOptimizer` sub-class that matches the given options best.
     *
     * @param  {object} options Options to look for while searching a matching configuration optimizer.
     * @param  {number} options.deviceAddress The VBus address of the controller.
     * @param  {string} options.version The version of the controller.
     * @param  {Customizer} options.customizer A `Customizer` instance to query additional information with.
     * @return {Promise} A Promise that resolves to the best matching optimizer result or `null` if no match was found.
     */
    async matchOptimizer(options) {
        options = _.defaults({}, options);

        let result = {
            match: 0,
            Optimizer: null,
            options: null,
        };

        const cache = {
            masterAddress: null,
            masterConfiguration: [],
        };

        for (const Optimizer of optimizerClasses) {
            const refResult = await Optimizer.matchOptimizer(options, cache);

            if ((refResult.match > 0) && (refResult.match > result.match)) {
                result = refResult;
            }
        }

        if (result.match > 0) {
            return result;
        } else {
            return null;
        }
    },

    /**
     * Find and create an instance of a `ConfigurationOptimizer` sub-class that matches the given options best.
     *
     * @param  {object} options See {@link ConfigurationOptimizerFactory.matchOptimizer} for details.
     * @return {Promise} A promise that resolves to the `ConfigurationOptimizer` instance or `null` if no matching optimizer was found.
     */
    async createOptimizer(options) {
        const result = await ConfigurationOptimizerFactory.matchOptimizer(options);

        let optimizer;
        if (result) {
            optimizer = new result.Optimizer(result.options);
        } else {
            optimizer = null;
        }
        return optimizer;
    },

    /**
     * Get the configuration optimizer for the given device (identified by its address).
     *
     * @param {number} deviceAddress VBus address of the device
     * @returns {Promise} A Promise that resolvs to the optimizer for the given device or `null` if no optimizer was found.
     */
    createOptimizerByDeviceAddress(deviceAddress) {
        return ConfigurationOptimizerFactory.createOptimizer({
            deviceAddress,
        });
    },

    _optimizerClasses: optimizerClasses,

};

module.exports = ConfigurationOptimizerFactory;
<commit_msg>resol cs2 and cs4 added<commit_after>/*! resol-vbus | Copyright (c) 2013-2018, Daniel Wippermann | MIT license */
'use strict';

const _ = require('./lodash');

const optimizerClasses = [

    // ======================================================================
    // RESOL
    // ======================================================================

    // DeltaSol BS4 v2
    require('./configuration-optimizers/resol-deltasol-bs4v2-103-configuration-optimizer'),

    // DeltaSol BX Plus
    require('./configuration-optimizers/resol-deltasol-bx-plus-xxx-configuration-optimizer'),

    // DeltaSol C
    require('./configuration-optimizers/resol-deltasol-c-104-configuration-optimizer'),

    // DeltaSol CS Plus
    require('./configuration-optimizers/resol-deltasol-cs-plus-xxx-configuration-optimizer'),

	// DeltaSol CS2
    require('./configuration-optimizers/resol-deltasol-cs2-200-configuration-optimizer'),

	// DeltaSol CS2
    require('./configuration-optimizers/resol-deltasol-cs4-200-configuration-optimizer'),

    // DeltaSol E V2
    require('./configuration-optimizers/resol-deltasol-e-v2-100-configuration-optimizer'),

    // DeltaSol MX
    require('./configuration-optimizers/resol-deltasol-mx-112-configuration-optimizer'),

    // DeltaSol SLT
    require('./configuration-optimizers/resol-deltasol-slt-102-configuration-optimizer'),

    // DeltaTherm HC
    require('./configuration-optimizers/resol-deltatherm-hc-xxx-configuration-optimizer'),

];

const ConfigurationOptimizerFactory = {

    /**
     * Find a `ConfigurationOptimizer` sub-class that matches the given options best.
     *
     * @param  {object} options Options to look for while searching a matching configuration optimizer.
     * @param  {number} options.deviceAddress The VBus address of the controller.
     * @param  {string} options.version The version of the controller.
     * @param  {Customizer} options.customizer A `Customizer` instance to query additional information with.
     * @return {Promise} A Promise that resolves to the best matching optimizer result or `null` if no match was found.
     */
    async matchOptimizer(options) {
        options = _.defaults({}, options);

        let result = {
            match: 0,
            Optimizer: null,
            options: null,
        };

        const cache = {
            masterAddress: null,
            masterConfiguration: [],
        };

        for (const Optimizer of optimizerClasses) {
            const refResult = await Optimizer.matchOptimizer(options, cache);

            if ((refResult.match > 0) && (refResult.match > result.match)) {
                result = refResult;
            }
        }

        if (result.match > 0) {
            return result;
        } else {
            return null;
        }
    },

    /**
     * Find and create an instance of a `ConfigurationOptimizer` sub-class that matches the given options best.
     *
     * @param  {object} options See {@link ConfigurationOptimizerFactory.matchOptimizer} for details.
     * @return {Promise} A promise that resolves to the `ConfigurationOptimizer` instance or `null` if no matching optimizer was found.
     */
    async createOptimizer(options) {
        const result = await ConfigurationOptimizerFactory.matchOptimizer(options);

        let optimizer;
        if (result) {
            optimizer = new result.Optimizer(result.options);
        } else {
            optimizer = null;
        }
        return optimizer;
    },

    /**
     * Get the configuration optimizer for the given device (identified by its address).
     *
     * @param {number} deviceAddress VBus address of the device
     * @returns {Promise} A Promise that resolvs to the optimizer for the given device or `null` if no optimizer was found.
     */
    createOptimizerByDeviceAddress(deviceAddress) {
        return ConfigurationOptimizerFactory.createOptimizer({
            deviceAddress,
        });
    },

    _optimizerClasses: optimizerClasses,

};

module.exports = ConfigurationOptimizerFactory;
<|endoftext|>


<commit_before>import styled from 'styled-components'

import { theme, cs } from '@/utils'

// 纯css，div隐藏滚动条，保留鼠标滚动效果。
// http://blog.csdn.net/liusaint1992/article/details/51277751
export const Wrapper = styled.aside.attrs((props) => ({
  'data-testid': props.testid,
}))`
  ${cs.flexColumn()};
  border-right: 1px solid;
  position: fixed;
  height: 100vh;
  top: 0;
  left: 0;
  width: ${({ pin }) => (pin ? '260px' : '56px')};
  box-shadow: ${({ pin }) => (pin ? '3px 0 20px rgba(0, 0, 0, 0.2); ' : '')};
  background: ${theme('sidebar.bg')};
  border-color: ${theme('sidebar.borderColor')};
  z-index: ${cs.zIndex.sidebar};
  // overflow: hidden;

  transition: width 0.2s, opacity 0.8s, box-shadow 0.1s linear 0.1s,
    background-color 0.3s;

  &:hover {
    width: 260px;
    box-shadow: 3px 0 20px rgba(0, 0, 0, 0.2);
  }
  ${cs.media.tablet`display: none`};
`
export const holder = 1
<commit_msg>fix(sidebar): wrong position fixed when wide screen (#765)<commit_after>import styled from 'styled-components'

import { theme, cs } from '@/utils'

// 纯css，div隐藏滚动条，保留鼠标滚动效果。
// http://blog.csdn.net/liusaint1992/article/details/51277751
export const Wrapper = styled.aside.attrs((props) => ({
  'data-testid': props.testid,
}))`
  ${cs.flexColumn()};
  border-right: 1px solid;
  position: fixed;
  height: 100vh;
  top: 0;
  /* left: 0; */
  width: ${({ pin }) => (pin ? '260px' : '56px')};
  box-shadow: ${({ pin }) => (pin ? '3px 0 20px rgba(0, 0, 0, 0.2); ' : '')};
  background: ${theme('sidebar.bg')};
  border-color: ${theme('sidebar.borderColor')};
  z-index: ${cs.zIndex.sidebar};

  transition: width 0.2s, opacity 0.8s, box-shadow 0.1s linear 0.1s,
    background-color 0.3s;

  &:hover {
    width: 260px;
    box-shadow: 3px 0 20px rgba(0, 0, 0, 0.2);
  }
  ${cs.media.tablet`display: none`};
`
export const holder = 1
<|endoftext|>


<commit_before>/* eslint-disable no-underscore-dangle */
import { extend } from '../../shared/utils';

function createStore(storeParams = {}) {
  const store = {
    __store: true,
  };
  const originalState = { ...(storeParams.state || {}) };
  const actions = { ...(storeParams.actions || {}) };
  const getters = { ...(storeParams.getters || {}) };
  const state = extend({}, originalState);

  let propsQueue = [];
  const gettersDependencies = {};
  const gettersCallbacks = {};

  Object.keys(getters).forEach((key) => {
    gettersDependencies[key] = [];
    gettersCallbacks[key] = [];
  });
  const addGetterDependencies = (key, deps) => {
    if (!gettersDependencies[key]) gettersDependencies[key] = [];
    deps.forEach((dep) => {
      if (gettersDependencies[key].indexOf(dep) < 0) {
        gettersDependencies[key].push(dep);
      }
    });
  };

  const addGetterCallback = (key, callback) => {
    if (!gettersCallbacks[key]) gettersCallbacks[key] = [];
    gettersCallbacks[key].push(callback);
  };

  const runGetterCallbacks = (stateKey, value) => {
    const keys = Object.keys(gettersDependencies).filter((getterKey) => {
      return gettersDependencies[getterKey].indexOf(stateKey) >= 0;
    });
    keys.forEach((getterKey) => {
      if (!gettersCallbacks[getterKey] || !gettersCallbacks[getterKey].length) return;
      gettersCallbacks[getterKey].forEach((callback) => {
        callback(value);
      });
    });
  };

  const removeGetterCallback = (callback) => {
    Object.keys(gettersCallbacks).forEach((key) => {
      const callbacks = gettersCallbacks[key];

      if (callbacks.indexOf(callback) >= 0) {
        callbacks.splice(callbacks.indexOf(callback), 1);
      }
    });
  };

  // eslint-disable-next-line
  store.__removeCallback = (callback) => {
    removeGetterCallback(callback);
  };

  const getterValue = (key) => {
    if (key === 'constructor') return;
    propsQueue = [];
    const value = getters[key]({ state: store.state });
    addGetterDependencies(key, propsQueue);
    const onUpdated = (callback) => {
      addGetterCallback(key, callback);
    };

    const obj = {
      value,
      onUpdated,
    };
    const callback = (v) => {
      obj.value = v;
    };

    obj.__callback = callback;
    addGetterCallback(key, callback);
    // eslint-disable-next-line
    return obj;
  };

  store.state = new Proxy(state, {
    set: (target, prop, value) => {
      target[prop] = value;
      runGetterCallbacks(prop, value);
      return true;
    },
    get: (target, prop) => {
      propsQueue.push(prop);
      return target[prop];
    },
  });

  store.getters = new Proxy(getters, {
    set: () => false,
    get: (target, prop) => {
      if (!target[prop]) {
        return undefined;
      }
      return getterValue(prop);
    },
  });

  store.dispatch = (actionName, data) => {
    return new Promise((resolve, reject) => {
      if (!actions[actionName]) {
        reject();
        throw new Error(`Framework7: Store action "${actionName}" is not found`);
      }
      const result = actions[actionName](
        { state: store.state, action: store.action, get: store.get },
        data,
      );
      resolve(result);
    });
  };

  return store;
}

export default createStore;
<commit_msg>Core: Store - "dispatch" in action context<commit_after>/* eslint-disable no-underscore-dangle */
import { extend } from '../../shared/utils';

function createStore(storeParams = {}) {
  const store = {
    __store: true,
  };
  const originalState = { ...(storeParams.state || {}) };
  const actions = { ...(storeParams.actions || {}) };
  const getters = { ...(storeParams.getters || {}) };
  const state = extend({}, originalState);

  let propsQueue = [];
  const gettersDependencies = {};
  const gettersCallbacks = {};

  Object.keys(getters).forEach((key) => {
    gettersDependencies[key] = [];
    gettersCallbacks[key] = [];
  });
  const addGetterDependencies = (key, deps) => {
    if (!gettersDependencies[key]) gettersDependencies[key] = [];
    deps.forEach((dep) => {
      if (gettersDependencies[key].indexOf(dep) < 0) {
        gettersDependencies[key].push(dep);
      }
    });
  };

  const addGetterCallback = (key, callback) => {
    if (!gettersCallbacks[key]) gettersCallbacks[key] = [];
    gettersCallbacks[key].push(callback);
  };

  const runGetterCallbacks = (stateKey, value) => {
    const keys = Object.keys(gettersDependencies).filter((getterKey) => {
      return gettersDependencies[getterKey].indexOf(stateKey) >= 0;
    });
    keys.forEach((getterKey) => {
      if (!gettersCallbacks[getterKey] || !gettersCallbacks[getterKey].length) return;
      gettersCallbacks[getterKey].forEach((callback) => {
        callback(value);
      });
    });
  };

  const removeGetterCallback = (callback) => {
    Object.keys(gettersCallbacks).forEach((key) => {
      const callbacks = gettersCallbacks[key];

      if (callbacks.indexOf(callback) >= 0) {
        callbacks.splice(callbacks.indexOf(callback), 1);
      }
    });
  };

  // eslint-disable-next-line
  store.__removeCallback = (callback) => {
    removeGetterCallback(callback);
  };

  const getterValue = (key) => {
    if (key === 'constructor') return;
    propsQueue = [];
    const value = getters[key]({ state: store.state });
    addGetterDependencies(key, propsQueue);
    const onUpdated = (callback) => {
      addGetterCallback(key, callback);
    };

    const obj = {
      value,
      onUpdated,
    };
    const callback = (v) => {
      obj.value = v;
    };

    obj.__callback = callback;
    addGetterCallback(key, callback);
    // eslint-disable-next-line
    return obj;
  };

  store.state = new Proxy(state, {
    set: (target, prop, value) => {
      target[prop] = value;
      runGetterCallbacks(prop, value);
      return true;
    },
    get: (target, prop) => {
      propsQueue.push(prop);
      return target[prop];
    },
  });

  store.getters = new Proxy(getters, {
    set: () => false,
    get: (target, prop) => {
      if (!target[prop]) {
        return undefined;
      }
      return getterValue(prop);
    },
  });

  store.dispatch = (actionName, data) => {
    return new Promise((resolve, reject) => {
      if (!actions[actionName]) {
        reject();
        throw new Error(`Framework7: Store action "${actionName}" is not found`);
      }
      const result = actions[actionName]({ state: store.state, dispatch: store.dispatch }, data);
      resolve(result);
    });
  };

  return store;
}

export default createStore;
<|endoftext|>


<commit_before>/*
    ------------------
    Initialize Variables
    ------------------
*/

//Constants
const VERSION = 1.1;
const BOOT_TIME = new Date();
const WH_TIME = 0;
const ADMINS = ["Dino", "α|CraftSpider|Ω", "HiddenStorys"];

//Command variables
var NumWWs = 0;
var MaxWWs = 10;
var IsSleeping = 0;

//Writing Hour variables
var WHActive = false;
var WHDisactive = false;
var WHAlertOne = false;
var WHAlertTwo = false;

/*
    User Commands dictionaries
*/
var Commands = {
	"information": function() {
		postMessage("Hello! I'm Talos, official PtP mod-bot.\nMy Developers are CraftSpider, Dino, and HiddenStorys.\nAny suggestions or bugs can be sent to my email, talos.ptp@gmail.com.");
	},
	"seen": function(user) {
		//postMessage("Sorry, this command doesn't work yet.");
		if(user[0]) {
			var time;
			searchMessages("{V:" + user.join(" ") + "}");
			setTimeout(function() {
				var recentMessage = elementByID("X138").childNodes[2];
				if(recentMessage.childNodes[5]) {
					time = recentMessage.childNodes[5].innerText;
				} else {
					time = recentMessage.childNodes[4].innerText;
				}
			}, 500);
			setTimeout(function() {
				if(time) {
                    postMessage("User " + user.join(" ") + " was last seen " + time);
				} else {
					postMessage("I couldn't find that user. Sorry.");
					X47();
				}
			}, 700);
			setTimeout(function() {
				X47();
			}, 900);
		} else {
			postMessage("Sorry, I need a user to look for.");
			X47();
		}
	},
	"uptime": function() {
		postMessage("I've been online since " + BOOT_TIME.toUTCString() + ".")
	},
	"version": function() {
		postMessage("I'm currently on version " + VERSION);
	},
	"wordWar": function(length) {
		if (length[0] > 60 || length[0] <= 0) {
			postMessage("Choose a number between 1 and 60.");
		} else if (NumWWs >= MaxWWs) {
		    postMessage("Too many word wars, I can't keep up! Wait for one to finish first.");
		} else {
		    NumWWs++;
			postMessage("I'm starting a " + length[0] + " minute word war." + (length[1]? " Keyword: " + length[1]  + "." : "") + " Go!");
			setTimeout(function() {
				NumWWs--;
				if (!IsSleeping) {
					postMessage("Word War " + (length[1]? "'" + length[1] + "' " : "") + "ends. How did you do?");
				}
			}, length[0] * 60000);
		}
	},
	"help": function (args) {
	    if (!args[0]) {
		    var helpList = "Greetings. I'm Talos, chat helper. My commands are:\n";
		    for (var C in Commands) {
		    	helpList += "^" + C + "\n";
		    }
		    helpList += "\nMy Admin Commands are:\n";
		    for (var C in ADMIN_COMMANDS) {
		    	helpList += "^" + C + "\n";
		    }
		    postMessage(helpList);
	    } else {
	        switch (args[0]) {
	            case "help":
	                postMessage("Use: ^help [Command Name]\nDescription: Help command, by default gives general information about Talos and a list of available commands. Adding the name of another command as an argument will give a more detailed description of that command. Though you probably figured that out, you're here after all :P");
	                break;
	            case "information":
	            	postMessage("Use: ^information\nDescription: Gives a short blurb about Talos.");
	            	break;
	            case "kill":
	                postMessage("Use: ^kill\nDescription: Causes Talos to immediately leave the chat, and cease running. Admin only.");
	                break;
	            case "seen":
	                postMessage("Use: ^seen <Username>\nDescription: Find how long ago this user last posted a message. Returns a time or date in EST.");
	                break;
	            case "toggleSleep":
	                postMessage("Use: ^toggleSleep [time]\nDescription: Turns user commands and related features off or on. An admin only command, to prevent abuse. Also doesn't declare the finish to any active WWs that finish while I'm asleep.");
	                break;
	            case "uptime":
	            	postMessage("Use: ^uptime\nDescription: Gives the time and date, down to the second, that Talos began running.");
	            	break;
	            case "version":
	            	postMessage("Use: ^version\nDescription: The version that Talos is currently running. I always know exactly where I am.");
	            	break;
	            case "wordWar":
	                postMessage("Use: ^wordWar <time> [keyword]\nDescription: Starts a Word War, with given keyword if provided. The time is in minutes, and Talos will say when that many minutes have elapsed.");
	                break;
	            default:
	                postMessage("Sorry, no available help page for that.");
	        }
	    }
	}
};

var ADMIN_COMMANDS = {
    "toggleSleep": function() {
    	if (IsSleeping == 0) {
    		IsSleeping = 1;
    		postMessage("Good night! Going to sleep now. To wake me, type [b]^toggleSleep[/b] again.");
    	} else {
    		IsSleeping = 0;
    		postMessage("I'm awake again, and available for user commands. To have me sleep again, type [b]^toggleSleep[/b].");
    	}
	},
	"kill": function() {
		postMessage("Et Tu, Brute?");
		setTimeout(function() {leaveChat();}, 200);
		throw new Error("Talos Killed by Admin");
	},
};

/*
    -----------------
    Wrapper Functions
    -----------------
*/
function elementByID(elementID) {
    return document.getElementById(elementID);
}

function leaveChat() {
    elementByID("X802").onclick();
}

function postMessage(message) {
    var HTMLTags = ["", "", "", "", "<s>", "</s>", "", ""];
    var ChatzyTags = ["[b]", "[/b]", "[i]", "[/i]", "[s]", "[/s]", "[u]", "[/u]"];
    for (var tag in HTMLTags) {
        message = message.replace(HTMLTags[tag],ChatzyTags[tag]);
    }
    X279(message);
}

function closeChat() {
	postMessage("/close");
}

function openChat() {
	postMessage("/open");
}

function toggleChatLock() {
	if(X105.X398) { //Variable for whether the chat is locked, of course
		postMessage("/open");
	} else {
		postMessage("/close");
	}
}

function searchMessages(term) {
	postMessage("/find " + term);
}

function privateMessage(name, message) {
	postMessage("/pm \"" + name + "\" " + message);
}

function globalMessage(message) { //Note, only sends the message to online users.
	var users = X330.split("\n");
	for (var i = 1; i <= users[0]; i++) {
		user = users[i].split("	");
		privateMessage(user[0], message);	//Replace the 0 with other numbers to grab different values. 2 is last leave/exit, 4 is status, 5 is location.
	}
}

function editRoomBoard(message, method, key) {  //Method is the style of editing to use. Options are: 0/default, overwrite. 1, append. 2, prepend. 3, replace.
    postMessage("/rb");
    setTimeout(function() {
        var BoardMessage = X17("X856");
        switch (method) {
            case 1:
                BoardMessage.value = BoardMessage.value + "\n" + message;
                break;
            case 2:
                BoardMessage.value = message + "\n" + BoardMessage.value;
                break;
            case 3:
                if (BoardMessage.value.match(new RegExp(key, "g")).length > 1) {
                    BoardMessage.value = BoardMessage.value.replace(new RegExp(key + ".+?" + key, "g"), key + message + key);
                }
                break;
            default:
                BoardMessage.value = message;
        }
        X565.onclick();
    }, 150);
}

//requires re-init of JSBot. Automate that?
function changeName(name) {
	X292('X387');

	setTimeout(function() {
		X481.value = name;
		X544.onsubmit();
	}, 1000);
}

/*
    -------------------
    Main loop functions
    -------------------
*/
function writingHour() {
    d = new Date();

    if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1)  && d.getUTCMinutes() == 50 && !WHAlertOne) {
        postMessage("[b][Alert][/b] Writing Hour starts in 10 minutes!");
        WHAlertOne = true;
    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1) && d.getUTCMinutes() == 55 && !WHAlertTwo) {
        postMessage("[b][Alert][/b] Writing Hour starts in 5 minutes!");
        WHAlertTwo = true;
    } else if (d.getUTCHours() == WH_TIME && d.getUTCMinutes() == 0 && !WHActive) {
        postMessage("[b]Writing Hour has started.[/b] Have fun, and use it productively!");
        WHActive = true;
        WHDisactive = false;
        setTimeout(function() {closeChat();}, 500);
    } else if (d.getUTCHours() == (WH_TIME == 23 ? 0 : WH_TIME + 1) && d.getUTCMinutes() == 0 && !WHDisactive) {
        openChat();
        setTimeout(function() {postMessage("[b]Writing Hour is over.[/b] How did you do?");}, 500);
        WHDisactive = true;
        WHActive = false;
        WHAlertTwo = false;
        WHAlertOne = false;
    }
}

function readChat() {
    if (!elementByID("X971") && elementByID("X138").firstChild.innerHTML != "Previous messages parsed (press ESC to re-parse page)") {
        return;
    }
	var Messages = elementByID("X138").innerHTML.split("\n");
	for (var i = 1; i < Messages.length; i++) {
		var Message = Messages[i];
		if (Message.match(/(.*)<\/b>: \^(\w+)(?:\s(.+))?(?: )/)) { //Instead of matching a set list of commands, match the word then check it against a dict?
		    var User = RegExp.$1;
			var Command = RegExp.$2;
			var Args = RegExp.$3.split(/\s/);
		    var isAdmin = false;
			for (var U in ADMINS) {
			    if (User == ADMINS[U]) {
			        isAdmin = true;
			        break;
			    }
			}
			if (window["ADMIN_COMMANDS"][Command] && isAdmin) {
			    window["ADMIN_COMMANDS"][Command](Args);
			} else if (IsSleeping == 1) {
				break;
			} else if (window["ADMIN_COMMANDS"][Command] && !isAdmin) {
			    postMessage("Sorry, that command is Admin only, and I don't recognize you!");
			} else if (window["Commands"][Command]) {
				window["Commands"][Command](Args);
			} else {
			    postMessage("Sorry, I don't understand that. May I suggest ^help?");
			}
		}
	}

	elementByID("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
	X783 = false;
}

function readPMs() {
    var ReceivedPM = elementByID("X94").innerHTML;
    if (ReceivedPM.match(/.+>(.+)<\/em>.+X296">\^(\w+)[\W]?(?:\s(.+))?(?:<\/div><p)/)) {
        var User = RegExp.$1;
        var Command = RegExp.$2;
		var Args = RegExp.$3.split(/\s/);
		var isAdmin = false;
		for (var U in ADMINS) {
		    if (User == ADMINS[U]) {
		        isAdmin = true;
		        break;
		    }
		}
		if (window["ADMIN_COMMANDS"][Command] && isAdmin) {
		    window["ADMIN_COMMANDS"][Command](Args);
		} else if (IsSleeping == 1) {
			X47();
			return;
		} else if (window["ADMIN_COMMANDS"][Command] && !isAdmin) {
		    privateMessage("Sorry, that command is Admin only, and I don't recognize you!");
		} else if (window["Commands"][Command]) {
			window["Commands"][Command](Args);
		} else {
		    privateMessage("Sorry, I don't understand that. May I suggest ^help?");
		}
    }
    //setTimeout(function(){ X47(); }, 100);
}

function mainLoop() {
    readChat();
    writingHour();
    readPMs();

}

/*
    -------------------
    Initialization Code
    -------------------
*/
setInterval(function() {mainLoop();}, 1000);
setInterval(function() {postMessage("");}, 60000*10)
elementByID("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
X783 = false;
<commit_msg>Formatting stuff.<commit_after>/*
    ------------------
    Initialize Variables
    ------------------
*/

//Constants
const VERSION = 1.1;
const BOOT_TIME = new Date();
const WH_TIME = 0;
const ADMINS = ["Dino", "α|CraftSpider|Ω", "HiddenStorys"];

//Command variables
var NumWWs = 0;
var MaxWWs = 10;
var IsSleeping = 0;

//Writing Hour variables
var WHActive = false;
var WHDisactive = false;
var WHAlertOne = false;
var WHAlertTwo = false;

/*
	--------------------------
    User Commands dictionaries
    --------------------------
*/
var Commands = {
	"information": function() {
		postMessage("Hello! I'm Talos, official PtP mod-bot.\nMy Developers are CraftSpider, Dino, and HiddenStorys.\nAny suggestions or bugs can be sent to my email, talos.ptp@gmail.com.");
	},
	"seen": function(user) {
		//postMessage("Sorry, this command doesn't work yet.");
		if(user[0]) {
			var time;
			searchMessages("{V:" + user.join(" ") + "}");
			setTimeout(function() {
				var recentMessage = elementByID("X138").childNodes[2];
				if(recentMessage.childNodes[5]) {
					time = recentMessage.childNodes[5].innerText;
				} else {
					time = recentMessage.childNodes[4].innerText;
				}
			}, 500);
			setTimeout(function() {
				if(time) {
                    postMessage("User " + user.join(" ") + " was last seen " + time);
				} else {
					postMessage("I couldn't find that user. Sorry.");
					X47();
				}
			}, 700);
			setTimeout(function() {
				X47();
			}, 900);
		} else {
			postMessage("Sorry, I need a user to look for.");
			X47();
		}
	},
	"uptime": function() {
		postMessage("I've been online since " + BOOT_TIME.toUTCString() + ".")
	},
	"version": function() {
		postMessage("I'm currently on version " + VERSION);
	},
	"wordWar": function(length) {
		if (length[0] > 60 || length[0] <= 0) {
			postMessage("Choose a number between 1 and 60.");
		} else if (NumWWs >= MaxWWs) {
		    postMessage("Too many word wars, I can't keep up! Wait for one to finish first.");
		} else {
		    NumWWs++;
			postMessage("I'm starting a " + length[0] + " minute word war." + (length[1]? " Keyword: " + length[1]  + "." : "") + " Go!");
			setTimeout(function() {
				NumWWs--;
				if (!IsSleeping) {
					postMessage("Word War " + (length[1]? "'" + length[1] + "' " : "") + "ends. How did you do?");
				}
			}, length[0] * 60000);
		}
	},
	"help": function (args) {
	    if (!args[0]) {
		    var helpList = "Greetings. I'm Talos, chat helper. My commands are:\n";
		    for (var C in Commands) {
		    	helpList += "^" + C + "\n";
		    }
		    helpList += "\nMy Admin Commands are:\n";
		    for (var C in ADMIN_COMMANDS) {
		    	helpList += "^" + C + "\n";
		    }
		    postMessage(helpList);
	    } else {
	        switch (args[0]) {
	            case "help":
	                postMessage("Use: ^help [Command Name]\nDescription: Help command, by default gives general information about Talos and a list of available commands. Adding the name of another command as an argument will give a more detailed description of that command. Though you probably figured that out, you're here after all :P");
	                break;
	            case "information":
	            	postMessage("Use: ^information\nDescription: Gives a short blurb about Talos.");
	            	break;
	            case "kill":
	                postMessage("Use: ^kill\nDescription: Causes Talos to immediately leave the chat, and cease running. Admin only.");
	                break;
	            case "seen":
	                postMessage("Use: ^seen <Username>\nDescription: Find how long ago this user last posted a message. Returns a time or date in EST.");
	                break;
	            case "toggleSleep":
	                postMessage("Use: ^toggleSleep [time]\nDescription: Turns user commands and related features off or on. An admin only command, to prevent abuse. Also doesn't declare the finish to any active WWs that finish while I'm asleep.");
	                break;
	            case "uptime":
	            	postMessage("Use: ^uptime\nDescription: Gives the time and date, down to the second, that Talos began running.");
	            	break;
	            case "version":
	            	postMessage("Use: ^version\nDescription: The version that Talos is currently running. I always know exactly where I am.");
	            	break;
	            case "wordWar":
	                postMessage("Use: ^wordWar <time> [keyword]\nDescription: Starts a Word War, with given keyword if provided. The time is in minutes, and Talos will say when that many minutes have elapsed.");
	                break;
	            default:
	                postMessage("Sorry, no available help page for that.");
	        }
	    }
	}
};

var ADMIN_COMMANDS = {
    "toggleSleep": function() {
    	if (IsSleeping == 0) {
    		IsSleeping = 1;
    		postMessage("Good night! Going to sleep now. To wake me, type [b]^toggleSleep[/b] again.");
    	} else {
    		IsSleeping = 0;
    		postMessage("I'm awake again, and available for user commands. To have me sleep again, type [b]^toggleSleep[/b].");
    	}
	},
	"kill": function() {
		postMessage("Et Tu, Brute?");
		setTimeout(function() {leaveChat();}, 200);
		throw new Error("Talos Killed by Admin");
	},
};

/*
    -----------------
    Wrapper Functions
    -----------------
*/
function elementByID(elementID) {
    return document.getElementById(elementID);
}

function leaveChat() {
    elementByID("X802").onclick();
}

function postMessage(message) {
    var HTMLTags = ["", "", "", "", "<s>", "</s>", "", ""];
    var ChatzyTags = ["[b]", "[/b]", "[i]", "[/i]", "[s]", "[/s]", "[u]", "[/u]"];
    for (var tag in HTMLTags) {
        message = message.replace(HTMLTags[tag],ChatzyTags[tag]);
    }
    X279(message);
}

function closeChat() {
	postMessage("/close");
}

function openChat() {
	postMessage("/open");
}

function toggleChatLock() {
	if(X105.X398) { //Variable for whether the chat is locked, of course
		postMessage("/open");
	} else {
		postMessage("/close");
	}
}

function searchMessages(term) {
	postMessage("/find " + term);
}

function privateMessage(name, message) {
	postMessage("/pm \"" + name + "\" " + message);
}

function globalMessage(message) { //Note, only sends the message to online users.
	var users = X330.split("\n");
	for (var i = 1; i <= users[0]; i++) {
		user = users[i].split("	");
		privateMessage(user[0], message);	//Replace the 0 with other numbers to grab different values. 2 is last leave/exit, 4 is status, 5 is location.
	}
}

function editRoomBoard(message, method, key) {  //Method is the style of editing to use. Options are: 0/default, overwrite. 1, append. 2, prepend. 3, replace.
    postMessage("/rb");
    setTimeout(function() {
        var BoardMessage = X17("X856");
        switch (method) {
            case 1:
                BoardMessage.value = BoardMessage.value + "\n" + message;
                break;
            case 2:
                BoardMessage.value = message + "\n" + BoardMessage.value;
                break;
            case 3:
                if (BoardMessage.value.match(new RegExp(key, "g")).length > 1) {
                    BoardMessage.value = BoardMessage.value.replace(new RegExp(key + ".+?" + key, "g"), key + message + key);
                }
                break;
            default:
                BoardMessage.value = message;
        }
        X565.onclick();
    }, 150);
}

//requires re-init of JSBot. Automate that?
function changeName(name) {
	X292('X387');

	setTimeout(function() {
		X481.value = name;
		X544.onsubmit();
	}, 1000);
}

/*
    -------------------
    Main loop functions
    -------------------
*/
function writingHour() {
    d = new Date();

    if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1)  && d.getUTCMinutes() == 50 && !WHAlertOne) {
        postMessage("[b][Alert][/b] Writing Hour starts in 10 minutes!");
        WHAlertOne = true;
    } else if (d.getUTCHours() == (WH_TIME == 0 ? 23 : WH_TIME - 1) && d.getUTCMinutes() == 55 && !WHAlertTwo) {
        postMessage("[b][Alert][/b] Writing Hour starts in 5 minutes!");
        WHAlertTwo = true;
    } else if (d.getUTCHours() == WH_TIME && d.getUTCMinutes() == 0 && !WHActive) {
        postMessage("[b]Writing Hour has started.[/b] Have fun, and use it productively!");
        WHActive = true;
        WHDisactive = false;
        setTimeout(function() {closeChat();}, 500);
    } else if (d.getUTCHours() == (WH_TIME == 23 ? 0 : WH_TIME + 1) && d.getUTCMinutes() == 0 && !WHDisactive) {
        openChat();
        setTimeout(function() {postMessage("[b]Writing Hour is over.[/b] How did you do?");}, 500);
        WHDisactive = true;
        WHActive = false;
        WHAlertTwo = false;
        WHAlertOne = false;
    }
}

function readChat() {
    if (!elementByID("X971") && elementByID("X138").firstChild.innerHTML != "Previous messages parsed (press ESC to re-parse page)") {
        return;
    }
	var Messages = elementByID("X138").innerHTML.split("\n");
	for (var i = 1; i < Messages.length; i++) {
		var Message = Messages[i];
		if (Message.match(/(.*)<\/b>: \^(\w+)(?:\s(.+))?(?: )/)) { //Instead of matching a set list of commands, match the word then check it against a dict?
		    var User = RegExp.$1;
			var Command = RegExp.$2;
			var Args = RegExp.$3.split(/\s/);
		    var isAdmin = false;
			for (var U in ADMINS) {
			    if (User == ADMINS[U]) {
			        isAdmin = true;
			        break;
			    }
			}
			if (window["ADMIN_COMMANDS"][Command] && isAdmin) {
			    window["ADMIN_COMMANDS"][Command](Args);
			} else if (IsSleeping == 1) {
				break;
			} else if (window["ADMIN_COMMANDS"][Command] && !isAdmin) {
			    postMessage("Sorry, that command is Admin only, and I don't recognize you!");
			} else if (window["Commands"][Command]) {
				window["Commands"][Command](Args);
			} else {
			    postMessage("Sorry, I don't understand that. May I suggest ^help?");
			}
		}
	}

	elementByID("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
	X783 = false;
}

function readPMs() {
    var ReceivedPM = elementByID("X94").innerHTML;
    if (ReceivedPM.match(/.+>(.+)<\/em>.+X296">\^(\w+)[\W]?(?:\s(.+))?(?:<\/div><p)/)) {
        var User = RegExp.$1;
        var Command = RegExp.$2;
		var Args = RegExp.$3.split(/\s/);
		var isAdmin = false;
		for (var U in ADMINS) {
		    if (User == ADMINS[U]) {
		        isAdmin = true;
		        break;
		    }
		}
		if (window["ADMIN_COMMANDS"][Command] && isAdmin) {
		    window["ADMIN_COMMANDS"][Command](Args);
		} else if (IsSleeping == 1) {
			X47();
			return;
		} else if (window["ADMIN_COMMANDS"][Command] && !isAdmin) {
		    privateMessage("Sorry, that command is Admin only, and I don't recognize you!");
		} else if (window["Commands"][Command]) {
			window["Commands"][Command](Args);
		} else {
		    privateMessage("Sorry, I don't understand that. May I suggest ^help?");
		}
    }
    //setTimeout(function(){ X47(); }, 100);
}

function mainLoop() {
    readChat();
    writingHour();
    readPMs();

}

/*
    -------------------
    Initialization Code
    -------------------
*/
setInterval(function() {mainLoop();}, 1000);
setInterval(function() {postMessage("");}, 60000*10)
elementByID("X138").innerHTML = '
Previous messages parsed (press ESC to re-parse page)
\n';
X783 = false;
<|endoftext|>