<commit_before>/*global self: true, fl */
"use strict";
"use babel";

self.fl = {};

const _ = require("lodash");
const api = require("./common/api");
const atomUtils = require("./atom_utils");
const message_action = require("./common/message_action");
const utils = require("./utils");
const usersModel = require("./common/user_model");
const prefs = require("./common/userPref_model");
const FlooUrl = require("./floourl").FlooUrl;
const open_url = require("open");
const buffer = require("./common/buffer_model");
const Terminals = require("./common/terminal_model").Terminals;
const Filetree = require("./common/filetree_model");

const floop = require("./common/floop");
const floorc = require("./common/floorc");
const FlooHandler = require("./common/handlers/floohandler").FlooHandler;

module.exports = {
  floobits: null,
  config: {
    audioOnly: {
      default: false,
      type: "boolean",
      description: "Disables video while video chatting."
    },
    showNotifications: {
      default: true,
      type: "boolean",
      description: "Enables Chrome desktop notifications."
    },
    mugshots: {
      default: false,
      type: "boolean",
      description: "Takes a snapshot every 60 seconds."
    },
    sound: {
      default: true,
      type: "boolean",
      description: "Plays sounds on join/part for other users for chatting."
    },
    userList: {
      title: "User List Panel",
      default: true,
      type: "boolean",
      description: "Opens the User list panel when you join a workspace."
    },
    source_audio_id: {
      title: "Audio Device ID",
      type: "string",
      default: "-1",
      description: "The device ID of the audio input for WebRTC.  Do not change manually!"
    },
    source_audio_name: {
      title: "Audio Device Name",
      type: "string",
      default: "Default",
      description: "The device name of the audio input for WebRTC.  Do not change manually!"
    },
    source_video_id: {
      title: "Video Source ID",
      type: "string",
      default: "-1",
      description: "The device id of the video input for WebRTC.  Do not change manually!"
    },
    source_video_name: {
      title: "Video Source Name",
      type: "string",
      default: "-1",
      description: "The device name of the video input for WebRTC.  Do not change manually!"
    },
  },
  welcome: function () {
    const Webview = require("./build/webview");
    const view = new Webview();
    const constants = require("./common/constants");
    view.load(constants.HOST);
  },
  mediaSource_: function (type) {
    MediaStreamTrack.getSources(function (sources) {
      const audio = sources.filter(function (s) {
        return s.kind === type;
      });
      const Sources = require("./media_sources");
      const view = new Sources(audio, function (source) {
        atom.config.set("floobits.source_" + type + "_id", source.id);
        atom.config.set("floobits.source_" + type + "_name", source.label);
      });
      atom.workspace.addTopPanel({item: view});
      view.focusFilterEditor();
    });
  },
  audioSources: function () {
    this.mediaSource_("audio");
  },
  videoSources: function () {
    this.mediaSource_("video");
  },
  activate: function () {
    const that = this;

    // Turn off metrics for everyone who installs our package
    // We include a note in our README, so this is OK!
    // atom.packages.disablePackage("metrics");
    if (!_.size(floorc.auth)) {
      setTimeout(this.welcome.bind(this), 0);
    }
    atom.commands.add("atom-workspace", {
      "floobits: create workspace": this.create_workspace.bind(this),
      "floobits: join workspace": this.join_workspace.bind(this),
      "floobits: leave workspace": this.leave_workspace.bind(this),
      "floobits: join recent workspace": this.join_recent_workspace.bind(this),
      "floobits: audio source": this.audioSources.bind(this),
      "floobits: video source": this.videoSources.bind(this),
    });

    this.users = new usersModel.Users();
    this.me = new usersModel.User();
    this.bufs = new buffer.Buffers();
    this.terminals = new Terminals([], {users: this.users});
    this.filetree = new Filetree();

    function onConfigUpdate (canJoin, config) {
      try {
        // Deprecation: Use ::getDirectories instead
        const dir = atom.project.getRootDirectory();
        const pathToFloobits = config["atoms-api-sucks-path"];
        const diff = {};

        _.each(config, function (value, key) {
          if (_.has(prefs.schema, key) && prefs[key] !== value) {
            diff[key] = value;
          }
        });

        if (!_.isEmpty(diff)) {
          prefs.set(diff);
          console.log("updated user prefs", diff);
        }

        if (!canJoin) {
          return;
        }

        prefs.requestNotificationPermission();

        if (!dir || !pathToFloobits || dir.path !== pathToFloobits) {
          return;
        }

        if (!config["atoms-api-sucks-url"]) {
          console.error("'floobits.atoms-api-sucks-url' isn't set?!? ");
          return;
        }
        atom.config.set("floobits.atoms-api-sucks-path", null);
        console.log("found pathToFloobits, will floobits");

        that.join_workspace_(dir.path, config["atoms-api-sucks-url"]);
      } catch (e) {
        console.error(e);
      }
    }

    atom.config.observe("floobits", onConfigUpdate.bind(null, false));

    onConfigUpdate(true, atom.config.get("floobits"));
    floop.onROOM_INFO(this.on_room_info, this);
    floop.onDISCONNECT(this.on_disconnect, this);
    floop.onREQUEST_PERMS(this.on_request_perms, this);
  },
  on_request_perms: function (data) {
    const user = this.users.getByConnectionID(data.user_id);
    if (!user) {
      return;
    }
    const handleRequestPerm = require("./build/handle_request_perm");
    const view = handleRequestPerm({username: user.username, userId: data.user_id, perms: data.perms});
    atomUtils.addModalPanel("handle-request-perm", view);
  },
  on_room_info: function (workspace) {
    console.log("foobar on_room_info", workspace);
    if (this.statusBar) {
      return;
    }
    const statusBar = require("./build/status_bar");
    const userId = workspace.user_id;
    const user = workspace.users[userId];
    if (!user) {
      return;
    }
    const view = statusBar({owner: workspace.owner, workspace: workspace.room_name, username: user.username});
    const reactStatusBar = require("./react_wrapper").create_node("status_bar", view);
    this.statusBar = atom.workspace.addBottomPanel({item: reactStatusBar});
  },
  on_disconnect: function () {
    console.log("foobar on_disconnect...", arguments);
    if (this.statusBar) {
      this.statusBar.destroy();
    }
  },
  deactivate: function () {
    this.leave_workspace();
  },
  serialize: function () {
  },
  floourl: "",
  create_workspace: function (doesNotExist) {
    const root = atom.project.getRootDirectory();
    let dotFloo;
    if (root) {
      const cwd = root.getPath();
      dotFloo = utils.load_floo(cwd);
    }
    let url = !doesNotExist && dotFloo && dotFloo.url;
    const _create_workspace = function (err, res) {
      if (err) {
        if (res.statusCode !== 404) {
          console.error(err);
        }
        url = null;
      }
      const view = require("./build/create_workspace")({url: url, err: err});
      atomUtils.addModalPanel("create-workspace", view);
    };
    if (!url || doesNotExist) {
      return _create_workspace();
    }
    return api.get_workspace_by_url(url, _create_workspace);
  },
  join_recent_workspace: function () {
    const recentworkspaceview = require("./recentworkspaceview");
    const view = new recentworkspaceview.RecentWorkspaceView();
    atom.workspace.addTopPanel({item: view});
    view.focusFilterEditor();
  },
  join_workspace: function () {
    const that = this;
    let dotFloo, url;
    const root = atom.project.getRootDirectory();

    if (root) {
      dotFloo = utils.load_floo(root.path);
      url = dotFloo.url;
    }

    url = url || "https://floobits.com/";

    const view = require("./build/join")({url: url, on_url: function (_path, _url) {
      if (!_url) {
        message_action.error("I need a URL!");
        return;
      }
      if (!_path) {
        message_action.error("I need a directory!");
        return;
      }
      that.join_workspace_(_path, _url);
    }});
    atomUtils.addModalPanel("join-workspace", view);
  },
  join_workspace_: function (path, url) {
    if (!path || !url) {
      throw new Error("need a path and url");
    }
    const parsed_url = utils.parse_url(url);
    if (_.isEmpty(parsed_url)) {
      console.error("bad url", url);
      return;
    }

    const root = atom.project.getRootDirectory();
    if (!root || root.getPath() !== path) {
      atom.config.set("floobits.atoms-api-sucks-url", url);
      atom.config.set("floobits.atoms-api-sucks-path", path);
      message_action.log("Opening new window...", true);
      atom.open({pathsToOpen: [path], newWindow: true});
      return;
    }

    const that = this;
    const floourl = new FlooUrl(parsed_url.owner, parsed_url.workspace, parsed_url.host, parsed_url.port);
    api.get_workspace(parsed_url.host, parsed_url.owner, parsed_url.workspace, function (err, workspace) {
      if (err) {
        const res = workspace;
        if (res.statusCode === 404) {
          const ync = require("./build/yes_no_cancel");
          return ync("404!", "The workspace " + floourl.toString() + " does not exist.  Do you want to create it?", function (unused, choice) {
            if (choice !== "yes") {
              return;
            }
            that.create_workspace(true);
          });
        }
        message_action.error(err, true);
        return console.error(err);
      }
      if (_.isEmpty(workspace)) {
        message_action.error("empty workspace?!", true);
        return console.error("empty workspace?!");
      }
      this.leave_workspace();
      fl.base_path = path;
      atom.commands.add("atom-workspace", {
        "floobits: open workspace in browser": this.open_in_browser.bind(this),
        "floobits: summon": this.summon.bind(this),
        "floobits: follow": this.follow.bind(this),
        "floobits: user list panel": this.user_list.bind(this),
      });
      const PersistentJson = require("./persistentjson");
      const persistentJson = new PersistentJson();
      persistentJson.load();
      persistentJson.update(path, url);
      persistentJson.write();

      this.floourl = floourl;
      this.handler = new FlooHandler(floourl, this.me, this.users, this.bufs, this.terminals, this.filetree);
      this.handler.start();
      if (atom.config.get("floobits.userList")) {
        this.user_list();
      }
      const WebRTC = require("./common/webrtc");
      this.webrtc = new WebRTC(this.users, this.me);
    }.bind(this));
  },
  user_list: function () {
    if (this.userPanel) {
      this.userPanel.destroy();
      return;
    }
    const pane = require("./build/user_list_pane");
    const view = pane({users: this.users, me: this.me, prefs: prefs});
    const users = require("./react_wrapper").create_node("users", view,
      {width: "230px", height: "100%", overflow: "auto"}
    );
    this.userPanel = atom.workspace.addRightPanel({item: users});
    const that = this;
    this.userPanel.onDidDestroy(function () {
      that.userPanel = null;
    });
    users.onDestroy(this.userPanel);
  },
  open_in_browser: function () {
    if (this.handler && this.handler.floourl) {
      open_url(this.handler.floourl.toString());
    }
  },
  leave_workspace: function () {
    message_action.log("Leaving workspace", true);
    console.log("leaving");
    if (!this.handler){
      return;
    }
    this.handler.stop();
    this.handler = null;
    if (this.userPanel) {
      this.userPanel.destroy();
    }

    this.userPanel = null;
  },
  follow: function () {
    if (!this.handler) {
      return;
    }
    const View = require("./follow_view");
    const view = new View(this.me, this.users);
    atom.workspace.addTopPanel({item: view});
    view.focusFilterEditor();
  },
  summon: function () {
    if (!this.handler) {
      return;
    }

    const editor = atom.workspace.getActiveEditor();

    if (!editor) {
      console.log("no active editor, I don't know what to do.");
      return;
    }

    const fluffer = this.bufs.findFluffer(editor);
    if (!fluffer || !fluffer.populated) {
      console.error("This file is not shared");
      return;
    }

    const ranges = atomUtils.rangeFromEditor(editor);

    floop.send_highlight({
      "id": fluffer.id,
      "ping": true,
      "summon": true,
      "following": false,
      "ranges": ranges,
    });
  }
};
<commit_msg>status bar lifecycle:<commit_after>/*global self: true, fl */
"use strict";
"use babel";

self.fl = {};

const _ = require("lodash");
const api = require("./common/api");
const atomUtils = require("./atom_utils");
const message_action = require("./common/message_action");
const utils = require("./utils");
const usersModel = require("./common/user_model");
const prefs = require("./common/userPref_model");
const FlooUrl = require("./floourl").FlooUrl;
const open_url = require("open");
const buffer = require("./common/buffer_model");
const Terminals = require("./common/terminal_model").Terminals;
const Filetree = require("./common/filetree_model");

const floop = require("./common/floop");
const floorc = require("./common/floorc");
const FlooHandler = require("./common/handlers/floohandler").FlooHandler;

module.exports = {
  floobits: null,
  config: {
    audioOnly: {
      default: false,
      type: "boolean",
      description: "Disables video while video chatting."
    },
    showNotifications: {
      default: true,
      type: "boolean",
      description: "Enables Chrome desktop notifications."
    },
    mugshots: {
      default: false,
      type: "boolean",
      description: "Takes a snapshot every 60 seconds."
    },
    sound: {
      default: true,
      type: "boolean",
      description: "Plays sounds on join/part for other users for chatting."
    },
    userList: {
      title: "User List Panel",
      default: true,
      type: "boolean",
      description: "Opens the User list panel when you join a workspace."
    },
    source_audio_id: {
      title: "Audio Device ID",
      type: "string",
      default: "-1",
      description: "The device ID of the audio input for WebRTC.  Do not change manually!"
    },
    source_audio_name: {
      title: "Audio Device Name",
      type: "string",
      default: "Default",
      description: "The device name of the audio input for WebRTC.  Do not change manually!"
    },
    source_video_id: {
      title: "Video Source ID",
      type: "string",
      default: "-1",
      description: "The device id of the video input for WebRTC.  Do not change manually!"
    },
    source_video_name: {
      title: "Video Source Name",
      type: "string",
      default: "-1",
      description: "The device name of the video input for WebRTC.  Do not change manually!"
    },
  },
  welcome: function () {
    const Webview = require("./build/webview");
    const view = new Webview();
    const constants = require("./common/constants");
    view.load(constants.HOST);
  },
  mediaSource_: function (type) {
    MediaStreamTrack.getSources(function (sources) {
      const audio = sources.filter(function (s) {
        return s.kind === type;
      });
      const Sources = require("./media_sources");
      const view = new Sources(audio, function (source) {
        atom.config.set("floobits.source_" + type + "_id", source.id);
        atom.config.set("floobits.source_" + type + "_name", source.label);
      });
      atom.workspace.addTopPanel({item: view});
      view.focusFilterEditor();
    });
  },
  audioSources: function () {
    this.mediaSource_("audio");
  },
  videoSources: function () {
    this.mediaSource_("video");
  },
  activate: function () {
    const that = this;

    // Turn off metrics for everyone who installs our package
    // We include a note in our README, so this is OK!
    // atom.packages.disablePackage("metrics");
    if (!_.size(floorc.auth)) {
      setTimeout(this.welcome.bind(this), 0);
    }
    atom.commands.add("atom-workspace", {
      "floobits: create workspace": this.create_workspace.bind(this),
      "floobits: join workspace": this.join_workspace.bind(this),
      "floobits: leave workspace": this.leave_workspace.bind(this),
      "floobits: join recent workspace": this.join_recent_workspace.bind(this),
      "floobits: audio source": this.audioSources.bind(this),
      "floobits: video source": this.videoSources.bind(this),
    });

    this.users = new usersModel.Users();
    this.me = new usersModel.User();
    this.bufs = new buffer.Buffers();
    this.terminals = new Terminals([], {users: this.users});
    this.filetree = new Filetree();

    function onConfigUpdate (canJoin, config) {
      try {
        // Deprecation: Use ::getDirectories instead
        const dir = atom.project.getRootDirectory();
        const pathToFloobits = config["atoms-api-sucks-path"];
        const diff = {};

        _.each(config, function (value, key) {
          if (_.has(prefs.schema, key) && prefs[key] !== value) {
            diff[key] = value;
          }
        });

        if (!_.isEmpty(diff)) {
          prefs.set(diff);
          console.log("updated user prefs", diff);
        }

        if (!canJoin) {
          return;
        }

        prefs.requestNotificationPermission();

        if (!dir || !pathToFloobits || dir.path !== pathToFloobits) {
          return;
        }

        if (!config["atoms-api-sucks-url"]) {
          console.error("'floobits.atoms-api-sucks-url' isn't set?!? ");
          return;
        }
        atom.config.set("floobits.atoms-api-sucks-path", null);
        console.log("found pathToFloobits, will floobits");

        that.join_workspace_(dir.path, config["atoms-api-sucks-url"]);
      } catch (e) {
        console.error(e);
      }
    }

    atom.config.observe("floobits", onConfigUpdate.bind(null, false));
    onConfigUpdate(true, atom.config.get("floobits"));
  },
  on_request_perms: function (data) {
    const user = this.users.getByConnectionID(data.user_id);
    if (!user) {
      return;
    }
    const handleRequestPerm = require("./build/handle_request_perm");
    const view = handleRequestPerm({username: user.username, userId: data.user_id, perms: data.perms});
    atomUtils.addModalPanel("handle-request-perm", view);
  },
  on_room_info: function (workspace) {
    console.log("foobar on_room_info", workspace);
    if (this.statusBar) {
      return;
    }
    const statusBar = require("./build/status_bar");
    const userId = workspace.user_id;
    const user = workspace.users[userId];
    if (!user) {
      return;
    }
    const view = statusBar({owner: workspace.owner, workspace: workspace.room_name, username: user.username});
    const reactStatusBar = require("./react_wrapper").create_node("status_bar", view);
    this.statusBar = atom.workspace.addBottomPanel({item: reactStatusBar});
  },
  on_disconnect: function () {
    console.log("foobar on_disconnect...", arguments);
    if (this.statusBar) {
      this.statusBar.destroy();
    }
  },
  deactivate: function () {
    this.leave_workspace();
  },
  serialize: function () {
  },
  floourl: "",
  create_workspace: function (doesNotExist) {
    const root = atom.project.getRootDirectory();
    let dotFloo;
    if (root) {
      const cwd = root.getPath();
      dotFloo = utils.load_floo(cwd);
    }
    let url = !doesNotExist && dotFloo && dotFloo.url;
    const _create_workspace = function (err, res) {
      if (err) {
        if (res.statusCode !== 404) {
          console.error(err);
        }
        url = null;
      }
      const view = require("./build/create_workspace")({url: url, err: err});
      atomUtils.addModalPanel("create-workspace", view);
    };
    if (!url || doesNotExist) {
      return _create_workspace();
    }
    return api.get_workspace_by_url(url, _create_workspace);
  },
  join_recent_workspace: function () {
    const recentworkspaceview = require("./recentworkspaceview");
    const view = new recentworkspaceview.RecentWorkspaceView();
    atom.workspace.addTopPanel({item: view});
    view.focusFilterEditor();
  },
  join_workspace: function () {
    const that = this;
    let dotFloo, url;
    const root = atom.project.getRootDirectory();

    if (root) {
      dotFloo = utils.load_floo(root.path);
      url = dotFloo.url;
    }

    url = url || "https://floobits.com/";

    const view = require("./build/join")({url: url, on_url: function (_path, _url) {
      if (!_url) {
        message_action.error("I need a URL!");
        return;
      }
      if (!_path) {
        message_action.error("I need a directory!");
        return;
      }
      that.join_workspace_(_path, _url);
    }});
    atomUtils.addModalPanel("join-workspace", view);
  },
  join_workspace_: function (path, url) {
    if (!path || !url) {
      throw new Error("need a path and url");
    }
    const parsed_url = utils.parse_url(url);
    if (_.isEmpty(parsed_url)) {
      console.error("bad url", url);
      return;
    }

    const root = atom.project.getRootDirectory();
    if (!root || root.getPath() !== path) {
      atom.config.set("floobits.atoms-api-sucks-url", url);
      atom.config.set("floobits.atoms-api-sucks-path", path);
      message_action.log("Opening new window...", true);
      atom.open({pathsToOpen: [path], newWindow: true});
      return;
    }

    const that = this;
    const floourl = new FlooUrl(parsed_url.owner, parsed_url.workspace, parsed_url.host, parsed_url.port);
    api.get_workspace(parsed_url.host, parsed_url.owner, parsed_url.workspace, function (err, workspace) {
      if (err) {
        const res = workspace;
        if (res.statusCode === 404) {
          const ync = require("./build/yes_no_cancel");
          return ync("404!", "The workspace " + floourl.toString() + " does not exist.  Do you want to create it?", function (unused, choice) {
            if (choice !== "yes") {
              return;
            }
            that.create_workspace(true);
          });
        }
        message_action.error(err, true);
        return console.error(err);
      }
      if (_.isEmpty(workspace)) {
        message_action.error("empty workspace?!", true);
        return console.error("empty workspace?!");
      }
      this.leave_workspace();
      fl.base_path = path;
      atom.commands.add("atom-workspace", {
        "floobits: open workspace in browser": this.open_in_browser.bind(this),
        "floobits: summon": this.summon.bind(this),
        "floobits: follow": this.follow.bind(this),
        "floobits: user list panel": this.user_list.bind(this),
      });
      const PersistentJson = require("./persistentjson");
      const persistentJson = new PersistentJson();
      persistentJson.load();
      persistentJson.update(path, url);
      persistentJson.write();

      floop.onROOM_INFO(this.on_room_info, this);
      floop.onDISCONNECT(this.on_disconnect, this);
      floop.onREQUEST_PERMS(this.on_request_perms, this);

      this.floourl = floourl;
      this.handler = new FlooHandler(floourl, this.me, this.users, this.bufs, this.terminals, this.filetree);
      this.handler.start();
      if (atom.config.get("floobits.userList")) {
        this.user_list();
      }
      const WebRTC = require("./common/webrtc");
      this.webrtc = new WebRTC(this.users, this.me);
    }.bind(this));
  },
  user_list: function () {
    if (this.userPanel) {
      this.userPanel.destroy();
      return;
    }
    const pane = require("./build/user_list_pane");
    const view = pane({users: this.users, me: this.me, prefs: prefs});
    const users = require("./react_wrapper").create_node("users", view,
      {width: "230px", height: "100%", overflow: "auto"}
    );
    this.userPanel = atom.workspace.addRightPanel({item: users});
    const that = this;
    this.userPanel.onDidDestroy(function () {
      that.userPanel = null;
    });
    users.onDestroy(this.userPanel);
  },
  open_in_browser: function () {
    if (this.handler && this.handler.floourl) {
      open_url(this.handler.floourl.toString());
    }
  },
  leave_workspace: function () {
    message_action.log("Leaving workspace", true);
    console.log("leaving");
    if (!this.handler){
      return;
    }
    this.handler.stop();
    this.handler = null;
    if (this.userPanel) {
      this.userPanel.destroy();
      this.userPanel = null;
    }
    if (this.statusBar) {
      this.statusBar.destroy();
      this.statusBar = null;
    }
  },
  follow: function () {
    if (!this.handler) {
      return;
    }
    const View = require("./follow_view");
    const view = new View(this.me, this.users);
    atom.workspace.addTopPanel({item: view});
    view.focusFilterEditor();
  },
  summon: function () {
    if (!this.handler) {
      return;
    }

    const editor = atom.workspace.getActiveEditor();

    if (!editor) {
      console.log("no active editor, I don't know what to do.");
      return;
    }

    const fluffer = this.bufs.findFluffer(editor);
    if (!fluffer || !fluffer.populated) {
      console.error("This file is not shared");
      return;
    }

    const ranges = atomUtils.rangeFromEditor(editor);

    floop.send_highlight({
      "id": fluffer.id,
      "ping": true,
      "summon": true,
      "following": false,
      "ranges": ranges,
    });
  }
};
<|endoftext|>


<commit_before>(function(root) {
  var Bindings, F, LVar, conjunction, disjunction, find, _;

  root = this;
  _ = root._ || require('underscore');
  F = {};
  F.succeed = function(result) {
    return [result];
  };
  F.fail = _.always([]);
  disjunction = function(l, r) {
    return function(x) {
      return _.cat(l(x), r(x));
    };
  };
  conjunction = function(l, r) {
    return function(x) {
      return _.mapcat(l(x), r);
    };
  };
  F.disj = function() {
    if (_.isEmpty(arguments)) {
      return F.fail;
    }
    return disjunction(_.first(arguments), F.disj.apply(this, _.rest(arguments)));
  };
  F.conj = function() {
    var clauses;

    clauses = _.toArray(arguments);
    if (_.isEmpty(clauses)) {
      return F.succeed;
    }
    if (_.size(clauses) === 1) {
      return _.first(clauses);
    }
    return conjunction(_.first(clauses), function(s) {
      return F.conj.apply(null, _.rest(clauses))(s);
    });
  };
  LVar = (function() {
    function LVar(name) {
      this.name = name;
    }

    return LVar;

  })();
  F.lvar = function(name) {
    return new LVar(name);
  };
  F.isLVar = function(v) {
    return v instanceof LVar;
  };
  find = function(v, bindings) {
    var lvar;

    lvar = bindings.lookup(v);
    if (F.isLVar(v)) {
      return lvar;
    }
    if (_.isArray(lvar)) {
      if (_.isEmpty(lvar)) {
        return lvar;
      } else {
        return _.cons(find(_.first(lvar), bindings), find(_.rest(lvar), bindings));
      }
    }
    return lvar;
  };
  Bindings = (function() {
    function Bindings(seed) {
      if (seed == null) {
        seed = {};
      }
      this.binds = _.merge({}, seed);
    }

    Bindings.prototype.extend = function(lvar, value) {
      var o;

      o = {};
      o[lvar.name] = value;
      return new Bindings(_.merge(this.binds, o));
    };

    Bindings.prototype.has = function(lvar) {
      return this.binds.hasOwnProperty(lvar.name);
    };

    Bindings.prototype.lookup = function(lvar) {
      if (!F.isLVar(lvar)) {
        return lvar;
      }
      if (this.has(lvar)) {
        return this.lookup(this.binds[lvar.name]);
      }
      return lvar;
    };

    return Bindings;

  })();
  F.ignorance = new Bindings();
  F.unify = function(l, r, bindings) {
    var s, t1, t2;

    t1 = bindings.lookup(l);
    t2 = bindings.lookup(r);
    if (_.isEqual(t1, t2)) {
      return s;
    }
    if (F.isLVar(t1)) {
      return bindings.extend(t1, t2);
    }
    if (F.isLVar(t2)) {
      return bindings.extend(t2, t1);
    }
    if (_.isArray(t1) && _.isArray(t2)) {
      s = F.unify(_.first(t1), _.first(t2), bindings);
      s = s !== null ? F.unify(_.rest(t1), _.rest(t2), bindings) : s;
      return s;
    }
    return null;
  };
  F.goal = function(l, r) {
    return function(bindings) {
      var result;

      result = F.unify(l, r, bindings);
      if (result !== null) {
        return F.succeed(result);
      }
      return F.fail(bindings);
    };
  };
  F.run = function(goal) {
    return goal(F.ignorance);
  };
  F.choice = function($v, list) {
    if (_.isEmpty(list)) {
      return F.fail;
    }
    return F.disj(F.goal($v, _.first(list)), F.choice($v, _.rest(list)));
  };
  if (typeof module !== "undefined" && module !== null) {
    return module.exports = F;
  } else {
    return root.F = F;
  }
})(this);
<commit_msg>Regenerating JS<commit_after>// Generated by CoffeeScript 1.6.2
(function() {
  (function(root) {
    var Bindings, F, LVar, conjunction, disjunction, find, _;

    root = this;
    _ = root._ || require('underscore');
    F = {};
    F.succeed = function(result) {
      return [result];
    };
    F.fail = _.always([]);
    disjunction = function(l, r) {
      return function(x) {
        return _.cat(l(x), r(x));
      };
    };
    conjunction = function(l, r) {
      return function(x) {
        return _.mapcat(l(x), r);
      };
    };
    F.disj = function() {
      if (_.isEmpty(arguments)) {
        return F.fail;
      }
      return disjunction(_.first(arguments), F.disj.apply(this, _.rest(arguments)));
    };
    F.conj = function() {
      var clauses;

      clauses = _.toArray(arguments);
      if (_.isEmpty(clauses)) {
        return F.succeed;
      }
      if (_.size(clauses) === 1) {
        return _.first(clauses);
      }
      return conjunction(_.first(clauses), function(s) {
        return F.conj.apply(null, _.rest(clauses))(s);
      });
    };
    LVar = (function() {
      function LVar(name) {
        this.name = name;
      }

      return LVar;

    })();
    F.lvar = function(name) {
      return new LVar(name);
    };
    F.isLVar = function(v) {
      return v instanceof LVar;
    };
    find = function(v, bindings) {
      var lvar;

      lvar = bindings.lookup(v);
      if (F.isLVar(v)) {
        return lvar;
      }
      if (_.isArray(lvar)) {
        if (_.isEmpty(lvar)) {
          return lvar;
        } else {
          return _.cons(find(_.first(lvar), bindings), find(_.rest(lvar), bindings));
        }
      }
      return lvar;
    };
    Bindings = (function() {
      function Bindings(seed) {
        if (seed == null) {
          seed = {};
        }
        this.binds = _.merge({}, seed);
      }

      Bindings.prototype.extend = function(lvar, value) {
        var o;

        o = {};
        o[lvar.name] = value;
        return new Bindings(_.merge(this.binds, o));
      };

      Bindings.prototype.has = function(lvar) {
        return this.binds.hasOwnProperty(lvar.name);
      };

      Bindings.prototype.lookup = function(lvar) {
        if (!F.isLVar(lvar)) {
          return lvar;
        }
        if (this.has(lvar)) {
          return this.lookup(this.binds[lvar.name]);
        }
        return lvar;
      };

      return Bindings;

    })();
    F.ignorance = new Bindings();
    F.unify = function(l, r, bindings) {
      var s, t1, t2;

      t1 = bindings.lookup(l);
      t2 = bindings.lookup(r);
      if (_.isEqual(t1, t2)) {
        return s;
      }
      if (F.isLVar(t1)) {
        return bindings.extend(t1, t2);
      }
      if (F.isLVar(t2)) {
        return bindings.extend(t2, t1);
      }
      if (_.isArray(t1) && _.isArray(t2)) {
        s = F.unify(_.first(t1), _.first(t2), bindings);
        s = s !== null ? F.unify(_.rest(t1), _.rest(t2), bindings) : s;
        return s;
      }
      return null;
    };
    F.goal = function(l, r) {
      return function(bindings) {
        var result;

        result = F.unify(l, r, bindings);
        if (result !== null) {
          return F.succeed(result);
        }
        return F.fail(bindings);
      };
    };
    F.run = function(goal) {
      return goal(F.ignorance);
    };
    F.choice = function($v, list) {
      if (_.isEmpty(list)) {
        return F.fail;
      }
      return F.disj(F.goal($v, _.first(list)), F.choice($v, _.rest(list)));
    };
    if (typeof module !== "undefined" && module !== null) {
      return module.exports = F;
    } else {
      return root.F = F;
    }
  })(this);

}).call(this);
<|endoftext|>


<commit_before>/**
 *  FsTools
 *
 *  Collection of FS related tools, that stdlib lack of.
 **/

'use strict';

// stdlib
var fs = require('fs'),
    path_join = require('path').join,
    path_exists = require('path').exists,
    dirname = require('path').dirname;

// 3rd-party
var Promise = require('simple-promise'),
    _ = require('underscore');

// INTERNAL HELPERS
////////////////////////////////////////////////////////////////////////////////

//  walk_flat(path, iterator, callback) -> void
//  - path (String): Path to iterate through
//  - iterator (Function): Will be fired on each element within `path`
//  - callback (Function): Will be fired once all files were processed
//
//  Walks through given `path` and calls `iterator(path, stats, callback)` for
//  each foun entry (regardless to it's type) and waits for all `callback`s
//  (passed to iterator) to be fired. After all callbacks were fired, fires
//  `callback` (given to walk_flat itself).
//
//  NOTICE: It walks through single dimension of file system - it won't go into
//          found sub-directories. See `walk_recursive` for this puprpose.
//
//  Example:
//
//    walk_flat('/home/nodeca', function (path, stats, callback) {
//      if ('/home/nodeca/secrets.yml' === path) {
//        callback(Error("There is secrets file."));
//        return;
//      }
//
//      if ('/home/nodeca/xxx' === path && stats.isDirectory()) {
//        callback(Error("Path contains xxx directory."));
//        return;
//      }
//
//      callback();
//    }, function (err) {
//      if (err) console.error(err);
//      console.log('Done');
//    });
var walk_flat = function walk_flat(path, iterator, callback) {
  fs.readdir(path, function (err, files) {
    var all;

    if (err) {
      callback(err);
      return;
    }

    all = new Promise.Joint(callback);

    _(files).chain().map(function(file) {
      return path_join(path, file);
    }).each(function (path) {
      var promise = all.promise();

      fs.stat(path, function (err, stats) {
        if (err) {
          all.reject(err);
          return;
        }

        iterator(path, stats, function (err) {
          if (err) {
            all.reject(err);
            return;
          }

          promise.resolve();
        });
      });
    });

    all.wait();
  });
};

//  walk_recursive(path, iterator, callback) -> void
//
//  Proxies call to `walk_flat`, but wraps `iterator` so that it will
//  recursively go deeper inside each found directoy instead of calling
//  iterator on it.
var walk_recursive = function walk_recursive(path, iterator, callback) {
  // walk through given path
  walk_flat(path, function (path, stats, callback) {
    // go deeper inside
    if (stats.isDirectory()) {
      walk_recursive(path, iterator, callback);
      return;
    }

    // call iterator if not directory
    iterator(path, stats, callback);
  }, callback);
};

// PUBLIC API
////////////////////////////////////////////////////////////////////////////////

/**
 *  FsTools.walk(path, pattern, iterator[, callback]) -> void
 *  FsTools.walk(path, iterator[, callback]) -> void
 *
 *  Walks throught all files withing `path` (including sub-dirs) and calls
 *  `iterator` on each found file (or block device etc.) matching `pattern`.
 *  If no `pattern` was given - will fire call `iterator` for every single
 *  path found. After all iterations will call `callback` (if it was specified)
 *  with passing `error` as first arguemtn if there was an error.
 *
 *  ##### Iterator
 *
 *  All iterations are running within promise. So `callback` given to the `walk`
 *  will fire only after all `iterator` callbacks willnotify they finished their
 *  work:
 *
 *      var iterator = function (path, stats, callback) {
 *        // ... do something
 *        if (err) {
 *          // ... if error occured we can "stop" walker
 *          callback(err);
 *          return;
 *        }
 *        // ... if everything is good and finished notify walker we're done
 *        callback();
 *      };
 *
 *  Iterator is called with following arguments:
 *
 *  - `path` (String): Full path of the found element (e.g. `/foo/bar.txt`)
 *  - `stats` (fs.Stats): Stats object of found path
 *  - `callback` (Function): Callback function to call after path processing
 *
 *
 *  ##### Example
 *
 *      fstools.walk('/home/nodeca', function (path, stats, callback) {
 *        if (stats.isBlockDevice()) {
 *          callback(Error("WTF? Block devices are not expetcted in my room"));
 *          return;
 *        }
 *
 *        if (stats.isSocket()) {
 *          console.log("Finally I found my socket");
 *        }
 *
 *        callback();
 *      }, function (err) {
 *        if (err) {
 *          // shit happens!
 *          console.error(err);
 *          process.exit(1);
 *        }
 *
 *        console.log("Hooray! We're done!");
 *      });
 *
 *
 *  ##### Example (using pattern matching)
 *
 *      fstools.walk('/home/nodeca', '\.yml$', function (path, stats, callback) {
 *        fs.readFile(path, 'utf-8', funtion (err, str) {
 *          if (err) {
 *            callback(err);
 *            return;
 *          }
 *
 *          console.log(str);
 *          callback();
 *        });
 *      }, function (err) {
 *        if (err) {
 *          console.error(err);
 *        }
 *
 *        console.log('Done!');
 *      });
 **/
var walk = exports.walk = function walk(path, pattern, iterator, callback) {
  var match; // function that tells whenever iterator need to be called or not

  if (_.isFunction(pattern)) {
    // Scenario: FileWalker(path, iterator[, callback])
    callback = iterator;
    iterator = pattern;
    match = function () { return true; };
  } else {
    // Scenario: FileWalker(path, pattern, iterator[, callback])
    pattern = new RegExp(pattern);
    match = function (path) { return path.test(pattern); };
  }

  if (!_.isFunction(callback)) {
    // Scenario: FileWalker(path, pattern, iterator)
    //       or: FileWalker(path, iterator)
    callback = function () {};
  }

  // start walking
  walk_recursive(path, function(path, stats, callback) {
    // call iterator on
    if (match(path)) {
      iterator(path, stats, callback);
      return;
    }

    callback();
  }, callback);
};

/**
 *  FsTools.rm_rf(path, callback) -> void
 *  - path (String): Path to remove
 *  - callback (Function): Fired after path was removed
 *
 *  Removes given `path`. If it was a directory will remove it recursively,
 *  similar to UNIX' `rm -rf <path>`. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *  If given `path` was file - will proxy call to `fs.unlink`.
 *
 *
 *  ##### Example
 *
 *      fstools.rm_rf('/home/nodeca/trash', function (err) {
 *        if (err) {
 *          console.log("U can't touch that");
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("It's Hammer time");
 *          process.exit(0);
 *        }
 *      });
 **/
var rm_rf = exports.rm_rf = function rm_rf(path, callback) {
  fs.stat(path, function (err, stats) {
    if (err) {
      // file/dir not exists - no need to do anything
      if ('ENOENT' === err.code) {
        callback(null);
        return;
      }

      // unknown error - can't continue
      callback(err);
      return;
    }

    if (!stats.isDirectory()) {
      fs.unlink(path, callback);
      return;
    }

    walk_flat(path, function (path, stats, callback) {
      if (stats.isDirectory()) {
        rm_rf(path, function (err) {
          if (err) {
            callback(err);
            return;
          }

          fs.rmdir(path, callback);
        });
        return;
      }

      fs.unlink(path, callback);
    }, callback);
  });
};

/**
 *  FsTools.mkdir_p(path, callback) -> void
 *  - path (String): Path to create
 *  - callback (Function): Fired after path was created
 *
 *  Creates given path, creating parents recursively if needed.
 *  Similar to UNIX' `mkdir -p <path>`. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *
 *  ##### Example
 *
 *      fstools.mkdir_p('/home/nodeca/media/xxx', function (err) {
 *        if (err) {
 *          console.log("Can't' create directory");
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("We can now store some romantic movies here");
 *          process.exit(0);
 *        }
 *      });
 **/
var mkdir_p = exports.mkdir_p = function mkdir_p(path, callback) {
  path_exists(path, function (exists) {
    var parent;

    if (exists) {
      callback(null);
      return;
    }

    parent = dirname(path);

    mkdir_p(parent, function (err) {
      if (err) {
        callback(err);
        return;
      }

      fs.mkdir(path, '0755', function (err) {
        // EEXIST is not error in our case
        // but a race condition :((
        if (err && 'EEXIST' === err.code) {
          callback(null);
          return;
        }

        // fallback to default behavior
        callback(err);
      });
    });
  });
};

/**
 *  FsTools.copy(src, dst, callback) -> void
 *  - src (String): Source file
 *  - dst (String): Detination file
 *  - callback (Function): Fired after path was copied
 *
 *  Copies `src` to `dst`, creates directory for given `dst` with
 *  [[FsTools.mkdir_p]] if needed. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *
 *  ##### Example
 *
 *      var src = '/home/nodeca/secrets.yml',
 *          dst = '/home/nodeca/very/deep/secrets/main.yml';
 *
 *      fstools.copy(src, dst, function (err) {
 *        if (err) {
 *          console.log("Failed copy " + src + " into " + dst);
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("Fone!");
 *          process.exit(0);
 *        }
 *      });
 **/
var copy = exports.copy = function copy(src, dst, callback) {
  fs.readFile(src, function (err, buff) {
    if (err) {
      callback(err);
      return;
    }

    mkdir_p(dirname(dst), function (err) {
      if (err) {
        callback(err);
        return;
      }

      fs.writeFile(dst, buff, callback);
    });
  });
};

////////////////////////////////////////////////////////////////////////////////
// vim:ts=2:sw=2
////////////////////////////////////////////////////////////////////////////////
<commit_msg>Forgotten patch<commit_after>/**
 *  FsTools
 *
 *  Collection of FS related tools, that stdlib lack of.
 **/

'use strict';

// stdlib
var fs = require('fs'),
    path_join = require('path').join,
    path_exists = require('path').exists,
    dirname = require('path').dirname;

// 3rd-party
var Promise = require('simple-promise'),
    _ = require('underscore');

// INTERNAL HELPERS
////////////////////////////////////////////////////////////////////////////////

//  walk_flat(path, iterator, callback) -> void
//  - path (String): Path to iterate through
//  - iterator (Function): Will be fired on each element within `path`
//  - callback (Function): Will be fired once all files were processed
//
//  Walks through given `path` and calls `iterator(path, stats, callback)` for
//  each foun entry (regardless to it's type) and waits for all `callback`s
//  (passed to iterator) to be fired. After all callbacks were fired, fires
//  `callback` (given to walk_flat itself).
//
//  NOTICE: It walks through single dimension of file system - it won't go into
//          found sub-directories. See `walk_recursive` for this puprpose.
//
//  Example:
//
//    walk_flat('/home/nodeca', function (path, stats, callback) {
//      if ('/home/nodeca/secrets.yml' === path) {
//        callback(Error("There is secrets file."));
//        return;
//      }
//
//      if ('/home/nodeca/xxx' === path && stats.isDirectory()) {
//        callback(Error("Path contains xxx directory."));
//        return;
//      }
//
//      callback();
//    }, function (err) {
//      if (err) console.error(err);
//      console.log('Done');
//    });
var walk_flat = function walk_flat(path, iterator, callback) {
  fs.readdir(path, function (err, files) {
    var all;

    if (err) {
      callback(err);
      return;
    }

    all = new Promise.Joint(callback);

    _(files).chain().map(function(file) {
      return path_join(path, file);
    }).each(function (path) {
      var promise = all.promise();

      fs.stat(path, function (err, stats) {
        if (err) {
          all.reject(err);
          return;
        }

        iterator(path, stats, function (err) {
          if (err) {
            all.reject(err);
            return;
          }

          promise.resolve();
        });
      });
    });

    all.wait();
  });
};

//  walk_recursive(path, iterator, callback) -> void
//
//  Proxies call to `walk_flat`, but wraps `iterator` so that it will
//  recursively go deeper inside each found directoy instead of calling
//  iterator on it.
var walk_recursive = function walk_recursive(path, iterator, callback) {
  // walk through given path
  walk_flat(path, function (path, stats, callback) {
    // go deeper inside
    if (stats.isDirectory()) {
      walk_recursive(path, iterator, callback);
      return;
    }

    // call iterator if not directory
    iterator(path, stats, callback);
  }, callback);
};

// PUBLIC API
////////////////////////////////////////////////////////////////////////////////

/**
 *  FsTools.walk(path, pattern, iterator[, callback]) -> void
 *  FsTools.walk(path, iterator[, callback]) -> void
 *
 *  Walks throught all files withing `path` (including sub-dirs) and calls
 *  `iterator` on each found file (or block device etc.) matching `pattern`.
 *  If no `pattern` was given - will fire call `iterator` for every single
 *  path found. After all iterations will call `callback` (if it was specified)
 *  with passing `error` as first arguemtn if there was an error.
 *
 *  ##### Iterator
 *
 *  All iterations are running within promise. So `callback` given to the `walk`
 *  will fire only after all `iterator` callbacks willnotify they finished their
 *  work:
 *
 *      var iterator = function (path, stats, callback) {
 *        // ... do something
 *        if (err) {
 *          // ... if error occured we can "stop" walker
 *          callback(err);
 *          return;
 *        }
 *        // ... if everything is good and finished notify walker we're done
 *        callback();
 *      };
 *
 *  Iterator is called with following arguments:
 *
 *  - `path` (String): Full path of the found element (e.g. `/foo/bar.txt`)
 *  - `stats` (fs.Stats): Stats object of found path
 *  - `callback` (Function): Callback function to call after path processing
 *
 *
 *  ##### Example
 *
 *      fstools.walk('/home/nodeca', function (path, stats, callback) {
 *        if (stats.isBlockDevice()) {
 *          callback(Error("WTF? Block devices are not expetcted in my room"));
 *          return;
 *        }
 *
 *        if (stats.isSocket()) {
 *          console.log("Finally I found my socket");
 *        }
 *
 *        callback();
 *      }, function (err) {
 *        if (err) {
 *          // shit happens!
 *          console.error(err);
 *          process.exit(1);
 *        }
 *
 *        console.log("Hooray! We're done!");
 *      });
 *
 *
 *  ##### Example (using pattern matching)
 *
 *      fstools.walk('/home/nodeca', '\.yml$', function (path, stats, callback) {
 *        fs.readFile(path, 'utf-8', funtion (err, str) {
 *          if (err) {
 *            callback(err);
 *            return;
 *          }
 *
 *          console.log(str);
 *          callback();
 *        });
 *      }, function (err) {
 *        if (err) {
 *          console.error(err);
 *        }
 *
 *        console.log('Done!');
 *      });
 **/
var walk = exports.walk = function walk(path, pattern, iterator, callback) {
  var match; // function that tells whenever iterator need to be called or not

  if (_.isFunction(pattern)) {
    // Scenario: FileWalker(path, iterator[, callback])
    callback = iterator;
    iterator = pattern;
    match = function () { return true; };
  } else {
    // Scenario: FileWalker(path, pattern, iterator[, callback])
    pattern = new RegExp(pattern);
    match = function (path) { return pattern.test(path); };
  }

  if (!_.isFunction(callback)) {
    // Scenario: FileWalker(path, pattern, iterator)
    //       or: FileWalker(path, iterator)
    callback = function () {};
  }

  // start walking
  walk_recursive(path, function(path, stats, callback) {
    // call iterator on
    if (match(path)) {
      iterator(path, stats, callback);
      return;
    }

    callback();
  }, callback);
};

/**
 *  FsTools.rm_rf(path, callback) -> void
 *  - path (String): Path to remove
 *  - callback (Function): Fired after path was removed
 *
 *  Removes given `path`. If it was a directory will remove it recursively,
 *  similar to UNIX' `rm -rf <path>`. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *  If given `path` was file - will proxy call to `fs.unlink`.
 *
 *
 *  ##### Example
 *
 *      fstools.rm_rf('/home/nodeca/trash', function (err) {
 *        if (err) {
 *          console.log("U can't touch that");
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("It's Hammer time");
 *          process.exit(0);
 *        }
 *      });
 **/
var rm_rf = exports.rm_rf = function rm_rf(path, callback) {
  fs.stat(path, function (err, stats) {
    if (err) {
      // file/dir not exists - no need to do anything
      if ('ENOENT' === err.code) {
        callback(null);
        return;
      }

      // unknown error - can't continue
      callback(err);
      return;
    }

    if (!stats.isDirectory()) {
      fs.unlink(path, callback);
      return;
    }

    walk_flat(path, function (path, stats, callback) {
      if (stats.isDirectory()) {
        rm_rf(path, function (err) {
          if (err) {
            callback(err);
            return;
          }

          fs.rmdir(path, callback);
        });
        return;
      }

      fs.unlink(path, callback);
    }, callback);
  });
};

/**
 *  FsTools.mkdir_p(path, callback) -> void
 *  - path (String): Path to create
 *  - callback (Function): Fired after path was created
 *
 *  Creates given path, creating parents recursively if needed.
 *  Similar to UNIX' `mkdir -p <path>`. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *
 *  ##### Example
 *
 *      fstools.mkdir_p('/home/nodeca/media/xxx', function (err) {
 *        if (err) {
 *          console.log("Can't' create directory");
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("We can now store some romantic movies here");
 *          process.exit(0);
 *        }
 *      });
 **/
var mkdir_p = exports.mkdir_p = function mkdir_p(path, callback) {
  path_exists(path, function (exists) {
    var parent;

    if (exists) {
      callback(null);
      return;
    }

    parent = dirname(path);

    mkdir_p(parent, function (err) {
      if (err) {
        callback(err);
        return;
      }

      fs.mkdir(path, '0755', function (err) {
        // EEXIST is not error in our case
        // but a race condition :((
        if (err && 'EEXIST' === err.code) {
          callback(null);
          return;
        }

        // fallback to default behavior
        callback(err);
      });
    });
  });
};

/**
 *  FsTools.copy(src, dst, callback) -> void
 *  - src (String): Source file
 *  - dst (String): Detination file
 *  - callback (Function): Fired after path was copied
 *
 *  Copies `src` to `dst`, creates directory for given `dst` with
 *  [[FsTools.mkdir_p]] if needed. After all will fire `callback(err)` with
 *  an error if there were any.
 *
 *
 *  ##### Example
 *
 *      var src = '/home/nodeca/secrets.yml',
 *          dst = '/home/nodeca/very/deep/secrets/main.yml';
 *
 *      fstools.copy(src, dst, function (err) {
 *        if (err) {
 *          console.log("Failed copy " + src + " into " + dst);
 *          console.err(err);
 *          process.exit(1);
 *        } else {
 *          console.log("Fone!");
 *          process.exit(0);
 *        }
 *      });
 **/
var copy = exports.copy = function copy(src, dst, callback) {
  fs.readFile(src, function (err, buff) {
    if (err) {
      callback(err);
      return;
    }

    mkdir_p(dirname(dst), function (err) {
      if (err) {
        callback(err);
        return;
      }

      fs.writeFile(dst, buff, callback);
    });
  });
};

////////////////////////////////////////////////////////////////////////////////
// vim:ts=2:sw=2
////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var rightPressed = false;
var leftPressed = false;
var paddleHeight = 20;
var paddleWidth = 100;
var paddleX = (canvas.width-paddleWidth)/2;
var paddleY = canvas.height-paddleHeight;

var ballRadius = 15;
var ballX = canvas.width/2;
var ballY = paddleY - ballRadius;

var gameOn = false;
var rightPressed = false;
var leftPressed = false;

var brickArray = [];
var brickWidth = 70;
var brickHeight = 25;
var brickPad = 10;
var brickMarginTop = 30;
var brickMarginLeft = 30;
var brickRows = 4;
var brickColumns = 8;

for(c=0; c<brickColumns; c++) {
  brickArray[c] = [];
  for(r=0; r<brickRows; r++) {
    brickArray[c][r] = {x: 0, y: 0};
  }
}

function populateBrickArray() {
    for(c=0; c<brickColumns; c++) {
        for(r=0; r<brickRows; r++) {
            var brickX = (c*(brickWidth+brickPad))+brickMarginLeft;
            var brickY = (r*(brickHeight+brickPad))+brickMarginTop;
            brickArray[c][r].x = brickX;
            brickArray[c][r].y = brickY;
            context.beginPath();
            context.rect(brickX, brickY, brickWidth, brickHeight);
            context.fillStyle = "#000000";
            context.fill();
            context.closePath();
        }
    }
}

document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keyup", keyUpHandler);

function keyDownHandler(e) {
  if(e.keyCode == 39) {
    rightPressed = true;
  }
  else if(e.keyCode == 37) {
    leftPressed = true;
  }
  else if(e.keyCode ==13) {
    gameOn = true;
  }
}

function keyUpHandler(e) {
  if(e.keyCode == 39) {
      rightPressed = false;
  }
  else if(e.keyCode == 37) {
      leftPressed = false;
  }
}

function paddleMove() {
  if (rightPressed === true && paddleX < canvas.width - paddleWidth) {
    paddleX += 5;
  } else if (leftPressed === true && paddleX > 0) {
    paddleX -= 5;
  }
}

function ballMove() {
  if (gameOn === true) {
    ballY -= 5;
  }
}

function draw() {
  context.fillStyle = 'blue';
  context.fillRect(paddleX, paddleY, paddleWidth, paddleHeight);

  context.fillStyle = 'magenta';
  context.beginPath();
  context.arc(ballX,ballY,ballRadius,0,2*Math.PI);
  context.fill();
}

requestAnimationFrame(function gameLoop() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  populateBrickArray();
  draw();
  paddleMove();
  ballMove();
  requestAnimationFrame(gameLoop);
});
<commit_msg>Fix conflicts locally<commit_after>

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var rightPressed = false;
var leftPressed = false;
var paddleHeight = 20;
var paddleWidth = 100;
var paddleX = (canvas.width-paddleWidth)/2;
var paddleY = canvas.height-paddleHeight;

var ballRadius = 15;
var ballX = canvas.width/2;
var ballY = paddleY - ballRadius;
var dirX = 2;
var dirY = -2;

var gameOn = false;
var rightPressed = false;
var leftPressed = false;

var brickArray = [];
var brickWidth = 70;
var brickHeight = 25;
var brickPad = 10;
var brickMarginTop = 30;
var brickMarginLeft = 30;
var brickRows = 4;
var brickColumns = 8;

for(c=0; c<brickColumns; c++) {
  brickArray[c] = [];
  for(r=0; r<brickRows; r++) {
    brickArray[c][r] = {x: 0, y: 0};
  }
}

function populateBrickArray() {
    for(c=0; c<brickColumns; c++) {
        for(r=0; r<brickRows; r++) {
            var brickX = (c*(brickWidth+brickPad))+brickMarginLeft;
            var brickY = (r*(brickHeight+brickPad))+brickMarginTop;
            brickArray[c][r].x = brickX;
            brickArray[c][r].y = brickY;
            context.beginPath();
            context.rect(brickX, brickY, brickWidth, brickHeight);
            context.fillStyle = "#000000";
            context.fill();
            context.closePath();
        }
    }
}

document.addEventListener("keydown", keyDownHandler);
document.addEventListener("keyup", keyUpHandler);

function keyDownHandler(e) {
  if(e.keyCode == 39) {
    rightPressed = true;
  }
  else if(e.keyCode == 37) {
    leftPressed = true;
  }
  else if(e.keyCode ==13) {
    gameOn = true;
  }
}

function keyUpHandler(e) {
  if(e.keyCode == 39) {
      rightPressed = false;
  }
  else if(e.keyCode == 37) {
      leftPressed = false;
  }
}

function paddleMove() {
  if (rightPressed === true && paddleX < canvas.width - paddleWidth) {
    paddleX += 5;
  } else if (leftPressed === true && paddleX > 0) {
    paddleX -= 5;
  }
}

function drawBall () {
  context.fillStyle = 'magenta';
  context.beginPath();
  context.arc(ballX,ballY,ballRadius,0,2*Math.PI);
  context.fill();
}

function ballMove() {
  if (gameOn === true) {
    ballX += dirX;
    ballY += dirY;
  }
  if(ballX + dirX + ballRadius > canvas.width || ballX + dirX - ballRadius < 0) {
    dirX = -dirX;
  }
  if(ballY + dirY + ballRadius > canvas.height || ballY + dirY - ballRadius < 0) {
    dirY = -dirY;
  }
}

function draw() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.fillStyle = 'blue';
  context.fillRect(paddleX, paddleY, paddleWidth, paddleHeight);
  drawBall();
}

requestAnimationFrame(function gameLoop() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  populateBrickArray();
  draw();
  paddleMove();
  ballMove();
  requestAnimationFrame(gameLoop);
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'LanguageChoiceView',
  extends: 'foam.u2.View',

  implements: [
    'foam.mlang.Expressions'
  ],

  requires: [
    'foam.u2.PopupView',
    'foam.nanos.auth.Language',
  ],

  imports: [
    'stack',
    'languageDAO',
    'subject',
    'userDAO',
    'countryDAO',
    'translationService'
  ],

  exports: [ 'as data' ],

  css: `
  ^carrot {
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid white;
    display: inline-block;
    float: right;
    margin-top: 7px;
    margin-left: 7px;
  }
  ^ .foam-u2-ActionView-languageChoice {
    display: inline-block;
    background: none !important;
    border: 0 !important;
    box-shadow: none !important;
    width: max-content;
    cursor: pointer;
    margin-right: 27px;
  }
  ^ .foam-nanos-u2-navigation-TopNavigation-LanguageChoiceView {
    align-items: center;
  }
  ^ .foam-u2-ActionView-languageChoice > span {
    font-family: /*%FONT1%*/ Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-size: 16px;
    font-weight: 300;
    letter-spacing: 0.2px;
    color: #ffffff;
  }
  ^ .popUpDropDown > div {
    margin-left: -8px;
    border-radius: 4px;
    width: 100%;
    text-align: center;
    height: 25;
    padding: 0px 8px 5px 8px;
    font-size: 14px;
    font-weight: 300;
    letter-spacing: 0.2px;
    color: /*%BLACK%*/ #1e1f21;
    line-height: 30px;
  }
  ^ .foam-u2-PopupView {
    border-radius: 4px;
    left: -30 !important;
    top: 51px !important;
    padding: 0px 8px 0px 8px !important;
    z-index: 1000;
    width: fit-content !important;
    background: white;
    opacity: 1;
    box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.19);
  }
  ^ .popUpDropDown > div:hover{
    background-color: #1cc2b7;
    color: white;
    cursor: pointer;
  }
  ^ .popUpDropDown::before {
    content: ' ';
    position: absolute;
    height: 0;
    width: 0;
    border: 8px solid transparent;
    border-bottom-color: white;
    -ms-transform: translate(110px, -16px);
    transform: translate(50px, -16px);
  }
  ^ .flag {
    width: 30px !important;
    height: 17.6px;
    object-fit: contain;
    padding-top: 6px;
    padding-left: 10px;
    margin-right: 23px;
  }
  ^ img {
    height: 17.6px !important;
    margin-right: 6;
    width: auto;
  }
  `,

  properties: [
    'optionsBtn_',
    'supportedLanguages',
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.auth.Language',
      name: 'defaultLanguage',
      factory: function() {
        return foam.nanos.auth.Language.create({code: 'en'})
      }
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.auth.Language',
      name: 'lastLanguage',
      factory: function() {
        let language = this.supportedLanguages.find( e => e.toString() === foam.locale )
        language = language === undefined ? this.defaultLanguage : language
        localStorage.setItem('localeLanguage', language.toString());
        return language
      }
    }
  ],

  methods: [
    async function initE() {
      var self = this
      let languages = (await this.languageDAO
                        .where(foam.mlang.predicate.Eq.create({
                          arg1: foam.nanos.auth.Language.ENABLED,
                          arg2: true
                        })).select()).array;

      this.supportedLanguages = languages
      if ( this.subject && this.subject.realUser ) {
        let userPreferLanguage = this.supportedLanguages.find( e => e.id.compareTo(self.subject.realUser.language) === 0 )
        if ( ! userPreferLanguage ) {
            foam.locale = this.defaultLanguage.toString()
            let user = self.subject.realUser
            user.language = this.defaultLanguage.id
            localStorage.setItem('localeLanguage', this.defaultLanguage.toString());
            await self.userDAO.put(user)
        } else {
          if ( foam.locale != userPreferLanguage.toString() ) {
            foam.locale = userPreferLanguage.toString()
            localStorage.setItem('localeLanguage', userPreferLanguage.toString());
            location.reload();
          }
        }
      }

      let country = await this.countryDAO.find(this.lastLanguage.variant)
      let label = this.lastLanguage.variant != "" ? `${this.lastLanguage.name}(${this.lastLanguage.variant})` : `${this.lastLanguage.name}`
      if ( country && country.name != null ) {
        label = `${this.lastLanguage.name}(${this.getCountryName(country.name, country.name)})`
      }

      this
        .addClass(this.myClass())
        .tag('span', null, this.optionsBtn_$)
        .start(this.LANGUAGE_CHOICE, {
          label: label
        })
        .start('div')
          .addClass(this.myClass('carrot'))
        .end()
      .end();
    },
    async function formatLabel(language) {
      let country = await this.countryDAO.find(language.variant)
      let label = language.variant != "" ? `${language.name}(${language.variant})` : `${language.name}`
      if ( country && country.name != null ) {
        label = `${language.name}(${this.getCountryName(country.name, country.name)})`
      }
      return label
    },
    function getCountryName(countryName, defaultName) {
      defaultName = defaultName ? defaultName : ''
      let translation = this.translationService.getTranslation(foam.locale, `${foam.locale.toLowerCase()}.country.${countryName}`)
      translation = translation ? translation : defaultName
      return translation
    }
  ],

  actions: [
    {
      name: 'languageChoice',
      label: '',
      code: function() {
        var self = this;
        self.optionPopup_ = this.PopupView.create({
          width: 1165,
          x: -1137,
          y: 140
        }).on('click', function() {
          return self.optionPopup_.remove();
        });

        self.optionPopup_ = self.optionPopup_.start('div').addClass('popUpDropDown')
          .add(
            this.supportedLanguages.map( c => {
              return self.E()
                .start('div')
                  .add(self.formatLabel(c))
                  .on('click', async function() {
                    let user = self.subject.realUser
                    user.language = c.id
                    await self.userDAO.put(user)

                    location.reload();

                    // TODO: Figure out a better way to store user preferences
                    localStorage.setItem('localeLanguage', c.toString());
                  });
            }))
          .end();
        self.optionsBtn_.add(self.optionPopup_);
      }
    }
  ]
});
<commit_msg>Add space in string literal between language name and country name in LanguageChoiceView<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'LanguageChoiceView',
  extends: 'foam.u2.View',

  implements: [
    'foam.mlang.Expressions'
  ],

  requires: [
    'foam.u2.PopupView',
    'foam.nanos.auth.Language',
  ],

  imports: [
    'stack',
    'languageDAO',
    'subject',
    'userDAO',
    'countryDAO',
    'translationService'
  ],

  exports: [ 'as data' ],

  css: `
  ^carrot {
    width: 0;
    height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 5px solid white;
    display: inline-block;
    float: right;
    margin-top: 7px;
    margin-left: 7px;
  }
  ^ .foam-u2-ActionView-languageChoice {
    display: inline-block;
    background: none !important;
    border: 0 !important;
    box-shadow: none !important;
    width: max-content;
    cursor: pointer;
    margin-right: 27px;
  }
  ^ .foam-nanos-u2-navigation-TopNavigation-LanguageChoiceView {
    align-items: center;
  }
  ^ .foam-u2-ActionView-languageChoice > span {
    font-family: /*%FONT1%*/ Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-size: 16px;
    font-weight: 300;
    letter-spacing: 0.2px;
    color: #ffffff;
  }
  ^ .popUpDropDown > div {
    margin-left: -8px;
    border-radius: 4px;
    width: 100%;
    text-align: center;
    height: 25;
    padding: 0px 8px 5px 8px;
    font-size: 14px;
    font-weight: 300;
    letter-spacing: 0.2px;
    color: /*%BLACK%*/ #1e1f21;
    line-height: 30px;
  }
  ^ .foam-u2-PopupView {
    border-radius: 4px;
    left: -30 !important;
    top: 51px !important;
    padding: 0px 8px 0px 8px !important;
    z-index: 1000;
    width: fit-content !important;
    background: white;
    opacity: 1;
    box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.19);
  }
  ^ .popUpDropDown > div:hover{
    background-color: #1cc2b7;
    color: white;
    cursor: pointer;
  }
  ^ .popUpDropDown::before {
    content: ' ';
    position: absolute;
    height: 0;
    width: 0;
    border: 8px solid transparent;
    border-bottom-color: white;
    -ms-transform: translate(110px, -16px);
    transform: translate(50px, -16px);
  }
  ^ .flag {
    width: 30px !important;
    height: 17.6px;
    object-fit: contain;
    padding-top: 6px;
    padding-left: 10px;
    margin-right: 23px;
  }
  ^ img {
    height: 17.6px !important;
    margin-right: 6;
    width: auto;
  }
  `,

  properties: [
    'optionsBtn_',
    'supportedLanguages',
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.auth.Language',
      name: 'defaultLanguage',
      factory: function() {
        return foam.nanos.auth.Language.create({code: 'en'})
      }
    },
    {
      class: 'FObjectProperty',
      of: 'foam.nanos.auth.Language',
      name: 'lastLanguage',
      factory: function() {
        let language = this.supportedLanguages.find( e => e.toString() === foam.locale )
        language = language === undefined ? this.defaultLanguage : language
        localStorage.setItem('localeLanguage', language.toString());
        return language
      }
    }
  ],

  methods: [
    async function initE() {
      var self = this
      let languages = (await this.languageDAO
                        .where(foam.mlang.predicate.Eq.create({
                          arg1: foam.nanos.auth.Language.ENABLED,
                          arg2: true
                        })).select()).array;

      this.supportedLanguages = languages
      if ( this.subject && this.subject.realUser ) {
        let userPreferLanguage = this.supportedLanguages.find( e => e.id.compareTo(self.subject.realUser.language) === 0 )
        if ( ! userPreferLanguage ) {
            foam.locale = this.defaultLanguage.toString()
            let user = self.subject.realUser
            user.language = this.defaultLanguage.id
            localStorage.setItem('localeLanguage', this.defaultLanguage.toString());
            await self.userDAO.put(user)
        } else {
          if ( foam.locale != userPreferLanguage.toString() ) {
            foam.locale = userPreferLanguage.toString()
            localStorage.setItem('localeLanguage', userPreferLanguage.toString());
            location.reload();
          }
        }
      }

      let country = await this.countryDAO.find(this.lastLanguage.variant)
      let label = this.lastLanguage.variant != "" ? `${this.lastLanguage.name}(${this.lastLanguage.variant})` : `${this.lastLanguage.name}`
      if ( country && country.name != null ) {
        label = `${this.lastLanguage.name}\u00A0(${this.getCountryName(country.name, country.name)})`
      }

      this
        .addClass(this.myClass())
        .tag('span', null, this.optionsBtn_$)
        .start(this.LANGUAGE_CHOICE, {
          label: label
        })
        .start('div')
          .addClass(this.myClass('carrot'))
        .end()
      .end();
    },
    async function formatLabel(language) {
      let country = await this.countryDAO.find(language.variant)
      let label = language.variant != "" ? `${language.name}(${language.variant})` : `${language.name}`
      if ( country && country.name != null ) {
        label = `${language.name}\u00A0(${this.getCountryName(country.name, country.name)})`
      }
      return label
    },
    function getCountryName(countryName, defaultName) {
      defaultName = defaultName ? defaultName : ''
      let translation = this.translationService.getTranslation(foam.locale, `${foam.locale.toLowerCase()}.country.${countryName}`)
      translation = translation ? translation : defaultName
      return translation
    }
  ],

  actions: [
    {
      name: 'languageChoice',
      label: '',
      code: function() {
        var self = this;
        self.optionPopup_ = this.PopupView.create({
          width: 1165,
          x: -1137,
          y: 140
        }).on('click', function() {
          return self.optionPopup_.remove();
        });

        self.optionPopup_ = self.optionPopup_.start('div').addClass('popUpDropDown')
          .add(
            this.supportedLanguages.map( c => {
              return self.E()
                .start('div')
                  .add(self.formatLabel(c))
                  .on('click', async function() {
                    let user = self.subject.realUser
                    user.language = c.id
                    await self.userDAO.put(user)

                    location.reload();

                    // TODO: Figure out a better way to store user preferences
                    localStorage.setItem('localeLanguage', c.toString());
                  });
            }))
          .end();
        self.optionsBtn_.add(self.optionPopup_);
      }
    }
  ]
});
<|endoftext|>


<commit_before>var _ = require('lodash'),
    ss = require('simple-statistics'),
    chroma = require('chroma-js')

module.exports = {

  // JENKS
  jenks: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var breaks = ss.jenks(vals, numBreaks)
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // QUANTILES
  quantiles: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var min = ss.min(vals)
    var max = ss.max(vals)
    var interval = 1 / numBreaks
    var quants = [0]
    var currentBreak = 0
    for(var i=0;i<numBreaks;i++){
      currentBreak += interval
      quants.push(currentBreak)
    }
    var breaks = ss.quantile(vals, quants)
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // EQUAL INTERVAL
  equalIntervals: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var min = ss.min(vals)
    var max = ss.max(vals)
    var interval = (max - min) / numBreaks
    var breaks = [0]
    var currentBreak = 0
    for(var i=0;i<=numBreaks;i++){
      currentBreak += interval
      breaks.push(currentBreak)
    }
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // CUSTOM
  custom: function(fc, z, breaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // RANDOM
  random: function(fc, colors){
    var normals = normalize(colors.length)
    //var scale = chroma.scale(colors);
    _.each(fc.features, function(f){
      var rand = Math.floor(Math.random()*colors.length)
      console.log(rand)
      var colorHex = chroma(colors[rand]).hex()
      f = setColor(f, colorHex)
    })
    return fc
  }

}

function colorize(fc, z, colors, breaks, normals){
  var scale = chroma.scale(colors);
  _.each(fc.features, function(f){
    _.each(breaks, function(b1, i){
      var b2 = breaks[i + 1]
      var colorHex = scale(normals[i+1]).hex()
      if(f.properties[z] >= b1 && f.properties[z] < b2){
        f = setColor(f, colorHex)
      }
      else if(f.properties[z] >= b2){
        f = setColor(f, colorHex)
      }
    })
  })
  return fc
}

function setColor(feature, colorHex){
  if(feature.geometry.type === 'Point'){
    feature.properties['marker-color'] = colorHex
    return feature
  }
  else if(feature.geometry.type === 'LineString' || feature.geometry.type === 'MultiLineString'){
    feature.properties['fill'] = 0
    feature.properties['stroke'] = colorHex
    feature.properties['stroke-opacity'] = .8
    feature.properties['stroke-width'] = 3
    return feature
  }
  else if(feature.geometry.type === 'Polygon' || feature.geometry.type === 'MultiPolygon'){
    feature.properties['fill'] = colorHex
    feature.properties['stroke'] = '#000000'
    feature.properties['fill-opacity'] = .8
    return feature
  }
}

function normalize(numBreaks)
{
  var normals = [0]
  var interval = 1 / numBreaks
  var currentBreak = 0
  for(var i=0;i<numBreaks;i++){
    currentBreak += interval
    normals.push((currentBreak).toFixed(4))
  }
  return normals
}
<commit_msg>random colors working<commit_after>var _ = require('lodash'),
    ss = require('simple-statistics'),
    chroma = require('chroma-js')

module.exports = {

  // JENKS
  jenks: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var breaks = ss.jenks(vals, numBreaks)
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // QUANTILES
  quantiles: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var min = ss.min(vals)
    var max = ss.max(vals)
    var interval = 1 / numBreaks
    var quants = [0]
    var currentBreak = 0
    for(var i=0;i<numBreaks;i++){
      currentBreak += interval
      quants.push(currentBreak)
    }
    var breaks = ss.quantile(vals, quants)
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // EQUAL INTERVAL
  equalIntervals: function(fc, z, numBreaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var min = ss.min(vals)
    var max = ss.max(vals)
    var interval = (max - min) / numBreaks
    var breaks = [0]
    var currentBreak = 0
    for(var i=0;i<=numBreaks;i++){
      currentBreak += interval
      breaks.push(currentBreak)
    }
    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // CUSTOM
  custom: function(fc, z, breaks, colors){
    var vals = _.chain(fc.features)
      .pluck('properties')
      .pluck(z)
      .value()

    var normals = normalize(breaks.length)
    fc = colorize(fc, z, colors, breaks, normals)
    return fc
  },

  // RANDOM
  random: function(fc, colors){
    var normals = normalize(colors.length)
    _.each(fc.features, function(f){
      var rand = Math.floor(Math.random()*colors.length)
      var colorHex = chroma(colors[rand]).hex()
      f = setColor(f, colorHex)
    })
    return fc
  }

}

function colorize(fc, z, colors, breaks, normals){
  var scale = chroma.scale(colors);
  _.each(fc.features, function(f){
    _.each(breaks, function(b1, i){
      var b2 = breaks[i + 1]
      var colorHex = scale(normals[i+1]).hex()
      if(f.properties[z] >= b1 && f.properties[z] < b2){
        f = setColor(f, colorHex)
      }
      else if(f.properties[z] >= b2){
        f = setColor(f, colorHex)
      }
    })
  })
  return fc
}

function setColor(feature, colorHex){
  if(feature.geometry.type === 'Point'){
    feature.properties['marker-color'] = colorHex
    return feature
  }
  else if(feature.geometry.type === 'LineString' || feature.geometry.type === 'MultiLineString'){
    feature.properties['fill'] = 0
    feature.properties['stroke'] = colorHex
    feature.properties['stroke-opacity'] = .8
    feature.properties['stroke-width'] = 3
    return feature
  }
  else if(feature.geometry.type === 'Polygon' || feature.geometry.type === 'MultiPolygon'){
    feature.properties['fill'] = colorHex
    feature.properties['stroke'] = '#000000'
    feature.properties['fill-opacity'] = .8
    return feature
  }
}

function normalize(numBreaks)
{
  var normals = [0]
  var interval = 1 / numBreaks
  var currentBreak = 0
  for(var i=0;i<numBreaks;i++){
    currentBreak += interval
    normals.push((currentBreak).toFixed(4))
  }
  return normals
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { Box } from '@tlon/indigo-react';
import { Route, Switch } from 'react-router-dom';
import styled from 'styled-components';

import LaunchApp from '~/views/apps/launch/app';
import TermApp from '~/views/apps/term/app';
import Landscape from '~/views/landscape/index';
import Profile from '~/views/apps/profile/profile';
import ErrorComponent from '~/views/components/Error';
import Notifications from '~/views/apps/notifications/notifications';
import GraphApp from '../../apps/graph/app';

export const Container = styled(Box)`
   flex-grow: 1;
   overflow: hidden;
   width: 100%;
   height: calc(100% - 62px);
`;

export const Content = (props) => {
  return (
    <Container>
      <Switch>
        <Route
          exact
          path='/'
          render={p => (
            <LaunchApp
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path='/~term'
          render={p => (
            <TermApp
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path='/~landscape'
          render={p => (
            <Landscape
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path="/~profile"
          render={ p => (
            <Profile
             {...props}
            />
          )}
        />
        <Route
          path="/~notifications"
          render={ p => (
            <Notifications {...props} />
          )}
        />
        <GraphApp {...props} />
        <Route
          render={p => (
            <ErrorComponent
              code={404}
              description="Not Found"
              {...p} />
          )}
        />
      </Switch>
    </Container>
  );
}
<commit_msg>landscape: fix overeager graphapp routing<commit_after>import React, { Component } from 'react';
import { Box } from '@tlon/indigo-react';
import { Route, Switch } from 'react-router-dom';
import styled from 'styled-components';

import LaunchApp from '~/views/apps/launch/app';
import TermApp from '~/views/apps/term/app';
import Landscape from '~/views/landscape/index';
import Profile from '~/views/apps/profile/profile';
import ErrorComponent from '~/views/components/Error';
import Notifications from '~/views/apps/notifications/notifications';
import GraphApp from '../../apps/graph/app';

export const Container = styled(Box)`
   flex-grow: 1;
   overflow: hidden;
   width: 100%;
   height: calc(100% - 62px);
`;

export const Content = (props) => {
  return (
    <Container>
      <Switch>
        <Route
          exact
          path='/'
          render={p => (
            <LaunchApp
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path='/~term'
          render={p => (
            <TermApp
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path='/~landscape'
          render={p => (
            <Landscape
              history={p.history}
              location={p.location}
              match={p.match}
              {...props} />
          )}
        />
        <Route
          path="/~profile"
          render={ p => (
            <Profile
             {...props}
            />
          )}
        />
        <Route
          path="/~notifications"
          render={ p => (
            <Notifications {...props} />
          )}
        />
        <GraphApp path="/~graph" {...props} />
        <Route
          render={p => (
            <ErrorComponent
              code={404}
              description="Not Found"
              {...p} />
          )}
        />
      </Switch>
    </Container>
  );
}
<|endoftext|>


<commit_before>// Send commands with rpi_hdmi to control attached display
function command(action) {
	// Bounce if not configured
	if (config.media.hdmi.rpi.enable !== true) return;

	switch (action) {
		case 'powerstatus' : {
			log.msg({ msg : 'Requesting power status' });

			hdmi_rpi.hdmi_client.status();
			break;
		}

		case 'poweron' : {
			// Only power on if it's not already on
			if (status.hdmi.rpi.power === true) return;

			log.msg({ msg : 'Sending power on' });

			hdmi_rpi.hdmi_client.power(true);
			break;
		}

		case 'poweroff' : {
			// Only power off if it's not already off
			if (status.hdmi.rpi.power === false) return;

			log.msg({ msg : 'Sending power off' });

			hdmi_rpi.hdmi_client.power(false);
		}
	}
}

// Configure event listeners
function init_listeners() {
	// Error handling
	hdmi_rpi.hdmi_client.on('error', (data) => {
		log.msg('event: error');
		log.msg(JSON.stringify(data, null, 2));
	});

	// Event handling
	hdmi_rpi.hdmi_client.on('command', (data) => {
		log.msg('event: command');
		log.msg(JSON.stringify(data, null, 2));
	});

	hdmi_rpi.hdmi_client.on('status', (data) => {
		log.msg('event: status');

		if (data.data.type === 'tv') {
			update.status('hdmi.rpi.group',       data.data.status.group);
			update.status('hdmi.rpi.mode',        data.data.status.mode);
			update.status('hdmi.rpi.power',       data.data.status.power);
			update.status('hdmi.rpi.progressive', data.data.status.progressive);
			update.status('hdmi.rpi.ratio',       data.data.status.ratio);
			update.status('hdmi.rpi.refreshrate', data.data.status.refreshrate);
			update.status('hdmi.rpi.resolution',  data.data.status.resolution);
			update.status('hdmi.rpi.state',       data.data.status.state);
		}
	});

	// Turn on and off with ignition
	IKE.on('ignition-poweroff', () => { command('poweroff'); });
	IKE.on('ignition-powerup',  () => { command('poweron');  });

	log.msg({ msg : 'Initialized listeners' });
}

// Start cec-client, populate connection var
function init(init_cb) {
	if (config.media.hdmi.rpi.enable !== true) {
		process.nextTick(init_cb);
		return;
	}

	// Only pull in libraries if hdmi is enabled
	hdmi_rpi.hdmi_client = new (require('rpi-hdmi'))();

	log.msg({ msg : 'Initialized' });

	init_listeners();

	// Get status
	setTimeout(() => {
		command('powerstatus');
	}, 3000);

	// Holla back
	process.nextTick(init_cb);
}

// Stop cec-client, clear connection var
function term(term_cb) {
	if (config.media.hdmi.rpi.enable !== true) {
		process.nextTick(term_cb);
		term_cb = undefined;
		return;
	}

	// Reset status variables
	update.status('hdmi.power_status',  null);

	log.msg({ msg : 'Terminated' });
	process.nextTick(term_cb);
	term_cb = undefined;
}

module.exports = {
	hdmi_client : null,

	command : command,

	init_listeners : init_listeners,

	init : init,
	term : term,
};
<commit_msg>Update<commit_after>// Send commands with rpi_hdmi to control attached display
function command(action) {
	// Bounce if not configured
	if (config.media.hdmi.rpi.enable !== true) return;

	switch (action) {
		case 'powerstatus' : {
			log.msg({ msg : 'Requesting power status' });

			hdmi_rpi.hdmi_client.status();
			break;
		}

		case 'poweron' : {
			// Only power on if it's not already on
			if (status.hdmi.rpi.power === true) return;

			log.msg({ msg : 'Sending power on' });

			hdmi_rpi.hdmi_client.power(true);
			break;
		}

		case 'poweroff' : {
			// Only power off if it's not already off
			if (status.hdmi.rpi.power === false) return;

			log.msg({ msg : 'Sending power off' });

			hdmi_rpi.hdmi_client.power(false);
		}
	}
}

// Configure event listeners
function init_listeners() {
	// Error handling
	hdmi_rpi.hdmi_client.on('error', (data) => {
		log.msg('event: error');
		log.msg(JSON.stringify(data));
	});

	// Event handling
	hdmi_rpi.hdmi_client.on('command', (data) => {
		log.msg('event: command');
		log.msg(JSON.stringify(data));
	});

	hdmi_rpi.hdmi_client.on('status', (data) => {
		log.msg('event: status');

		if (data.data.type === 'tv') {
			update.status('hdmi.rpi.group',       data.data.status.group);
			update.status('hdmi.rpi.mode',        data.data.status.mode);
			update.status('hdmi.rpi.power',       data.data.status.power);
			update.status('hdmi.rpi.progressive', data.data.status.progressive);
			update.status('hdmi.rpi.ratio',       data.data.status.ratio);
			update.status('hdmi.rpi.refreshrate', data.data.status.refreshrate);
			update.status('hdmi.rpi.resolution',  data.data.status.resolution);
			update.status('hdmi.rpi.state',       data.data.status.state);
		}
	});

	// Turn on and off with ignition
	IKE.on('ignition-poweroff', () => { command('poweroff'); });
	IKE.on('ignition-powerup',  () => { command('poweron');  });

	log.msg({ msg : 'Initialized listeners' });
}

// Start cec-client, populate connection var
function init(init_cb) {
	if (config.media.hdmi.rpi.enable !== true) {
		process.nextTick(init_cb);
		return;
	}

	// Only pull in libraries if hdmi is enabled
	hdmi_rpi.hdmi_client = new (require('rpi-hdmi'))();

	log.msg({ msg : 'Initialized' });

	init_listeners();

	// Get status
	setTimeout(() => {
		command('powerstatus');
	}, 3000);

	// Holla back
	process.nextTick(init_cb);
}

// Stop cec-client, clear connection var
function term(term_cb) {
	if (config.media.hdmi.rpi.enable !== true) {
		process.nextTick(term_cb);
		term_cb = undefined;
		return;
	}

	// Reset status variables
	update.status('hdmi.power_status',  null);

	log.msg({ msg : 'Terminated' });
	process.nextTick(term_cb);
	term_cb = undefined;
}

module.exports = {
	hdmi_client : null,

	command : command,

	init_listeners : init_listeners,

	init : init,
	term : term,
};
<|endoftext|>