<commit_before>var _ = require('lodash');

export const defaultConfig = {
    maxAge: 24,
    maxAuthors: 20,
    maxComplexity: 14,
    redish: d3.rgb("#E60D0D"),
    blueish: d3.rgb("#0E34E0"),
    neutralColor: d3.rgb("green"),
    parentStrokeColor: d3.rgb("#4E4545"),
    parentFillColor: d3.rgb("#7D7E8C")
};

function buildCodeMaatDataFn(maxAge) {
    return (d) => {
        const age = _.get(d,["data","code-maat","ageMonths"]);

        if (age) {
            return maxAge - age;
        } else {
            return null;
        }
    }
}

function buildAuthorsDataFn() {
    return (d) => {
        return _.get(d, ["data","code-maat","nAuthors"]);
    }
}

function buildLanguageDataFn() {
    return (d) => {
        return _.get(d, ["data","cloc","language"]);
    }
}

function buildJsComplexityDataFn(maxComplexity) {
    return (d) => {
        const complexity = _.get(d, ["data","jscomplexity","cyclomatic"]);
        if (complexity) {
            return maxComplexity - complexity
        } else {
            return null;
        }
    }
}

function buildScaledNodeColourFn(dataFn, parentColour, defaultColour, colourScale) {
    return (d) => {
        if (d.children) {
            return parentColour;
        }
        const value = dataFn(d);
        if (value) {
            return colourScale(value);
        }

        return defaultColour;
    }
}

export function strategies(config) {
    const redBlueScale = d3.scale.linear().range([config.redish, config.blueish]);
    const darkerRedBlueScale = d3.scale.linear().range([config.redish.darker(), config.blueish.darker()]);
    const codeMaatDataFn = buildCodeMaatDataFn(config.maxAge);
    const authorsDataFn = buildAuthorsDataFn();
    const languageDataFn = buildLanguageDataFn();
    const languageScale = d3.scale.category20();
    const languageStrokeColor = d3.rgb("black");
    const jsComplexityDataFn = buildJsComplexityDataFn(config.maxComplexity);
    return {
        age: {
            nodeDataFn: codeMaatDataFn,
            fillFn: buildScaledNodeColourFn(codeMaatDataFn,
                config.parentFillColor,
                config.redish, // default assumed to be max age
                redBlueScale.copy().domain([0,config.maxAge])),
            strokeFn: buildScaledNodeColourFn(codeMaatDataFn,
                config.parentStrokeColor,
                config.redish,
                darkerRedBlueScale.copy().domain([0,config.maxAge]))
        },
        authors: {
            nodeDataFn: authorsDataFn,
            fillFn: buildScaledNodeColourFn(authorsDataFn,
                config.parentFillColor,
                config.redish,
                redBlueScale.copy().domain([0,config.maxAuthors])),
            strokeFn: buildScaledNodeColourFn(authorsDataFn,
                config.parentStrokeColor,
                config.redish,
                darkerRedBlueScale.copy().domain([0,config.maxAuthors]))
        },
        language: {
            nodeDataFn: languageDataFn,
            fillFn: buildScaledNodeColourFn(languageDataFn,
                config.parentFillColor,
                config.neutralColor,
                languageScale),
            strokeFn: (d) => { return languageStrokeColor; }
        },
        jscomplexity: {
            nodeDataFn: jsComplexityDataFn,
            fillFn: buildScaledNodeColourFn(jsComplexityDataFn,
                config.parentFillColor,
                config.neutralColor,
                redBlueScale.copy().domain([0,config.maxComplexity])),
            strokeFn: buildScaledNodeColourFn(jsComplexityDataFn,
                config.parentStrokeColor,
                config.neutralColor.darker(),
                darkerRedBlueScale.copy().domain([0,config.maxComplexity]))
        }
    }
}

export default class TreeMap {
    constructor(config, maxTitleDepth = 4, minValueForTitle = 500) {
        this.config = config;
        this.strategies = strategies(this.config);
        this.w = 960;
        this.h = 700;
        this.paddingAllowance = 2;
        this.maxTitleDepth = maxTitleDepth;
        this.minValueForTitle = minValueForTitle;

        this.treemap = d3.layout.treemap()
            .size([this.w, this.h])
            .padding(d => this.padding(d))
            .value(d => d.data.cloc ? d.data.cloc.code : null);

    }

    padding(d) {
        return this.showTitle(d) ? [16, 1, 1, 1] : 1
    }

    showTitle(d) {
        if (d.value < this.minValueForTitle) return 0;
        return d.children && d.depth <= this.maxTitleDepth;
    }

    mouseOver(d) {
        this.tooltip.transition()
            .duration(200);
        this.tooltip
            .style("opacity", 0.9);
        this.tooltip.html(this.formatTooltip(d))
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY) + "px");
    }

    mouseOut(d) {
        this.tooltip.transition()
            .duration(500)
            .style("opacity", 0);
    }

    formatTooltip(d) {
        if (d.data) {
            return `${d.name}<pre>${JSON.stringify(d.data, null, 2)}</pre>`
        } else {
            //console.log(d);
            const {area, depth, value} = d;
            const data = {area, depth, value};
            return `${d.name}<pre>${JSON.stringify(data, null, 2)}</pre>`
        }
    }

    //outputType can be any valid strategy
    render(outputType) {
        // TODO: render has all sorts of side effects - and there's no clean-up
        // needs thought on modularity, and the meaning of calling render multiple times.
        // the real goal would be to be able to render once, then use d3 magic to re-render
        //  with a different strategy, different root note, all the rest.

        var strategy = this.strategies[outputType];

        this.tooltip = d3
            .select("body")
            .append("div")
            .attr("class", "tooltip");

        this.svg = d3.select("body").append("svg")
            .style("position", "relative")
            .style("width", `${this.w}px`)
            .style("height", `${this.h}px`)
            .append("g")
            .attr("transform", "translate(-.5,-.5)");

        d3.json("/data/metrics.json", (json) => {
            var cell = this.svg.data([json]).selectAll("g")
                .data(this.treemap)
                .enter().append("g")
                .attr("class", "cell")
                .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

            cell.on("mouseover", d => this.mouseOver(d))
                .on("mouseout", d => this.mouseOut(d));

            cell.append("rect")
                .attr("width", d => d.dx)
                .attr("height", d => d.dy)
                .style("fill", strategy.fillFn)
                .style("stroke", strategy.strokeFn)
                .style("z-index", d => -d.depth);

            cell.append("foreignObject")
                .attr("class", "foreignObject")
                .attr("width", d => Math.max(d.dx - this.paddingAllowance, 2))
                .attr("height", d => Math.max(d.dy - this.paddingAllowance, 2))
                .append("xhtml:body")
                .attr("class", "labelbody")
                .append("div")
                .attr("class", "label")
                .text(d => this.showTitle(d) ? d.name : null)
                .attr("text-anchor", "middle");

        });
    }
}

<commit_msg>refactor to use ternary ops, simpler es6 fns<commit_after>var _ = require('lodash');

export const defaultConfig = {
    maxAge: 24,
    maxAuthors: 20,
    maxComplexity: 14,
    redish: d3.rgb("#E60D0D"),
    blueish: d3.rgb("#0E34E0"),
    neutralColor: d3.rgb("green"),
    parentStrokeColor: d3.rgb("#4E4545"),
    parentFillColor: d3.rgb("#7D7E8C")
};

function buildCodeMaatDataFn(maxAge) {
    return d => {
        const age = _.get(d,["data","code-maat","ageMonths"]);

        return age ? maxAge - age : null;
    }
}

function buildAuthorsDataFn() {
    return d => _.get(d, ["data","code-maat","nAuthors"]);
}

function buildLanguageDataFn() {
    return d => _.get(d, ["data","cloc","language"]);
}

function buildJsComplexityDataFn(maxComplexity) {
    return d => {
        const complexity = _.get(d, ["data","jscomplexity","cyclomatic"]);

        return complexity ?  maxComplexity - complexity : null;
    }
}

function buildScaledNodeColourFn(dataFn, parentColour, defaultColour, colourScale) {
    return d => {
        if (d.children) {
            return parentColour;
        }
        const value = dataFn(d);

        return value ? colourScale(value) : defaultColour;
    }
}

export function strategies(config) {
    const redBlueScale = d3.scale.linear().range([config.redish, config.blueish]);
    const darkerRedBlueScale = d3.scale.linear().range([config.redish.darker(), config.blueish.darker()]);
    const codeMaatDataFn = buildCodeMaatDataFn(config.maxAge);
    const authorsDataFn = buildAuthorsDataFn();
    const languageDataFn = buildLanguageDataFn();
    const languageScale = d3.scale.category20();
    const languageStrokeColor = d3.rgb("black");
    const jsComplexityDataFn = buildJsComplexityDataFn(config.maxComplexity);
    return {
        age: {
            nodeDataFn: codeMaatDataFn,
            fillFn: buildScaledNodeColourFn(codeMaatDataFn,
                config.parentFillColor,
                config.redish, // default assumed to be max age
                redBlueScale.copy().domain([0,config.maxAge])),
            strokeFn: buildScaledNodeColourFn(codeMaatDataFn,
                config.parentStrokeColor,
                config.redish,
                darkerRedBlueScale.copy().domain([0,config.maxAge]))
        },
        authors: {
            nodeDataFn: authorsDataFn,
            fillFn: buildScaledNodeColourFn(authorsDataFn,
                config.parentFillColor,
                config.redish,
                redBlueScale.copy().domain([0,config.maxAuthors])),
            strokeFn: buildScaledNodeColourFn(authorsDataFn,
                config.parentStrokeColor,
                config.redish,
                darkerRedBlueScale.copy().domain([0,config.maxAuthors]))
        },
        language: {
            nodeDataFn: languageDataFn,
            fillFn: buildScaledNodeColourFn(languageDataFn,
                config.parentFillColor,
                config.neutralColor,
                languageScale),
            strokeFn: d => languageStrokeColor
        },
        jscomplexity: {
            nodeDataFn: jsComplexityDataFn,
            fillFn: buildScaledNodeColourFn(jsComplexityDataFn,
                config.parentFillColor,
                config.neutralColor,
                redBlueScale.copy().domain([0,config.maxComplexity])),
            strokeFn: buildScaledNodeColourFn(jsComplexityDataFn,
                config.parentStrokeColor,
                config.neutralColor.darker(),
                darkerRedBlueScale.copy().domain([0,config.maxComplexity]))
        }
    }
}

export default class TreeMap {
    constructor(config, maxTitleDepth = 4, minValueForTitle = 500) {
        this.config = config;
        this.strategies = strategies(this.config);
        this.w = 960;
        this.h = 700;
        this.paddingAllowance = 2;
        this.maxTitleDepth = maxTitleDepth;
        this.minValueForTitle = minValueForTitle;

        this.treemap = d3.layout.treemap()
            .size([this.w, this.h])
            .padding(d => this.padding(d))
            .value(d => d.data.cloc ? d.data.cloc.code : null);

    }

    padding(d) {
        return this.showTitle(d) ? [16, 1, 1, 1] : 1
    }

    showTitle(d) {
        if (d.value < this.minValueForTitle) return 0;
        return d.children && d.depth <= this.maxTitleDepth;
    }

    mouseOver(d) {
        this.tooltip.transition()
            .duration(200);
        this.tooltip
            .style("opacity", 0.9);
        this.tooltip.html(this.formatTooltip(d))
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY) + "px");
    }

    mouseOut(d) {
        this.tooltip.transition()
            .duration(500)
            .style("opacity", 0);
    }

    formatTooltip(d) {
        if (d.data) {
            return `${d.name}<pre>${JSON.stringify(d.data, null, 2)}</pre>`
        } else {
            // TODO: can we use lodash for this:
            const {area, depth, value} = d;
            const data = {area, depth, value};
            return `${d.name}<pre>${JSON.stringify(data, null, 2)}</pre>`
        }
    }

    //outputType can be any valid strategy
    render(outputType) {
        // TODO: render has all sorts of side effects - and there's no clean-up
        // needs thought on modularity, and the meaning of calling render multiple times.
        // the real goal would be to be able to render once, then use d3 magic to re-render
        //  with a different strategy, different root note, all the rest.

        var strategy = this.strategies[outputType];

        this.tooltip = d3
            .select("body")
            .append("div")
            .attr("class", "tooltip");

        this.svg = d3.select("body").append("svg")
            .style("position", "relative")
            .style("width", `${this.w}px`)
            .style("height", `${this.h}px`)
            .append("g")
            .attr("transform", "translate(-.5,-.5)");

        d3.json("/data/metrics.json", (json) => {
            var cell = this.svg.data([json]).selectAll("g")
                .data(this.treemap)
                .enter().append("g")
                .attr("class", "cell")
                .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

            cell.on("mouseover", d => this.mouseOver(d))
                .on("mouseout", d => this.mouseOut(d));

            cell.append("rect")
                .attr("width", d => d.dx)
                .attr("height", d => d.dy)
                .style("fill", strategy.fillFn)
                .style("stroke", strategy.strokeFn)
                .style("z-index", d => -d.depth);

            cell.append("foreignObject")
                .attr("class", "foreignObject")
                .attr("width", d => Math.max(d.dx - this.paddingAllowance, 2))
                .attr("height", d => Math.max(d.dy - this.paddingAllowance, 2))
                .append("xhtml:body")
                .attr("class", "labelbody")
                .append("div")
                .attr("class", "label")
                .text(d => this.showTitle(d) ? d.name : null)
                .attr("text-anchor", "middle");

        });
    }
}

<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var agent = require('superagent');
var defaults = require('superagent-defaults');
var uuid = require('uuid');
var Houkou = require('houkou');
var DecodeJWT = require('jwt-decode');

var log = require('bows')('Actions');

var constants = require('./action-constants');

var makeFetchMultiple = function(ctx, pendingEvent, completeEvent, key, urlTemplate) {
  log('Generating fetchMultiple function', pendingEvent, completeEvent);

  return function() {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
    });

    var self = this;
    ctx.agent.get(urlTemplate.build({})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        models: res.body[key],
      });
    });
  };
};

var makeFetchOne = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating fetchOneOf function', pendingEvent, completeEvent);

  return function(id) {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
    });

    var self = this;
    ctx.agent.get(urlTemplate.build({id: id})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeCreate = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating create function', pendingEvent, completeEvent);

  return function(parameters, attributes) {
    var operationId = uuid.v1();

    attributes = _.extend({}, attributes);
    parameters = _.extend({}, parameters);

    this.dispatch(pendingEvent, {
      operationId: operationId,
      attributes: attributes,
    });

    var self = this;
    ctx.agent.post(urlTemplate.build(parameters)).send(attributes).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeUpdate = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating update function', pendingEvent, completeEvent);

  return function(attributes) {
    var operationId = uuid.v1();
    var id = attributes.id;

    attributes = _.extend({}, attributes);

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
      attributes: attributes,
    });

    var self = this;
    ctx.agent.put(urlTemplate.build({id: id})).send(attributes).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeDelete = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating delete function', pendingEvent, completeEvent);

  return function(id) {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
    });

    var self = this;
    ctx.agent.del(urlTemplate.build({id: id})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
      });
    });
  };
};

module.exports = function createActions(baseUrl, pubnubKey) {
  var ctx = {
    agent: agent,
    jwt: null,
    pubnub: null,

    setJwt(jwt) {
      if (!this.jwt) {
        this.jwt = jwt;
        this.agent = defaults().set('authorization', 'Bearer ' + jwt);
      }
    },

    connectPubnub(channel, actions) {
      if (!this.pubnub) {
        this.pubnub = PUBNUB.init({
          subscribe_key: pubnubKey,
          ssl: true,
        });

        var self = this;

        this.pubnub.subscribe({
          channel: channel,
          message(incoming, env, channel) {
            if (incoming.type === "message") {
              actions.dispatch(constants.MESSAGE_CREATE_REMOTE, {
                model: {
                  id: incoming.id,
                  created_at: incoming.created_at,
                  from: incoming.from,
                  text: incoming.text,
                },
              });
            }

            if (incoming.type === "match") {
              self.agent.get(baseUrl + '/v1/matches/' + incoming.other_user_id + '.json').end(function(res) {
                if (!res.ok || !res.body || !res.body.person) {
                  return;
                }

                return actions.dispatch(constants.MATCH_CREATE_REMOTE, {
                  model: res.body.person,
                });
              });
            }
          },
        });
      }
    },
  };

  return {
    peopleFetch: makeFetchMultiple(ctx, constants.PERSON_LOAD_PENDING, constants.PERSON_LOAD_COMPLETE, 'people', new Houkou(baseUrl + '/v1/people.json')),
    personFetch: makeFetchOne(ctx, constants.PERSON_GET_PENDING, constants.PERSON_GET_COMPLETE, new Houkou(baseUrl + '/v1/people/:id.json')),
    matchesFetch: makeFetchMultiple(ctx, constants.MATCH_LOAD_PENDING, constants.MATCH_LOAD_COMPLETE, 'matches', new Houkou(baseUrl + '/v1/matches.json')),
    matchFetch: makeFetchOne(ctx, constants.MATCH_GET_PENDING, constants.MATCH_GET_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id.json')),
    matchCreate: makeCreate(ctx, constants.MATCH_CREATE_PENDING, constants.MATCH_CREATE_COMPLETE, new Houkou(baseUrl + '/v1/matches.json')),
    matchDelete: makeDelete(ctx, constants.MATCH_DELETE_PENDING, constants.MATCH_DELETE_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id.json')),
    messageCreate: makeCreate(ctx, constants.MESSAGE_CREATE_PENDING, constants.MESSAGE_CREATE_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id/messages.json')),

    init() {
      try {
        var jwt = window.localStorage.getItem("jwt");
        var profile = JSON.parse(window.localStorage.getItem("profile"));

        var decoded = DecodeJWT(jwt);
      } catch (e) { return; }

      if (decoded.exp*1000 <= Date.now()) {
        return;
      }

      ctx.setJwt(jwt);
      ctx.connectPubnub(profile.channel, this);

      this.dispatch(constants.LOGIN_COMPLETE, {
        jwt: jwt,
        profile: profile,
      });
    },

    login() {
      var operationId = uuid.v1();

      this.dispatch(constants.LOGIN_PENDING, {
        operationId: operationId,
      });

      var self = this;

      var onMessage = function onMessage(ev) {
        if (ev.origin !== window.location.origin) {
          return;
        }

        if (typeof ev.data !== "object" || ev.data === null || typeof ev.data.token !== "string") {
          return;
        }

        window.removeEventListener('message', onMessage);

        var token = ev.data.token;

        ctx.setJwt(token);

        ctx.agent.get(baseUrl + '/v1/profile.json').end(function(res) {
          if (!res.ok) {
            return self.dispatch(constants.LOGIN_COMPLETE, {
              operationId: operationId,
              error: res.text,
            });
          }

          var profile = res.body.person;

          ctx.connectPubnub(profile.channel, self);

          return self.dispatch(constants.LOGIN_COMPLETE, {
            operationId: operationId,
            jwt: token,
            profile: profile,
          });
        });
      };
      window.addEventListener('message', onMessage);

      window.open(baseUrl + '/auth?redirect_uri=' + escape(window.location.origin + '/login-callback.html'));
    },
  };
};
<commit_msg>fix live message updates<commit_after>'use strict';

var _ = require('lodash');
var agent = require('superagent');
var defaults = require('superagent-defaults');
var uuid = require('uuid');
var Houkou = require('houkou');
var DecodeJWT = require('jwt-decode');

var log = require('bows')('Actions');

var constants = require('./action-constants');

var makeFetchMultiple = function(ctx, pendingEvent, completeEvent, key, urlTemplate) {
  log('Generating fetchMultiple function', pendingEvent, completeEvent);

  return function() {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
    });

    var self = this;
    ctx.agent.get(urlTemplate.build({})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        models: res.body[key],
      });
    });
  };
};

var makeFetchOne = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating fetchOneOf function', pendingEvent, completeEvent);

  return function(id) {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
    });

    var self = this;
    ctx.agent.get(urlTemplate.build({id: id})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeCreate = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating create function', pendingEvent, completeEvent);

  return function(parameters, attributes) {
    var operationId = uuid.v1();

    attributes = _.extend({}, attributes);
    parameters = _.extend({}, parameters);

    this.dispatch(pendingEvent, {
      operationId: operationId,
      attributes: attributes,
    });

    var self = this;
    ctx.agent.post(urlTemplate.build(parameters)).send(attributes).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeUpdate = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating update function', pendingEvent, completeEvent);

  return function(attributes) {
    var operationId = uuid.v1();
    var id = attributes.id;

    attributes = _.extend({}, attributes);

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
      attributes: attributes,
    });

    var self = this;
    ctx.agent.put(urlTemplate.build({id: id})).send(attributes).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
        model: res.body,
      });
    });
  };
};

var makeDelete = function(ctx, pendingEvent, completeEvent, urlTemplate) {
  log('Generating delete function', pendingEvent, completeEvent);

  return function(id) {
    var operationId = uuid.v1();

    this.dispatch(pendingEvent, {
      operationId: operationId,
      id: id,
    });

    var self = this;
    ctx.agent.del(urlTemplate.build({id: id})).end(function(res) {
      if (!res.ok) {
        return self.dispatch(completeEvent, {
          operationId: operationId,
          error: res.text,
        });
      }

      return self.dispatch(completeEvent, {
        operationId: operationId,
      });
    });
  };
};

module.exports = function createActions(baseUrl, pubnubKey) {
  var ctx = {
    agent: agent,
    jwt: null,
    pubnub: null,

    setJwt(jwt) {
      if (!this.jwt) {
        this.jwt = jwt;
        this.agent = defaults().set('authorization', 'Bearer ' + jwt);
      }
    },

    connectPubnub(channel, actions) {
      if (!this.pubnub) {
        this.pubnub = PUBNUB.init({
          subscribe_key: pubnubKey,
          ssl: true,
        });

        var self = this;

        this.pubnub.subscribe({
          channel: channel,
          message(incoming, env, channel) {
            if (incoming.type === "message") {
              actions.dispatch(constants.MESSAGE_CREATE_REMOTE, {
                model: {
                  id: incoming.id,
                  created_at: incoming.created_at,
                  matchId: incoming.from,
                  from: incoming.from,
                  text: incoming.text,
                },
              });
            }

            if (incoming.type === "match") {
              self.agent.get(baseUrl + '/v1/matches/' + incoming.other_user_id + '.json').end(function(res) {
                if (!res.ok || !res.body || !res.body.person) {
                  return;
                }

                return actions.dispatch(constants.MATCH_CREATE_REMOTE, {
                  model: res.body.person,
                });
              });
            }
          },
        });
      }
    },
  };

  return {
    peopleFetch: makeFetchMultiple(ctx, constants.PERSON_LOAD_PENDING, constants.PERSON_LOAD_COMPLETE, 'people', new Houkou(baseUrl + '/v1/people.json')),
    personFetch: makeFetchOne(ctx, constants.PERSON_GET_PENDING, constants.PERSON_GET_COMPLETE, new Houkou(baseUrl + '/v1/people/:id.json')),
    matchesFetch: makeFetchMultiple(ctx, constants.MATCH_LOAD_PENDING, constants.MATCH_LOAD_COMPLETE, 'matches', new Houkou(baseUrl + '/v1/matches.json')),
    matchFetch: makeFetchOne(ctx, constants.MATCH_GET_PENDING, constants.MATCH_GET_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id.json')),
    matchCreate: makeCreate(ctx, constants.MATCH_CREATE_PENDING, constants.MATCH_CREATE_COMPLETE, new Houkou(baseUrl + '/v1/matches.json')),
    matchDelete: makeDelete(ctx, constants.MATCH_DELETE_PENDING, constants.MATCH_DELETE_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id.json')),
    messageCreate: makeCreate(ctx, constants.MESSAGE_CREATE_PENDING, constants.MESSAGE_CREATE_COMPLETE, new Houkou(baseUrl + '/v1/matches/:id/messages.json')),

    init() {
      try {
        var jwt = window.localStorage.getItem("jwt");
        var profile = JSON.parse(window.localStorage.getItem("profile"));

        var decoded = DecodeJWT(jwt);
      } catch (e) { return; }

      if (decoded.exp*1000 <= Date.now()) {
        return;
      }

      ctx.setJwt(jwt);
      ctx.connectPubnub(profile.channel, this);

      this.dispatch(constants.LOGIN_COMPLETE, {
        jwt: jwt,
        profile: profile,
      });
    },

    login() {
      var operationId = uuid.v1();

      this.dispatch(constants.LOGIN_PENDING, {
        operationId: operationId,
      });

      var self = this;

      var onMessage = function onMessage(ev) {
        if (ev.origin !== window.location.origin) {
          return;
        }

        if (typeof ev.data !== "object" || ev.data === null || typeof ev.data.token !== "string") {
          return;
        }

        window.removeEventListener('message', onMessage);

        var token = ev.data.token;

        ctx.setJwt(token);

        ctx.agent.get(baseUrl + '/v1/profile.json').end(function(res) {
          if (!res.ok) {
            return self.dispatch(constants.LOGIN_COMPLETE, {
              operationId: operationId,
              error: res.text,
            });
          }

          var profile = res.body.person;

          ctx.connectPubnub(profile.channel, self);

          return self.dispatch(constants.LOGIN_COMPLETE, {
            operationId: operationId,
            jwt: token,
            profile: profile,
          });
        });
      };
      window.addEventListener('message', onMessage);

      window.open(baseUrl + '/auth?redirect_uri=' + escape(window.location.origin + '/login-callback.html'));
    },
  };
};
<|endoftext|>


<commit_before>import {join} from 'aurelia-path';
import {HttpRequestMessage} from './http-request-message';
import {JSONPRequestMessage} from './jsonp-request-message';

/**
* A builder class allowing fluent composition of HTTP requests.
*
* @class RequestBuilder
* @constructor
*/
export class RequestBuilder {
	constructor (client) {
		this.client = client;
		this.transformers = client.requestTransformers.slice(0);
		this.useJsonp = false;
	}

	/**
	* Adds a user-defined request transformer to the RequestBuilder.
	*
	* @method addHelper
	* @param {String} name The name of the helper to add.
	* @param {Function} fn The helper function.
	* @chainable
	*/
	static addHelper(name, fn){
		RequestBuilder.prototype[name] = function(){
			this.transformers.push(fn.apply(this, arguments));
			return this;
		};
	}

	/**
	* Sends the request.
	*
	* @method send
	* @return {Promise} A cancellable promise object.
	*/
	send(){
		let message = this.useJsonp ? new JSONPRequestMessage() : new HttpRequestMessage();
		return this.client.send(message, this.transformers);
	}
}

RequestBuilder.addHelper('asDelete', function(){
	return function(client, processor, message){
		message.method = 'DELETE';
	};
});

RequestBuilder.addHelper('asGet', function(){
	return function(client, processor, message){
		message.method = 'GET';
	};
});

RequestBuilder.addHelper('asHead', function(){
	return function(client, processor, message){
		message.method = 'HEAD';
	};
});

RequestBuilder.addHelper('asOptions', function(){
	return function(client, processor, message){
		message.method = 'OPTIONS';
	};
});

RequestBuilder.addHelper('asPatch', function(){
	return function(client, processor, message){
		message.method = 'PATCH';
	};
});

RequestBuilder.addHelper('asPost', function(){
	return function(client, processor, message){
		message.method = 'POST';
	};
});

RequestBuilder.addHelper('asPut', function(){
	return function(client, processor, message){
		message.method = 'PUT';
	};
});

RequestBuilder.addHelper('asJsonp', function(jsonpParameterName){
	this.useJsonp = true;
	return function(client, processor, message){
		message.jsonpParameterName =  jsonpParameterName;
	};
});

RequestBuilder.addHelper('withUri', function(uri){
	return function(client, processor, message){
		message.uri = uri;
	};
});

RequestBuilder.addHelper('withContent', function(content){
	return function(client, processor, message){
		message.content = content;
	};
});

RequestBuilder.addHelper('withBaseUri', function(baseUri){
	return function(client, processor, message){
		message.baseUri = baseUri;
	}
});

RequestBuilder.addHelper('withParams', function(params){
	return function(client, processor, message){
		message.params = params;
	}
});

RequestBuilder.addHelper('withResponseType', function(responseType){
	return function(client, processor, message){
		message.responseType = responseType;
	}
});

RequestBuilder.addHelper('withTimeout', function(timeout){
	return function(client, processor, message){
		message.timeout = timeout;
	}
});

RequestBuilder.addHelper('withHeader', function(key, value){
	return function(client, processor, message){
		message.headers.add(key, value);
	}
});

RequestBuilder.addHelper('withCredentials', function(value){
	return function(client, processor, message){
		message.withCredentials = value;
	}
});

RequestBuilder.addHelper('withReviver', function(reviver){
	return function(client, processor, message){
		message.reviver = reviver;
	}
});

RequestBuilder.addHelper('withReplacer', function(replacer){
	return function(client, processor, message){
		message.replacer = replacer;
	}
});

RequestBuilder.addHelper('withProgressCallback', function(progressCallback){
	return function(client, processor, message){
		message.progressCallback = progressCallback;
	}
});

RequestBuilder.addHelper('withCallbackParameterName', function(callbackParameterName){
	return function(client, processor, message){
		message.callbackParameterName = callbackParameterName;
	}
});
<commit_msg>fix(request-builder): incorrect jsonp callback property name<commit_after>import {join} from 'aurelia-path';
import {HttpRequestMessage} from './http-request-message';
import {JSONPRequestMessage} from './jsonp-request-message';

/**
* A builder class allowing fluent composition of HTTP requests.
*
* @class RequestBuilder
* @constructor
*/
export class RequestBuilder {
	constructor (client) {
		this.client = client;
		this.transformers = client.requestTransformers.slice(0);
		this.useJsonp = false;
	}

	/**
	* Adds a user-defined request transformer to the RequestBuilder.
	*
	* @method addHelper
	* @param {String} name The name of the helper to add.
	* @param {Function} fn The helper function.
	* @chainable
	*/
	static addHelper(name, fn){
		RequestBuilder.prototype[name] = function(){
			this.transformers.push(fn.apply(this, arguments));
			return this;
		};
	}

	/**
	* Sends the request.
	*
	* @method send
	* @return {Promise} A cancellable promise object.
	*/
	send(){
		let message = this.useJsonp ? new JSONPRequestMessage() : new HttpRequestMessage();
		return this.client.send(message, this.transformers);
	}
}

RequestBuilder.addHelper('asDelete', function(){
	return function(client, processor, message){
		message.method = 'DELETE';
	};
});

RequestBuilder.addHelper('asGet', function(){
	return function(client, processor, message){
		message.method = 'GET';
	};
});

RequestBuilder.addHelper('asHead', function(){
	return function(client, processor, message){
		message.method = 'HEAD';
	};
});

RequestBuilder.addHelper('asOptions', function(){
	return function(client, processor, message){
		message.method = 'OPTIONS';
	};
});

RequestBuilder.addHelper('asPatch', function(){
	return function(client, processor, message){
		message.method = 'PATCH';
	};
});

RequestBuilder.addHelper('asPost', function(){
	return function(client, processor, message){
		message.method = 'POST';
	};
});

RequestBuilder.addHelper('asPut', function(){
	return function(client, processor, message){
		message.method = 'PUT';
	};
});

RequestBuilder.addHelper('asJsonp', function(callbackParameterName){
	this.useJsonp = true;
	return function(client, processor, message){
		message.callbackParameterName =  callbackParameterName;
	};
});

RequestBuilder.addHelper('withUri', function(uri){
	return function(client, processor, message){
		message.uri = uri;
	};
});

RequestBuilder.addHelper('withContent', function(content){
	return function(client, processor, message){
		message.content = content;
	};
});

RequestBuilder.addHelper('withBaseUri', function(baseUri){
	return function(client, processor, message){
		message.baseUri = baseUri;
	}
});

RequestBuilder.addHelper('withParams', function(params){
	return function(client, processor, message){
		message.params = params;
	}
});

RequestBuilder.addHelper('withResponseType', function(responseType){
	return function(client, processor, message){
		message.responseType = responseType;
	}
});

RequestBuilder.addHelper('withTimeout', function(timeout){
	return function(client, processor, message){
		message.timeout = timeout;
	}
});

RequestBuilder.addHelper('withHeader', function(key, value){
	return function(client, processor, message){
		message.headers.add(key, value);
	}
});

RequestBuilder.addHelper('withCredentials', function(value){
	return function(client, processor, message){
		message.withCredentials = value;
	}
});

RequestBuilder.addHelper('withReviver', function(reviver){
	return function(client, processor, message){
		message.reviver = reviver;
	}
});

RequestBuilder.addHelper('withReplacer', function(replacer){
	return function(client, processor, message){
		message.replacer = replacer;
	}
});

RequestBuilder.addHelper('withProgressCallback', function(progressCallback){
	return function(client, processor, message){
		message.progressCallback = progressCallback;
	}
});

RequestBuilder.addHelper('withCallbackParameterName', function(callbackParameterName){
	return function(client, processor, message){
		message.callbackParameterName = callbackParameterName;
	}
});
<|endoftext|>


<commit_before>'use strict';

angular.module('report-editor')
    .controller('APICtrl', function(_, $log, $scope, $state, $sce, $stateParams, swagger, API_URL, Session, API, PROFILE){

        var method = $stateParams.method;
        var path = '/' + $stateParams.path;
        var operation;
        swagger.apis.forEach(function(api){
            if(api.path === path) {
                api.operations.forEach(function(op){
                    if(op.method === method) {
                        operation = op;
                        return false;
                    }
                });
                return false;
            }
        });

        if(!operation) {
            $state.go('404');
            return;
        }

        operation.notes = $sce.trustAsHtml(operation.notes);
        operation.parameters =
            _.chain(operation.parameters)
            .filter(function(param){
                return !param.deprecated && param.name !== 'token' && param.name !== '_method' && (param.profile === undefined || param.profile.indexOf(PROFILE) !== -1);
            })
            .forEach(function(param){
                param.description = $sce.trustAsHtml(param.description);
                if(param.nameEditable){
                    param.placeholder = param.name;
                    param.name = undefined;
                }
            })
            .value();

        $scope.examples = _.chain(operation.examples).filter(function(example){
            return example.profile === undefined || example.profile.indexOf(PROFILE) !== -1;
        }).value();

        $scope.API_URL = API_URL;
        $scope.api = swagger;
        $scope.path = path;
        $scope.op = _.clone(operation);
        $scope.token = Session.getToken();
        $scope.params = {
            token: Session.getToken()
        };

        var camelCase = function(id) {
            var tokens = [];
            _.each(id.split('-'), function(token, index){
                if(index === 0) {
                    tokens.push(token[0].toLowerCase() + token.substring(1));
                } else {
                    tokens.push(token[0].toUpperCase() + token.substring(1));
                }
            });
            return tokens.join('');
        };

        var getParams = function(convertDashedParamsToCamelCase){
            var params = {
                token: $scope.token
            };
            var parameters = _.chain($scope.op.parameters)
                .filter(function(param){ return param.value !== undefined; })
                .value();
            _.each(parameters, function(param){
                var name = param.name;
                if(convertDashedParamsToCamelCase && name.indexOf('-') !== -1){
                    name = camelCase(name);
                }
                if(_.isString(name) && name !== '') {
                    params[name] = param.value;
                }
            });
            return params;
        };

        $scope.getUrl = function(inBrowser, inParam){
            var result = API_URL + '/_queries/public/api' + path;
            var params = getParams(false /* no camel case params */);
            if(Object.keys(params).length > 0) {
                result += '?';
                params = _.clone(params);
                if(inBrowser) {
                    params._method = 'POST';
                }
                result += _.chain(params).map(function(v, k){
                    if(_.isArray(v)) {
                        return _.chain(v).map(function(v){
                            return k + '=' + encodeURIComponent(v);
                        }).value().join('&');
                    } else {
                        return k + '=' + encodeURIComponent(v);
                    }
                }).join('&');
            }
            if(inParam) {
                result = encodeURIComponent(result);
            }
            return result;
        };

        $scope.curl = function(){
            return 'curl -X ' + $scope.op.method + ' "' + $scope.getUrl() + '"';
        };

        var getParamByPattern = function(name){
            var paramsWithPatterns = _.filter($scope.op.parameters, function(param){
                return _.isString(param.pattern);
            });
            var param = _.find(paramsWithPatterns, function(param){
                var pattern = new RegExp(param.pattern);
                return pattern.test( name );
            });
            if(_.isObject(param) && (_.isArray(param.value) || _.isString(param.value))){
                // value is already in use
                // need to add another parameter of the same kind
                var newParam = _.clone(param);
                newParam.name = name;
                $scope.op.parameters.push(newParam);
                return newParam;
            } else if (_.isObject(param)){
                param.name = name;
            }
            return param;
        };

        var getParam = function(name){
            var param = _.find($scope.op.parameters, function(param){
                return param.name === name;
            });
            if(_.isObject(param)){
                return param;
            }

            // no direct match let's look for a pattern match
            return getParamByPattern(name);
        };

        $scope.test = function(p) {
            if(p) {
                // reset
                $scope.op = angular.copy(operation);

                // make all values arrays
                p = _.mapValues(p, function(paramValue){
                    if(_.isArray(paramValue)){
                        return paramValue;
                    }
                    return [paramValue];
                });
                _.each(p, function(value, name){
                    var param = getParam(name);
                    if(_.isObject(param)){
                        param.value = value;
                    } else {
                        $log.error(name + ': Parameter does not exist for operation.');
                    }
                });
            }
            // $log.log(JSON.stringify($scope.op.parameters, null, '\t'));
            $scope.loading = true;
            $scope.error = undefined;
            $scope.body = undefined;
            var params = getParams(true /* use camel case params */);
            if(_.keys(params).length > 1) {
                API.Queries[operation.nickname](params)
                    .then(function (body) {
                        $scope.body = _.isString(body) ? body : JSON.stringify(body, null, 2);
                    })
                    .catch(function (error) {
                        $scope.body = _.isString(error.body) ? error.body : JSON.stringify(error.body, null, 2);
                        $scope.error = error;
                    })
                    .finally(function () {
                        $scope.loading = false;
                    });
            } else {
                $scope.error = 'Too few parameters.';
                $scope.body = 'Too few parameters.';
                $scope.loading = false;
            }
        };

        if($scope.examples.length > 0) {
            $scope.test($scope.examples[0].parameters);
        }
    });
<commit_msg>:bug: do not camel case pattern matched parameters.<commit_after>'use strict';

angular.module('report-editor')
    .controller('APICtrl', function(_, $log, $scope, $state, $sce, $stateParams, swagger, API_URL, Session, API, PROFILE){

        var method = $stateParams.method;
        var path = '/' + $stateParams.path;
        var operation;
        swagger.apis.forEach(function(api){
            if(api.path === path) {
                api.operations.forEach(function(op){
                    if(op.method === method) {
                        operation = op;
                        return false;
                    }
                });
                return false;
            }
        });

        if(!operation) {
            $state.go('404');
            return;
        }

        operation.notes = $sce.trustAsHtml(operation.notes);
        operation.parameters =
            _.chain(operation.parameters)
            .filter(function(param){
                return !param.deprecated && param.name !== 'token' && param.name !== '_method' && (param.profile === undefined || param.profile.indexOf(PROFILE) !== -1);
            })
            .forEach(function(param){
                param.description = $sce.trustAsHtml(param.description);
                if(param.nameEditable){
                    param.placeholder = param.name;
                    param.name = undefined;
                }
            })
            .value();

        $scope.examples = _.chain(operation.examples).filter(function(example){
            return example.profile === undefined || example.profile.indexOf(PROFILE) !== -1;
        }).value();

        $scope.API_URL = API_URL;
        $scope.api = swagger;
        $scope.path = path;
        $scope.op = _.clone(operation);
        $scope.token = Session.getToken();
        $scope.params = {
            token: Session.getToken()
        };

        var camelCase = function(id) {
            var tokens = [];
            _.each(id.split('-'), function(token, index){
                if(index === 0) {
                    tokens.push(token[0].toLowerCase() + token.substring(1));
                } else {
                    tokens.push(token[0].toUpperCase() + token.substring(1));
                }
            });
            return tokens.join('');
        };

        var getParams = function(convertDashedParamsToCamelCase){
            var params = {
                token: $scope.token
            };
            var parameters = _.chain($scope.op.parameters)
                .filter(function(param){ return param.value !== undefined; })
                .value();
            _.each(parameters, function(param){
                var name = param.name;
                if(convertDashedParamsToCamelCase && name.indexOf('-') !== -1 && !_.isString(param.pattern)){
                    name = camelCase(name);
                }
                if(_.isString(name) && name !== '') {
                    params[name] = param.value;
                }
            });
            return params;
        };

        $scope.getUrl = function(inBrowser, inParam){
            var result = API_URL + '/_queries/public/api' + path;
            var params = getParams(false /* no camel case params */);
            if(Object.keys(params).length > 0) {
                result += '?';
                params = _.clone(params);
                if(inBrowser) {
                    params._method = 'POST';
                }
                result += _.chain(params).map(function(v, k){
                    if(_.isArray(v)) {
                        return _.chain(v).map(function(v){
                            return k + '=' + encodeURIComponent(v);
                        }).value().join('&');
                    } else {
                        return k + '=' + encodeURIComponent(v);
                    }
                }).join('&');
            }
            if(inParam) {
                result = encodeURIComponent(result);
            }
            return result;
        };

        $scope.curl = function(){
            return 'curl -X ' + $scope.op.method + ' "' + $scope.getUrl() + '"';
        };

        var getParamByPattern = function(name){
            var paramsWithPatterns = _.filter($scope.op.parameters, function(param){
                return _.isString(param.pattern);
            });
            var param = _.find(paramsWithPatterns, function(param){
                var pattern = new RegExp(param.pattern);
                return pattern.test( name );
            });
            if(_.isObject(param) && (_.isArray(param.value) || _.isString(param.value))){
                // value is already in use
                // need to add another parameter of the same kind
                var newParam = _.clone(param);
                newParam.name = name;
                $scope.op.parameters.push(newParam);
                return newParam;
            } else if (_.isObject(param)){
                param.name = name;
            }
            return param;
        };

        var getParam = function(name){
            var param = _.find($scope.op.parameters, function(param){
                return param.name === name;
            });
            if(_.isObject(param)){
                return param;
            }

            // no direct match let's look for a pattern match
            return getParamByPattern(name);
        };

        $scope.test = function(p) {
            if(p) {
                // reset
                $scope.op = angular.copy(operation);

                // make all values arrays
                p = _.mapValues(p, function(paramValue){
                    if(_.isArray(paramValue)){
                        return paramValue;
                    }
                    return [paramValue];
                });
                _.each(p, function(value, name){
                    var param = getParam(name);
                    if(_.isObject(param)){
                        param.value = value;
                    } else {
                        $log.error(name + ': Parameter does not exist for operation.');
                    }
                });
            }
            // $log.log(JSON.stringify($scope.op.parameters, null, '\t'));
            $scope.loading = true;
            $scope.error = undefined;
            $scope.body = undefined;
            var params = getParams(true /* use camel case params */);
            if(_.keys(params).length > 1) {
                API.Queries[operation.nickname](params)
                    .then(function (body) {
                        $scope.body = _.isString(body) ? body : JSON.stringify(body, null, 2);
                    })
                    .catch(function (error) {
                        $scope.body = _.isString(error.body) ? error.body : JSON.stringify(error.body, null, 2);
                        $scope.error = error;
                    })
                    .finally(function () {
                        $scope.loading = false;
                    });
            } else {
                $scope.error = 'Too few parameters.';
                $scope.body = 'Too few parameters.';
                $scope.loading = false;
            }
        };

        if($scope.examples.length > 0) {
            $scope.test($scope.examples[0].parameters);
        }
    });
<|endoftext|>


<commit_before>import {
  isWormhole
} from './utils'

let cache = {
  baseUrl: 'https://drdyne.github.io/eve-daytripper',
  identified: {},
  mapSolarSystems: []
}

export const mapSolarSystemsCache = () => {
  return ( cache.mapSolarSystems.length )
  ? Promise.resolve(cache.mapSolarSystems)
  : fetch(cache.baseUrl + `/static/mapSolarSystems.json`)
  .then(response => response.json())
  .then(json => {
    cache.mapSolarSystems = json
    return json
  })
}

export const get = id => {
  return mapSolarSystemsCache()
  .then(systems => systems.find(s => id === s.solarSystemID))
  .then(system => ({
    id: system.solarSystemID,
    name: system.solarSystemName,
    sec: system.security
  }))
}

export const identify = name => {
  const Name = name.toUpperCase()
  if ( cache.identified[Name] ) return Promise.resolve(cache.identified[Name])

  //static content served from gh-pages... check /docs/static/typeids/***.json
  //https://drdyne.github.io/eve-daytripper/static/typeids/A.json

  //return fetch(`/static/typeids/${cat}.json`)
  return mapSolarSystemsCache()
  .then(systems => systems.find(s => Name === s.solarSystemName.toUpperCase()))
  .then(system => {
    if ( !system ) return Promise.reject(`Unknown system: ${Name}`)

    const { solarSystemID, solarSystemName, security } = system
    console.log(`identified ${solarSystemID}:${solarSystemName}`)

    cache.identified[Name] = {
      id: solarSystemID,
      name: solarSystemName,
      sec: security
    }
    return cache.identified[Name]
  })
}

const Jita = '30000142'
const Hek = '30002053'
export const route = (origin, destination, options={shortest, safest}) => {
  if ( isWormhole(origin.name) )
    return Promise.reject({"error":"No route found", isWormhole: 'origin'})

  if ( isWormhole(destination.name) )
    return Promise.reject({"error":"No route found", isWormhole: 'destination'})

  const flag = options.shortest
  ? 'shortest'
  : options.safest
  ? 'secure'
  : 'shortest'

  const url = `https://esi.tech.ccp.is/latest/route/${origin.id}/${destination.id}/?datasource=tranquility&flag=${flag}`
  return fetch(url)
  .then(response => response.json())
  .then(route => Promise.all(route.map(get)))
  .then(route => route[0].id === origin.id
  ? route
  : route.reverse()) // sometimes ccp server reverses order /shrug
}

export const shortest = (origin, destination) => (
  route(origin, destination, {shortest: true})
)

export const safest = (origin, destination) => (
  route(origin, destination, {safest :true})
)

export default {
  identify,
  get,
  route,
  shortest,
  safest,
}
<commit_msg>added wh effects/signatures/statics cache to api<commit_after>import {
  isWormhole,
  wormholeId
} from './utils'

let cache = {
  baseUrl: 'https://drdyne.github.io/eve-daytripper/static',
  identified: {},
  mapSolarSystems: [],
  wh: {
    effects: null,
    signatures: null,
    statics: {},
  }
}

const mapSolarSystemsCache = () => {
  return ( cache.mapSolarSystems.length )
  ? Promise.resolve(cache.mapSolarSystems)
  : fetch(cache.baseUrl + `/mapSolarSystems.json`)
  .then(response => response.json())
  .then(json => {
    cache.mapSolarSystems = json
    return json
  })
}

const whSignaturesCache = () => {
  return ( cache.wh.signatures )
  ? Promise.resolve(cache.wh.signatures)
  : fetch(cache.baseUrl + '/wh/signatures.json')
  .then(response => response.json())
  .then(json => {
    cache.wh.signatures = json
    return json
  })
}

const whEffectsCache = () => {
  return ( cache.wh.effects )
  ? Promise.resolve(cache.wh.effects)
  : fetch(cache.baseUrl + '/wh/effects.json')
  .then(response => response.json())
  .then(json => {
    cache.wh.effects = json
    return json
  })
}

const whStaticsCache = id => {
  return ( cache.wh.statics[id] )
  ? Promise.resolve(cache.wh.statics[id])
  : fetch(`${cache.baseUrl}/wh/statics/${id}.json`)
  .then(response => response.json())
  .then(json => {
    cache.wh.statics[id] = json
    return json
  })
}

export const get = id => {
  return mapSolarSystemsCache()
  .then(systems => systems.find(s => id === s.solarSystemID))
  .then(system => ({
    id: system.solarSystemID,
    name: system.solarSystemName,
    sec: system.security
  }))
}

export const identify = name => {
  const Name = name.toUpperCase()
  if ( cache.identified[Name] ) return Promise.resolve(cache.identified[Name])

  //static content served from gh-pages... check /docs/static/typeids/***.json
  //https://drdyne.github.io/eve-daytripper/static/typeids/A.json

  //return fetch(`/static/typeids/${cat}.json`)
  return mapSolarSystemsCache()
  .then(systems => systems.find(s => Name === s.solarSystemName.toUpperCase()))
  .then(system => {
    if ( !system ) return Promise.reject(`Unknown system: ${Name}`)

    const { solarSystemID, solarSystemName, security } = system
    console.log(`identified ${solarSystemID}:${solarSystemName}`)

    cache.identified[Name] = {
      id: solarSystemID,
      name: solarSystemName,
      sec: security
    }
    return cache.identified[Name]
  })
  .then(system => isWormhole(system.name) ? identifyWormhole(system) : system)
}

export const identifyWormhole = system => {
  console.log(system)
  const whid = wormholeId(system)

  return Promise.all([
    whStaticsCache(),
    whSignaturesCache(),
    whEffectsCache(),
  ])
  .then(([statics, signatures, effects]) => {
    console.log(system, statics, signatures, effects)

    return system
  })

}

const Jita = '30000142'
const Hek = '30002053'
export const route = (origin, destination, options={shortest, safest}) => {
  if ( isWormhole(origin.name) )
    return Promise.reject({"error":"No route found", isWormhole: 'origin'})

  if ( isWormhole(destination.name) )
    return Promise.reject({"error":"No route found", isWormhole: 'destination'})

  const flag = options.shortest
  ? 'shortest'
  : options.safest
  ? 'secure'
  : 'shortest'

  const url = `https://esi.tech.ccp.is/latest/route/${origin.id}/${destination.id}/?datasource=tranquility&flag=${flag}`
  return fetch(url)
  .then(response => response.json())
  .then(route => Promise.all(route.map(get)))
  .then(route => route[0].id === origin.id
  ? route
  : route.reverse()) // sometimes ccp server reverses order /shrug
}

export const shortest = (origin, destination) => (
  route(origin, destination, {shortest: true})
)

export const safest = (origin, destination) => (
  route(origin, destination, {safest :true})
)

export default {
  identify,
  get,
  route,
  shortest,
  safest,
}
<|endoftext|>


<commit_before>'use strict';

/*
 * nextroomer is used to build up rooms
 *
 * Bring the controller to level 3 after that build constructionSites
 * and continue upgrading.
 *
 * If the room is 'underSiege', build a tower next to a source, build ramparts
 * and fill the tower.
 */

roles.nextroomer = {};

roles.nextroomer.died = function(name, creepMemory) {
  let roomName = creepMemory.routing.route[creepMemory.routing.routePos].room;
  let message = `${name} ${roomName} ${JSON.stringify(creepMemory)}`;
  if (roomName === creepMemory.routing.targetRoom) {
    // TODO make underSiege to a counter
  }
  // Works but was annoying due to suppen
  // console.log('DIED:', message);
};

roles.nextroomer.settings = {
  layoutString: 'MWC',
  amount: [6, 3, 3],
};

roles.nextroomer.checkForRampart = function(coords) {
  let pos = new RoomPosition(coords.x, coords.y, coords.roomName);
  let structures = pos.lookFor('structure');
  return _.find(structures, (s) => s.structureType === STRUCTURE_RAMPART);
};

roles.nextroomer.buildRamparts = function(creep) {
  let ramparts = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: {
      structureType: STRUCTURE_RAMPART
    }
  });

  // TODO Guess roles.nextroomer should be higher
  let rampartMinHits = 10000;

  creep.say('checkRamparts');
  let posRampart = roles.nextroomer.checkForRampart(creep.pos);
  if (posRampart) {
    if (posRampart.hits < rampartMinHits) {
      creep.repair(posRampart);
      return true;
    }
  } else {
    creep.room.createConstructionSite(creep.pos.x, creep.pos.y, STRUCTURE_RAMPART);
    return true;
  }

  let room = Game.rooms[creep.room.name];
  let linkPosMem = room.memory.position.structure.link[1];
  if (creep.pos.getRangeTo(linkPosMem.x, linkPosMem.y) > 1) {
    linkPosMem = room.memory.position.structure.link[2];
  }

  let links = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: function(object) {
      return object.structureType === STRUCTURE_LINK;
    }
  });
  if (links.length) {
    creep.say('dismantle');
    creep.log(JSON.stringify(links));
    creep.dismantle(links[0]);
    return true;
  }

  creep.say('cr');
  let towerRampart = roles.nextroomer.checkForRampart(linkPosMem);
  if (towerRampart) {
    creep.say('tr');
    if (towerRampart.hits < rampartMinHits) {
      creep.repair(towerRampart);
      return true;
    }
  } else {
    let returnCode = creep.room.createConstructionSite(linkPosMem.x, linkPosMem.y, STRUCTURE_RAMPART);
    creep.log('Build tower rampart: ' + returnCode);
    return true;
  }
  return false;
};

roles.nextroomer.defendTower = function(creep, source) {
  let room = Game.rooms[creep.room.name];
  let constructionSites = creep.pos.findInRange(FIND_CONSTRUCTION_SITES, 1);
  if (constructionSites.length > 0) {
    for (let constructionSiteId in constructionSites) {
      creep.build(constructionSites[constructionSiteId]);
    }
    return true;
  }

  let towers = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: {
      structureType: STRUCTURE_TOWER
    }
  });

  if (towers.length > 0) {
    if (roles.nextroomer.buildRamparts(creep)) {
      return true;
    }

    for (let towerId in towers) {
      let tower = towers[towerId];
      if (tower.energy === tower.energyCapacity) {
        room.memory.underSiege = false;
        return false;
      } else {
        let returnCode = creep.transfer(tower, RESOURCE_ENERGY);
        if (returnCode === OK) {
          return true;
        }

        //if (returnCode === ERR_FULL) {}
        // Don't know what to do
        creep.say(returnCode);
        return true;
      }
    }
    return roles.nextroomer.buildRamparts(creep);
  } else if (roles.nextroomer.buildRamparts(creep)) {
    return true;
  }

  let linkPosMem = room.memory.position.structure.link[1];

  if (creep.pos.getRangeTo(linkPosMem.x, linkPosMem.y) > 2) {
    linkPosMem = room.memory.position.structure.link[2];
  }
  let linkPos = new RoomPosition(linkPosMem.x, linkPosMem.y, linkPosMem.roomName);
  let returnCode = linkPos.createConstructionSite(STRUCTURE_TOWER);
  if (returnCode === ERR_RCL_NOT_ENOUGH) {
    delete room.memory.underSiege;
  }
  creep.log('Build tower: ' + returnCode);
};

roles.nextroomer.stayAtSource = function(creep, source) {
  if (creep.carry.energy < creep.carryCapacity - 30) {
    let returnCode = creep.harvest(source);
    if (returnCode === OK) {
      if (creep.carry.energy >= 0) {
        var creepWithoutEnergy = creep.pos.findClosestByRange(FIND_MY_CREEPS, {
          filter: function(object) {
            return (object.carry.energy === 0 && object.id !== creep.id);
          }
        });
        let range = creep.pos.getRangeTo(creepWithoutEnergy);

        if (range === 1) {
          creep.transfer(creepWithoutEnergy, RESOURCE_ENERGY);
        }
      }
      return true;
    }
  }
  return roles.nextroomer.defendTower(creep, source);
};

roles.nextroomer.underSiege = function(creep) {
  let room = Game.rooms[creep.room.name];
  if (creep.memory.targetId) {
    let sourcerPosMem = room.memory.position.creep[creep.memory.targetId];
    let source = Game.getObjectById(creep.memory.targetId);
    if (creep.pos.isEqualTo(sourcerPosMem.x, sourcerPosMem.y)) {
      return roles.nextroomer.stayAtSource(creep, source);
    } else {
      delete creep.memory.targetId;
    }
  }
  let sources = room.find(FIND_SOURCES);
  for (var sourceId in sources) {
    let source = sources[sourceId];
    let sourcerPosMem = room.memory.position.creep[source.id];
    let sourcerPos = new RoomPosition(sourcerPosMem.x, sourcerPosMem.y, sourcerPosMem.roomName);

    if (creep.pos.isEqualTo(sourcerPos)) {
      creep.memory.targetId = source.id;
      return roles.nextroomer.stayAtSource(creep, source);
    }

    let creeps = sourcerPos.lookFor('creep');
    if (creeps.length === 0) {
      creep.moveTo(sourcerPos.x, sourcerPos.y);
      return true;
    }
  }
  return false;
};

roles.nextroomer.settle = function(creep) {
  let room = Game.rooms[creep.room.name];
  let hostileCreeps = room.find(FIND_HOSTILE_CREEPS);
  if (hostileCreeps.length) {
    room.memory.underSiege = true;
    if (creep.room.controller.ticksToDowngrade < CONTROLLER_DOWNGRADE[creep.room.controller.level] / 10 || creep.room.controller.level === 1) {
      let methods = [Creep.getEnergy, Creep.upgradeControllerTask];
      return Creep.execute(creep, methods);
    }
  }
  room.memory.wayBlocked = false;
  if (room.memory.underSiege && room.controller && room.controller.level >= 3) {
    creep.log('underSiege: ' + room.memory.attackTimer);
    return roles.nextroomer.underSiege(creep);
  }

  if (creep.carry.energy > 0) {
    var towers = creep.room.find(FIND_STRUCTURES, {
      filter: function(object) {
        return (object.structureType === STRUCTURE_TOWER &&
          object.energy < 10);
      }
    });
    if (towers.length) {
      creep.moveTo(towers[0]);
      creep.transfer(towers[0], RESOURCE_ENERGY);
      return true;
    }
  }

  if (_.sum(creep.carry) === 0) {
    let hostileStructures = creep.room.findPropertyFilter(FIND_HOSTILE_STRUCTURES, 'structureType', [STRUCTURE_RAMPART, STRUCTURE_EXTRACTOR, STRUCTURE_WALL, STRUCTURE_CONTROLLER]);
    if (hostileStructures.length) {
      let structure = _.max(hostileStructures, s => s.structureType === STRUCTURE_STORAGE);

      if (structure.structureType === STRUCTURE_STORAGE) {
        if (structure.store.energy === 0) {
          structure.destroy();
          return true;
        }
      } else if (!structure.energy) {
        structure.destroy();
        return true;
      }
      creep.say('ho: ' + structure.pos, true);
      creep.log(structure.structureType);
      creep.moveTo(structure);
      creep.withdraw(structure, RESOURCE_ENERGY);
      return true;
    }
  }

  if (creep.room.energyCapacityAvailable < 300) {
    let constructionSites = creep.room.findPropertyFilter(FIND_CONSTRUCTION_SITES, 'structureType', [STRUCTURE_LAB, STRUCTURE_NUKER, STRUCTURE_TERMINAL]);
    for (let cs of constructionSites) {
      cs.remove();
    }
  }

  let methods = [Creep.getEnergy];
  if (creep.room.controller.ticksToDowngrade < 1500) {
    methods.push(Creep.upgradeControllerTask);
  }
  let structures = creep.room.findPropertyFilter(FIND_MY_CONSTRUCTION_SITES, 'structureType', [STRUCTURE_RAMPART, STRUCTURE_CONTROLLER], true);
  if (creep.room.controller.level >= 3 && structures.length > 0) {
    methods.push(Creep.constructTask);
  }

  if (creep.room.controller.level < 8) {
    methods.push(Creep.upgradeControllerTask);
  }

  methods.push(Creep.transferEnergy);
  return Creep.execute(creep, methods);
};

roles.nextroomer.preMove = function(creep, directions) {
  if (!directions) {
    return false;
  }
  let posForward = creep.pos.getAdjacentPosition(directions.forwardDirection);
  let structures = posForward.lookFor(LOOK_STRUCTURES);
  for (let structure of structures) {
    if (structure.structureType === STRUCTURE_ROAD) {
      continue;
    }
    if (structure.structureType === STRUCTURE_RAMPART && structure.my) {
      continue;
    }

    creep.dismantle(structure);
    creep.say('dismantle');
    break;
  }
};

roles.nextroomer.action = function(creep) {
  // TODO when does this happen?
  if (creep.room.name != creep.memory.routing.targetRoom) {
    delete creep.memory.routing.reached;
    return false;
  }

  // TODO ugly fix cause, target gets deleted
  creep.memory.targetBackup = creep.memory.targetBackup || creep.memory.target;
  if (creep.room.name === creep.memory.targetBackup) {
    return roles.nextroomer.settle(creep);
  }
  return roles.nextroomer.settle(creep);
};

roles.nextroomer.execute = function(creep) {
  creep.log('Execute!!!');
  //creep.moveTo(25, 25);
};
<commit_msg>Do not care about hostile creeps if safe mode is active (and will not end until all hostile creeps are die)<commit_after>'use strict';

/*
 * nextroomer is used to build up rooms
 *
 * Bring the controller to level 3 after that build constructionSites
 * and continue upgrading.
 *
 * If the room is 'underSiege', build a tower next to a source, build ramparts
 * and fill the tower.
 */

roles.nextroomer = {};

roles.nextroomer.died = function(name, creepMemory) {
  let roomName = creepMemory.routing.route[creepMemory.routing.routePos].room;
  let message = `${name} ${roomName} ${JSON.stringify(creepMemory)}`;
  if (roomName === creepMemory.routing.targetRoom) {
    // TODO make underSiege to a counter
  }
  // Works but was annoying due to suppen
  // console.log('DIED:', message);
};

roles.nextroomer.settings = {
  layoutString: 'MWC',
  amount: [6, 3, 3],
};

roles.nextroomer.checkForRampart = function(coords) {
  let pos = new RoomPosition(coords.x, coords.y, coords.roomName);
  let structures = pos.lookFor('structure');
  return _.find(structures, (s) => s.structureType === STRUCTURE_RAMPART);
};

roles.nextroomer.buildRamparts = function(creep) {
  let ramparts = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: {
      structureType: STRUCTURE_RAMPART
    }
  });

  // TODO Guess roles.nextroomer should be higher
  let rampartMinHits = 10000;

  creep.say('checkRamparts');
  let posRampart = roles.nextroomer.checkForRampart(creep.pos);
  if (posRampart) {
    if (posRampart.hits < rampartMinHits) {
      creep.repair(posRampart);
      return true;
    }
  } else {
    creep.room.createConstructionSite(creep.pos.x, creep.pos.y, STRUCTURE_RAMPART);
    return true;
  }

  let room = Game.rooms[creep.room.name];
  let linkPosMem = room.memory.position.structure.link[1];
  if (creep.pos.getRangeTo(linkPosMem.x, linkPosMem.y) > 1) {
    linkPosMem = room.memory.position.structure.link[2];
  }

  let links = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: function(object) {
      return object.structureType === STRUCTURE_LINK;
    }
  });
  if (links.length) {
    creep.say('dismantle');
    creep.log(JSON.stringify(links));
    creep.dismantle(links[0]);
    return true;
  }

  creep.say('cr');
  let towerRampart = roles.nextroomer.checkForRampart(linkPosMem);
  if (towerRampart) {
    creep.say('tr');
    if (towerRampart.hits < rampartMinHits) {
      creep.repair(towerRampart);
      return true;
    }
  } else {
    let returnCode = creep.room.createConstructionSite(linkPosMem.x, linkPosMem.y, STRUCTURE_RAMPART);
    creep.log('Build tower rampart: ' + returnCode);
    return true;
  }
  return false;
};

roles.nextroomer.defendTower = function(creep, source) {
  let room = Game.rooms[creep.room.name];
  let constructionSites = creep.pos.findInRange(FIND_CONSTRUCTION_SITES, 1);
  if (constructionSites.length > 0) {
    for (let constructionSiteId in constructionSites) {
      creep.build(constructionSites[constructionSiteId]);
    }
    return true;
  }

  let towers = creep.pos.findInRange(FIND_STRUCTURES, 1, {
    filter: {
      structureType: STRUCTURE_TOWER
    }
  });

  if (towers.length > 0) {
    if (roles.nextroomer.buildRamparts(creep)) {
      return true;
    }

    for (let towerId in towers) {
      let tower = towers[towerId];
      if (tower.energy === tower.energyCapacity) {
        room.memory.underSiege = false;
        return false;
      } else {
        let returnCode = creep.transfer(tower, RESOURCE_ENERGY);
        if (returnCode === OK) {
          return true;
        }

        //if (returnCode === ERR_FULL) {}
        // Don't know what to do
        creep.say(returnCode);
        return true;
      }
    }
    return roles.nextroomer.buildRamparts(creep);
  } else if (roles.nextroomer.buildRamparts(creep)) {
    return true;
  }

  let linkPosMem = room.memory.position.structure.link[1];

  if (creep.pos.getRangeTo(linkPosMem.x, linkPosMem.y) > 2) {
    linkPosMem = room.memory.position.structure.link[2];
  }
  let linkPos = new RoomPosition(linkPosMem.x, linkPosMem.y, linkPosMem.roomName);
  let returnCode = linkPos.createConstructionSite(STRUCTURE_TOWER);
  if (returnCode === ERR_RCL_NOT_ENOUGH) {
    delete room.memory.underSiege;
  }
  creep.log('Build tower: ' + returnCode);
};

roles.nextroomer.stayAtSource = function(creep, source) {
  if (creep.carry.energy < creep.carryCapacity - 30) {
    let returnCode = creep.harvest(source);
    if (returnCode === OK) {
      if (creep.carry.energy >= 0) {
        var creepWithoutEnergy = creep.pos.findClosestByRange(FIND_MY_CREEPS, {
          filter: function(object) {
            return (object.carry.energy === 0 && object.id !== creep.id);
          }
        });
        let range = creep.pos.getRangeTo(creepWithoutEnergy);

        if (range === 1) {
          creep.transfer(creepWithoutEnergy, RESOURCE_ENERGY);
        }
      }
      return true;
    }
  }
  return roles.nextroomer.defendTower(creep, source);
};

roles.nextroomer.underSiege = function(creep) {
  let room = Game.rooms[creep.room.name];
  if (creep.memory.targetId) {
    let sourcerPosMem = room.memory.position.creep[creep.memory.targetId];
    let source = Game.getObjectById(creep.memory.targetId);
    if (creep.pos.isEqualTo(sourcerPosMem.x, sourcerPosMem.y)) {
      return roles.nextroomer.stayAtSource(creep, source);
    } else {
      delete creep.memory.targetId;
    }
  }
  let sources = room.find(FIND_SOURCES);
  for (var sourceId in sources) {
    let source = sources[sourceId];
    let sourcerPosMem = room.memory.position.creep[source.id];
    let sourcerPos = new RoomPosition(sourcerPosMem.x, sourcerPosMem.y, sourcerPosMem.roomName);

    if (creep.pos.isEqualTo(sourcerPos)) {
      creep.memory.targetId = source.id;
      return roles.nextroomer.stayAtSource(creep, source);
    }

    let creeps = sourcerPos.lookFor('creep');
    if (creeps.length === 0) {
      creep.moveTo(sourcerPos.x, sourcerPos.y);
      return true;
    }
  }
  return false;
};

roles.nextroomer.settle = function(creep) {
  let room = Game.rooms[creep.room.name];
  let hostileCreeps = room.find(FIND_HOSTILE_CREEPS, {filter: creep => !room.controller.safeMode || creep.ticksToLive > room.controller.safeMode});
  if (hostileCreeps.length) {
    room.memory.underSiege = true;
    if (creep.room.controller.ticksToDowngrade < CONTROLLER_DOWNGRADE[creep.room.controller.level] / 10 || creep.room.controller.level === 1) {
      let methods = [Creep.getEnergy, Creep.upgradeControllerTask];
      return Creep.execute(creep, methods);
    }
  }
  room.memory.wayBlocked = false;
  if (room.memory.underSiege && room.controller && room.controller.level >= 3) {
    creep.log('underSiege: ' + room.memory.attackTimer);
    return roles.nextroomer.underSiege(creep);
  }

  if (creep.carry.energy > 0) {
    var towers = creep.room.find(FIND_STRUCTURES, {
      filter: function(object) {
        return (object.structureType === STRUCTURE_TOWER &&
          object.energy < 10);
      }
    });
    if (towers.length) {
      creep.moveTo(towers[0]);
      creep.transfer(towers[0], RESOURCE_ENERGY);
      return true;
    }
  }

  if (_.sum(creep.carry) === 0) {
    let hostileStructures = creep.room.findPropertyFilter(FIND_HOSTILE_STRUCTURES, 'structureType', [STRUCTURE_RAMPART, STRUCTURE_EXTRACTOR, STRUCTURE_WALL, STRUCTURE_CONTROLLER]);
    if (hostileStructures.length) {
      let structure = _.max(hostileStructures, s => s.structureType === STRUCTURE_STORAGE);

      if (structure.structureType === STRUCTURE_STORAGE) {
        if (structure.store.energy === 0) {
          structure.destroy();
          return true;
        }
      } else if (!structure.energy) {
        structure.destroy();
        return true;
      }
      creep.say('ho: ' + structure.pos, true);
      creep.log(structure.structureType);
      creep.moveTo(structure);
      creep.withdraw(structure, RESOURCE_ENERGY);
      return true;
    }
  }

  if (creep.room.energyCapacityAvailable < 300) {
    let constructionSites = creep.room.findPropertyFilter(FIND_CONSTRUCTION_SITES, 'structureType', [STRUCTURE_LAB, STRUCTURE_NUKER, STRUCTURE_TERMINAL]);
    for (let cs of constructionSites) {
      cs.remove();
    }
  }

  let methods = [Creep.getEnergy];
  if (creep.room.controller.ticksToDowngrade < 1500) {
    methods.push(Creep.upgradeControllerTask);
  }
  let structures = creep.room.findPropertyFilter(FIND_MY_CONSTRUCTION_SITES, 'structureType', [STRUCTURE_RAMPART, STRUCTURE_CONTROLLER], true);
  if (creep.room.controller.level >= 3 && structures.length > 0) {
    methods.push(Creep.constructTask);
  }

  if (creep.room.controller.level < 8) {
    methods.push(Creep.upgradeControllerTask);
  }

  methods.push(Creep.transferEnergy);
  return Creep.execute(creep, methods);
};

roles.nextroomer.preMove = function(creep, directions) {
  if (!directions) {
    return false;
  }
  let posForward = creep.pos.getAdjacentPosition(directions.forwardDirection);
  let structures = posForward.lookFor(LOOK_STRUCTURES);
  for (let structure of structures) {
    if (structure.structureType === STRUCTURE_ROAD) {
      continue;
    }
    if (structure.structureType === STRUCTURE_RAMPART && structure.my) {
      continue;
    }

    creep.dismantle(structure);
    creep.say('dismantle');
    break;
  }
};

roles.nextroomer.action = function(creep) {
  // TODO when does this happen?
  if (creep.room.name != creep.memory.routing.targetRoom) {
    delete creep.memory.routing.reached;
    return false;
  }

  // TODO ugly fix cause, target gets deleted
  creep.memory.targetBackup = creep.memory.targetBackup || creep.memory.target;
  if (creep.room.name === creep.memory.targetBackup) {
    return roles.nextroomer.settle(creep);
  }
  return roles.nextroomer.settle(creep);
};

roles.nextroomer.execute = function(creep) {
  creep.log('Execute!!!');
  //creep.moveTo(25, 25);
};
<|endoftext|>


<commit_before>export default class ROMGraphics {
	constructor(bitsPerPixel) {
		this.bitsPerPixel = bitsPerPixel;
	}
	/* Internal function - builds the tile array from the gfx buffer. */
	buildTiles() {
		let n = this.gfxROMGraphics.length / (8 * this.bitsPerPixel);
		this.tiles = [];
		for (let i = 0; i < n; ++i) {
			this.tiles.push(new Array(8));
			let o = i * 8 * this.bitsPerPixel;
			for (let x = 0; x < 8; ++x) {
				this.tiles[i][x] = new Array(8);
				for (let y = 0; y < 8; ++y) {
					let c = 0;
					for (let bp = 0; bp < this.bitsPerPixel; ++bp) {
						// N.B. such a slight bug! we must Math.floor this value,
						// do to the possibility of a number like 0.5 (should equal 0)
						let halfBp = Math.floor(bp / 2);
						let gfx = this.gfxROMGraphics[o + y * 2 + (halfBp * 16 + (bp & 1))];
						c += ((gfx & (1 << 7 - x)) >> 7 - x) << bp;
					}
					this.tiles[i][x][y] = c;
				}
			}
		}
	}
	/* JNI C code */
	draw(bmp, palette, arrayROMGraphics) {
		let data = bmp;
		let block = 0, tile = 0, subPalette = 0;
		let n = 0, b1 = 0, b2 = 0;
		let verticalFlip = false, horizontalFlip = false;
		// TODO: hardcoding is bad; how do I get the stride normally?
		let stride = 1024;
		/* For each pixel in the 256×256 grid, we need to render the image found in the dump */
		for (let i = 0; i < 32; ++i) {
			for (let j = 0; j < 32; ++j) {
				n = j * 32 + i;
				b1 = arrayROMGraphics[n * 2];
				b2 = arrayROMGraphics[n * 2 + 1] << 8;
				block = b1 + b2;
				tile = block & 0x3FF;
				verticalFlip = (block & 0x8000) !== 0;
				horizontalFlip = (block & 0x4000) !== 0;
				subPalette = (block >> 10) & 7;
				this.drawTile(data, stride, i * 8, j * 8, palette, tile, subPalette, verticalFlip, horizontalFlip);
			}
		}
		return data;
	}
	drawTile(pixels, stride, x, y, palette, tile, subPalette, verticalFlip, horizontalFlip) {
		let i, j, px, py;
		for (i = 0; i < 8; ++i) {
			for (j = 0; j < 8; ++j) {
				let rgbArray = this.getRGBPalette(palette, tile, subPalette, i, j);
				if (horizontalFlip) {
					px = x + 7 - i;
				}
				else {
					px = x + i;
				}
				if (verticalFlip) {
					py = y + 7 - j;
				}
				else {
					py = y + j;
				}
				let pos = 4 * px + stride * py;
				pixels[pos + 0] = (rgbArray >> 16) & 0xFF;
				pixels[pos + 1] = (rgbArray >> 8) & 0xFF;
				pixels[pos + 2] = (rgbArray) & 0xFF;
			}
		}
		return pixels;
	}
	getRGBPalette(palette, tile, subPalette, i, j) {
		let pos = this.tiles[tile][i][j];
		let colorChunk = palette.getColors(subPalette)[pos];
		return colorChunk;
	}
	/**
	* Internal function - reads graphics from the specified block and builds
	* tileset.
	*
	* @param block
	* The block to read graphics data from
	*/
	loadGraphics(block) {
		this.gfxROMGraphics = new Int16Array();
		this.gfxROMGraphics = block.decompress();
		this.address = block.address;
		this.buildTiles();
	}
};
<commit_msg>Moved some calculations out of inner loop<commit_after>export default class ROMGraphics {
	constructor(bitsPerPixel) {
		this.bitsPerPixel = bitsPerPixel;
	}
	/* Internal function - builds the tile array from the gfx buffer. */
	buildTiles() {
		let n = this.gfxROMGraphics.length / (8 * this.bitsPerPixel);
		this.tiles = [];
		for (let i = 0; i < n; ++i) {
			this.tiles.push(new Array(8));
			let o = i * 8 * this.bitsPerPixel;
			for (let x = 0; x < 8; ++x) {
				this.tiles[i][x] = new Array(8);
				for (let y = 0; y < 8; ++y) {
					let c = 0;
					for (let bp = 0; bp < this.bitsPerPixel; ++bp) {
						// NOTE: Such a slight bug! We must Math.floor this value, due to the possibility of a number like 0.5 (which should equal 0).
						let halfBp = Math.floor(bp / 2);
						let gfx = this.gfxROMGraphics[o + y * 2 + (halfBp * 16 + (bp & 1))];
						c += ((gfx & (1 << 7 - x)) >> 7 - x) << bp;
					}
					this.tiles[i][x][y] = c;
				}
			}
		}
	}
	/* JNI C code */
	draw(bmp, palette, arrayROMGraphics) {
		let data = bmp;
		let block = 0, tile = 0, subPalette = 0;
		let n = 0, b1 = 0, b2 = 0;
		let verticalFlip = false, horizontalFlip = false;
		// TODO: hardcoding is bad; how do I get the stride normally?
		let stride = 1024;
		/* For each pixel in the 256×256 grid, we need to render the image found in the dump */
		for (let i = 0; i < 32; ++i) {
			for (let j = 0; j < 32; ++j) {
				n = j * 32 + i;
				b1 = arrayROMGraphics[n * 2];
				b2 = arrayROMGraphics[n * 2 + 1] << 8;
				block = b1 + b2;
				tile = block & 0x3FF;
				verticalFlip = (block & 0x8000) !== 0;
				horizontalFlip = (block & 0x4000) !== 0;
				subPalette = (block >> 10) & 7;
				this.drawTile(data, stride, i * 8, j * 8, palette, tile, subPalette, verticalFlip, horizontalFlip);
			}
		}
		return data;
	}
	drawTile(pixels, stride, x, y, palette, tile, subPalette, verticalFlip, horizontalFlip) {
		let i, j, px, py, pos, rgbArray, subPaletteArray = palette.getColors(subPalette);
		for (i = 0; i < 8; ++i) {
			if (horizontalFlip) {
				px = x + 7 - i;
			}
			else {
				px = x + i;
			}
			for (j = 0; j < 8; ++j) {
				rgbArray = subPaletteArray[this.tiles[tile][i][j]];
				if (verticalFlip) {
					py = y + 7 - j;
				}
				else {
					py = y + j;
				}
				pos = 4 * px + stride * py;
				pixels[pos + 0] = (rgbArray >> 16) & 0xFF;
				pixels[pos + 1] = (rgbArray >> 8) & 0xFF;
				pixels[pos + 2] = (rgbArray) & 0xFF;
			}
		}
		return pixels;
	}
	/**
	* Internal function - reads graphics from the specified block and builds
	* tileset.
	*
	* @param block
	* The block to read graphics data from
	*/
	loadGraphics(block) {
		this.gfxROMGraphics = new Int16Array();
		this.gfxROMGraphics = block.decompress();
		this.address = block.address;
		this.buildTiles();
	}
};
<|endoftext|>


<commit_before>//system args :
//	- system.args[0] : phantomjs-script.js path
//	- system.args[1] : width
//	- system.args[2] : height
//	- system.args[3] : url
//	- system.args[4] : ip of user (to save screenshot on server)

//send data to node application with console.log('key_name:stdout_key:'+data)
//keys_names (examples) :
//  - resource_requested
//  - resource_received
//  - start
//  - end
//  - ok
//  - warning
//  - err
//  - time
//  - screenshot
//  - html
//  - css
//  - script
//  - ...
//example : console.log('resource_requested:stdout_key:'+msg);
var page = require('webpage').create()
,	system = require('system')
;

//this function is load each time a resource is requested
page.onResourceRequested = function(requestData, networkRequest) {
    console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData.url));
};
//this function is load each time a resource is received
page.onResourceReceived = function(response) {
    console.log(' received : ' + JSON.stringify(response.url));
    console.log('console:stdout_key:HTTP GET (200) ' + JSON.stringify(response.url));
};
//this function is load each time a message was written in sand-boxed console of the evaluate function
page.onConsoleMessage = function (msg) {
    console.log(msg);
};

function getCssResources (page) {
    page.evaluate(function() {
        var stylesheets = document.styleSheets;
        for (var i = 0; i < stylesheets.length; i++){
            for (var j = 0; j < stylesheets[i].cssRules.length; j++) {
                console.log('css:stdout_key:' + i + stylesheets[i].cssRules[j].cssText);
            }
        }
        return document;
    });
}
function getHtmlResources (page) {
    console.log('html:stdout_key:' + page.content);
}
//this function have to send DOM (document)
//don't work with success for the moment.
function getDOM (page) {
    var dom = page.evaluate(function() {
        return document;
    });
    console.log('dom:stdout_key:' + JSON.stringify(dom));
}
function getScreenshot (page) {
    page.render('./public/screenshots/' + system.args[4] + '.png', {format: 'png', quality: '100'});
    console.log('screenshot:stdout_key:' + system.args[4] + '.png');
}
function getDocumentWidth (page) {
    page.evaluate(function () {
        console.log('doc-width:stdout_key:' +document.width);
    });
}

page.viewportSize = { width: system.args[1], height: system.args[2] };
page.clipRect = { top: 0, left: 0, width: system.args[1], height: system.args[2] };

var time = Date.now();
page.open(system.args[3], function (status) {
  	if (status !== 'success') {
        console.log('FAIL to load the address');
  	} else {
    	time = Date.now() - time;
    	console.log('time:stdout_key:' + time);
  	}
    getScreenshot(page);
    getCssResources(page);
    getHtmlResources(page);
    getDocumentWidth(page);
    phantom.exit();
});

<commit_msg>configure phantomjs to react properly to meta viewport when rendering<commit_after>//system args :
//	- system.args[0] : phantomjs-script.js path
//	- system.args[1] : width
//	- system.args[2] : height
//	- system.args[3] : url
//	- system.args[4] : ip of user (to save screenshot on server)

//send data to node application with console.log('key_name:stdout_key:'+data)
//keys_names (examples) :
//  - resource_requested
//  - resource_received
//  - start
//  - end
//  - ok
//  - warning
//  - err
//  - time
//  - screenshot
//  - html
//  - css
//  - script
//  - ...
//example : console.log('resource_requested:stdout_key:'+msg);
var page = require('webpage').create()
,	system = require('system')
,       metaparser = require('./metaviewport-parser')
;

//this function is load each time a resource is requested
page.onResourceRequested = function(requestData, networkRequest) {
    console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData.url));
};
//this function is load each time a resource is received
page.onResourceReceived = function(response) {
    console.log(' received : ' + JSON.stringify(response.url));
    console.log('console:stdout_key:HTTP GET (200) ' + JSON.stringify(response.url));
};
//this function is load each time a message was written in sand-boxed console of the evaluate function
page.onConsoleMessage = function (msg) {
    console.log(msg);
};

function getCssResources (page) {
    page.evaluate(function() {
        var stylesheets = document.styleSheets;
        for (var i = 0; i < stylesheets.length; i++){
            for (var j = 0; j < stylesheets[i].cssRules.length; j++) {
                console.log('css:stdout_key:' + i + stylesheets[i].cssRules[j].cssText);
            }
        }
        return document;
    });
}
function getHtmlResources (page) {
    console.log('html:stdout_key:' + page.content);
}
//this function have to send DOM (document)
//don't work with success for the moment.
function getDOM (page) {
    var dom = page.evaluate(function() {
        return document;
    });
    console.log('dom:stdout_key:' + JSON.stringify(dom));
}
function getScreenshot (page) {
    var contentAttr = page.evaluate(function () {
        var viewports = document.querySelectorAll('meta[name=viewport]');
        if (viewports.length > 0) {
            return viewports[viewports.length - 1].getAttribute("content");
        }
        return null;
    });
    var renderingData;
    if (contentAttr) {
        var viewportProps = metaparser.parseMetaViewPortContent(contentAttr);
        renderingData = metaparser.getRenderingDataFromViewport(viewportProps.validProperties, system.args[1], system.args[2], 4, 0.25 );
    } else {
        renderingData = {zoom: null, width: system.args[1]*3, height: system.args[2]*3};
    }
    page.viewportSize = { width: renderingData.width, height: renderingData.height };

    page.clipRect = { top: 0, left: 0, width: renderingData.width, height: renderingData.height };

    page.render('./public/screenshots/' + system.args[4] + '.png', {format: 'png', quality: '100'});
    console.log('screenshot:stdout_key:' + system.args[4] + '.png');
}
function getDocumentWidth (page) {
    page.evaluate(function () {
        console.log('doc-width:stdout_key:' +document.width);
    });
}

var time = Date.now();
page.open(system.args[3], function (status) {
  	if (status !== 'success') {
        console.log('FAIL to load the address');
  	} else {
    	time = Date.now() - time;
    	console.log('time:stdout_key:' + time);
  	}
    getScreenshot(page);
    getCssResources(page);
    getHtmlResources(page);
    getDocumentWidth(page);
    phantom.exit();
});

<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { graphql, gql } from 'react-apollo'
import moment from 'moment'

import Page from '../layouts/main'

class ChatList extends Component {

  render() {
    const { data: { loading, error, allChatrooms, _allChatroomsMeta }, onClickChatroom } = this.props;
    if (loading) return
Loading

    if (error) return
Error: {error}

    if (allChatrooms) {
      if (allChatrooms.length === 0) return
No chats yet 😂

      return (

Total chats: {_allChatroomsMeta.count}

            {allChatrooms.map((chat, index) => {
              return (

 onClickChatroom(chat.id)}>

{chat.title}({chat._messagesMeta.count})

{moment(chat.createdAt).fromNow()}

              )
            })}

      )
    }
    console.log('bottom loading, null?', allChatrooms)
    return
Loading

  }
}

export const ALL_CHATROOMS_QUERY = gql`
  query allChatrooms {
    allChatrooms(orderBy: createdAt_DESC) {
      id
      title
      createdAt
      _messagesMeta {
        count
      }
    }

    _allChatroomsMeta {
      count
    }
  }
`

ChatList.propTypes = {
  onClickChatroom: React.PropTypes.func.isRequired,
};

export default graphql(ALL_CHATROOMS_QUERY)(ChatList)
<commit_msg>Remove unused log<commit_after>import React, { Component } from 'react';
import { graphql, gql } from 'react-apollo'
import moment from 'moment'

import Page from '../layouts/main'

class ChatList extends Component {

  render() {
    const { data: { loading, error, allChatrooms, _allChatroomsMeta }, onClickChatroom } = this.props;
    if (loading) return
Loading

    if (error) return
Error: {error}

    if (allChatrooms) {
      if (allChatrooms.length === 0) return
No chats yet 😂

      return (

Total chats: {_allChatroomsMeta.count}

            {allChatrooms.map((chat, index) => {
              return (

 onClickChatroom(chat.id)}>

{chat.title}({chat._messagesMeta.count})

{moment(chat.createdAt).fromNow()}

              )
            })}

      )
    }
    return
Loading

  }
}

export const ALL_CHATROOMS_QUERY = gql`
  query allChatrooms {
    allChatrooms(orderBy: createdAt_DESC) {
      id
      title
      createdAt
      _messagesMeta {
        count
      }
    }

    _allChatroomsMeta {
      count
    }
  }
`

ChatList.propTypes = {
  onClickChatroom: React.PropTypes.func.isRequired,
};

export default graphql(ALL_CHATROOMS_QUERY)(ChatList)
<|endoftext|>


<commit_before>var fs = require('fs')
  , path = require('path')
  , swig = require('swig')
  , async = require('async')

// TODO - better name - this is block:func plugin map
var cache = {};

// Generate func for string template names
var registerTemplate = function(name, template, dir){
  cache[name] = function(context, cb){
    if (/\.html$/.test(template)){
      dir = dir || '.'
      template = fs.readFileSync(path.join(dir, template), 'utf8');
    }
    cb(null, template);
  }
}

var registerBlock = function(block, render){
  cache[block] = render;
}

// This generates a generator that will
// render the appropriate block in a form
// suitable for async.parallel.
var getPluginTemplate = function(name){
  var ctx = this;
  return function(cb){
    if (cache[name]){
      cache[name](ctx, function(err, res){
        if (err) return cb(err);
        cb(null, [name, res]);
      });
    } else {
      cb(null, null);
    }
  }
}

// Express 3 Template Engine
var engine = function(path, options, fn){
  //console.log("Plugin Engine () :", path);
  options.filename = path;

  fs.readFile(path, 'utf8', function(err, str){
    if (err) return fn(err);
    engine.render(str, options, fn);
  });
}

// This Render function is a bit complicated, as we're essentially
// monkeypatching swig.render to async collect the appropriate
// extension blocks, render them, and then render them into the
// template.
//
// Because we don't know which blocks are on which page, we actually
// end up rendering the template twice - first to work out which
// blocks are needed, and second, to actually insert them.
engine.render = function(str, options, fn){
  try {
    // Compile

    options._striderRegister = [] // register of templates needed
    options._striderBlocks = {} // output of pluginblocks

    var tmpl = swig.compile(str, options);

    // Which plugins were needed?
    // Render 1st pass
    tmpl(options);
    var exts = options._striderRegister.map(getPluginTemplate, options);

    // Call each block of plugin
    async.parallel(exts, function(err, blocks){
      if (err) return fn(err);

      for (var i=0; i< blocks.length; i++){
        if (blocks[i]){
          options._striderBlocks[blocks[i][0]] = blocks[i][1];
        }
      }

      // Render template with the _striderBlocks
      fn(null, tmpl(options));
    })

  } catch (err) {
    fn(err);
  }
}

module.exports = {
    registerBlock: registerBlock
  , registerTemplate: registerTemplate
  , engine : engine
}

<commit_msg>cleanup plugin template<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var swig = require('swig');
var async = require('async');

// TODO - better name - this is block:func plugin map
var cache = {};

// Generate func for string template names
function registerTemplate (name, template, dir) {
  cache[name] = function (context, cb) {
    if (/\.html$/.test(template)){
      dir = dir || '.'
      template = fs.readFileSync(path.join(dir, template), 'utf8');
    }

    cb(null, template);
  }
}

function registerBlock(block, render) {
  cache[block] = render;
}

// This generates a generator that will
// render the appropriate block in a form
// suitable for async.parallel.
function getPluginTemplate(name) {
  var ctx = this;

  return function (cb) {
    if (cache[name]){
      cache[name](ctx, function (err, res) {
        if (err) return cb(err);
        cb(null, [name, res]);
      });
    } else {
      cb(null, null);
    }
  }
}

// Express 3 Template Engine
function engine(path, options, fn) {
  //console.log("Plugin Engine () :", path);
  options.filename = path;

  fs.readFile(path, 'utf8', function (err, str) {
    if (err) return fn(err);
    engine.render(str, options, fn);
  });
}

// This Render function is a bit complicated, as we're essentially
// monkeypatching swig.render to async collect the appropriate
// extension blocks, render them, and then render them into the
// template.
//
// Because we don't know which blocks are on which page, we actually
// end up rendering the template twice - first to work out which
// blocks are needed, and second, to actually insert them.
engine.render = function (str, options, fn) {
  try {
    // Compile
    options._striderRegister = [] // register of templates needed
    options._striderBlocks = {} // output of pluginblocks

    var tmpl = swig.compile(str, options);

    // Which plugins were needed?
    // Render 1st pass
    tmpl(options);
    var exts = options._striderRegister.map(getPluginTemplate, options);

    // Call each block of plugin
    async.parallel(exts, function(err, blocks){
      if (err) return fn(err);

      for (var i=0; i< blocks.length; i++){
        if (blocks[i]){
          options._striderBlocks[blocks[i][0]] = blocks[i][1];
        }
      }

      // Render template with the _striderBlocks
      fn(null, tmpl(options));
    });

  } catch (err) {
    fn(err);
  }
};

module.exports = {
  registerBlock: registerBlock,
  registerTemplate: registerTemplate,
  engine: engine
};
<|endoftext|>