<commit_before>"use strict";

const axios =   require("axios");
const moment = require("moment");
const path =   require("path");
const fs   =   require("fs");

const mdUtil = require("../util/md_util.js");
const configModule = require("../model/config.js");
const config = require("../config.js");
const language = require("../model/language.js");

const NodeCache = require("node-cache");

const nominatimCacheFile = path.join(__dirname, "..", "cache", "nominatim.cache");
const nominatimCacheDir  = path.join(__dirname, "..", "cache");
const nominatimCache = new NodeCache({ stdTTL: 21 * 24 * 60 * 60, checkperiod: 24 * 60 * 60 });

const osmbcDateFormat = config.getValue("CalendarDateFormat", { mustExist: true });

function createDir(dir, callback) {
  if (fs.existsSync(dir)) return callback();
  return fs.mkdir(dir, callback);
}

function storeCache() {
  function storeCacheFunction() {
    const keys = nominatimCache.keys();
    const dump = nominatimCache.mget(keys);
    const dumpstring = JSON.stringify(dump);
    createDir(nominatimCacheDir, function writeData() {
      fs.writeFile(nominatimCacheFile, dumpstring, (err) => {
        if (err) {
          throw err;
        }
      });
    });
  }
  // Wait 1 second to first return result and give timeslot to frontend
  setTimeout(storeCacheFunction, 1000);
}
const cacheLoaded = false;
function readCache() {
  if (cacheLoaded) return;
  const dumpstring = fs.readFileSync(nominatimCacheFile);
  const dump = JSON.parse(dumpstring);
  for (const k in dump) {
    nominatimCache.set(k, dump[k]);
  }
}

async function loadEvents(lang) {
  readCache();
  const url = "https://osmcal.org/api/v2/events/";
  let json;
  let request;
  try {
    request = await axios.get(url);
    json = request.data;
  } catch (err) {
    // ignore error
  }
  if (!Array.isArray(json)) json = [{ name: "osmcal did not reply with Eventlist" }];
  let event;
  for (event of json) {
    if (!event.location) continue;
    if (!event.location.coords) continue;
    const requestString = "https://nominatim.openstreetmap.org/reverse?format=jsonv2&zoom=10&lat=" + encodeURI(event.location.coords[1]) +
    "&lon=" + encodeURI(event.location.coords[0]) +
    "&accept-language=" + lang;

    let loc = nominatimCache.get(requestString);
    if (loc === undefined) {
      try {
        request = await axios.get(requestString, { headers: { "User-Agent": "OSMBC Calendar Generator" } });
        loc = request.data;
      } catch (err) {
        // ignore axios error
      }
      if (loc && !loc.error) nominatimCache.set(requestString, loc);
    }
    if (loc && loc.name) event.town = loc.name; else event.town = "no location";

    // special fix for not delivering town (e.g. Berlin)

    if (loc && loc.addresstype === "postcode" && loc.address && loc.address.state) event.town = loc.address.state;
    if (loc && loc.address && loc.address.country) event.country = loc.address.country;
    if (loc && loc.address && loc.address.country_code) event.country_code = loc.address.country_code;
  }
  storeCache();
  return json;
}

async function filterEvents(events, filter) {
  const result = [];
  let event;
  for (event of events) {
    if (!filterEvent(event, filter)) result.push(event);
  }
  return result;
}

function filterEvent(event, option) {
  let date = new moment();

  const startDate = moment(event.date && event.date.start);
  let endDate = startDate.clone();
  if (event.date && typeof event.date.end !== "undefined") endDate = moment(event.date.end);

  let diff = -3;
  const optionDiff = (option) ? parseInt(option.date) : diff;
  if (!Number.isNaN(optionDiff)) {
    diff = optionDiff;
  }
  date = date.add(diff, "day");
  let duration = 15;
  if (option && option.duration && option.duration !== "") {
    duration = parseInt(option.duration);
  }
  let bigDuration = 23;
  if (option && option.big_duration && option.big_duration !== "") {
    bigDuration = parseInt(option.big_duration);
  }
  const from = date.clone();
  const to = date.clone().add(duration, "days");
  const toForBig = date.clone().add(bigDuration, "days");

  // until in two weeks
  let filtered = false;

  if (endDate.isBefore(from, "day")) filtered = true;
  if (startDate.isAfter(toForBig, "day")) filtered = true;

  if (option && option.includeCountries && event.country_code &&
    option.includeCountries.indexOf(event.country_code) < 0) filtered = true;

  if (option && option.excludeCountries && event.country_code &&
    option.excludeCountries.indexOf(event.country_code) >= 0) filtered = true;

  if (!event.big && startDate.isAfter(to)) filtered = true;
  return filtered;
}

function enrichData(json, lang) {
  const ct = configModule.getConfig("calendartranslation");
  const cf = configModule.getConfig("calendarflags");

  if (!Array.isArray(json)) return;

  if (json.length === 0) return;

  if (typeof json[0] !== "object") return;

  let event;
  for (event of json) {
    // convert online venue to binary online flag
    let online = false;
    if (event.location && ct.locationNoTranslation && ct.locationNoTranslation.indexOf(event.location.venue) >= 0) online = true;
    event.online = online;

    if (event.cancelled) {
      event.name = "~~" + event.name + "~~";
    }

    if (event.url) {
      event.name = event.name + ` [:osmcalpic:](${event.url})`;
    }

    // convert date
    let dateString;
    const sd = moment(event.date && event.date.start);
    const ed = moment(event.date && event.date.end);
    sd.locale(language.momentLocale(lang));
    ed.locale(language.momentLocale(lang));

    if (event.date && event.date.start) {
      dateString = sd.format(osmbcDateFormat);
    }
    if (event.date && event.date.end) {
      if ((sd.startOf("day").isBefore(ed.startOf("day")))) {
        dateString = sd.format(osmbcDateFormat) + " - " + ed.format(osmbcDateFormat);
      }
    }
    event.dateString = dateString;

    // generate Calendar Flags
    event.country_flag = event.country_code;
    if (cf[event.country_code]) event.country_flag = `![flag](${cf[event.country_code]})`;

    if (event.online) {
      if (cf.online) event.online = `![online](${cf.online})`;
      else event.online = "✓";
    } else event.online = "";
  }
}

async function getEventMd(lang) {
  const ef = configModule.getConfig("eventsfilter");
  const ct = configModule.getConfig("calendartranslation");
  let townName = "Town";
  if (ct.town && ct.town[lang]) townName = ct.town[lang];
  let countryName = "Country";
  if (ct.country && ct.country[lang]) countryName = ct.country[lang];
  let titleName = "Title";
  if (ct.title && ct.title[lang]) titleName = ct.title[lang];
  let dateName = "Date";
  if (ct.date && ct.date[lang]) dateName = ct.date[lang];
  let onlineName = "Online";
  if (ct.online && ct.online[lang]) onlineName = ct.online[lang];

  let events;
  let filter;
  let filteredEvents;

  try {
    events = await loadEvents(lang);
    filter = ef[lang];
    filteredEvents = await filterEvents(events, filter);
  } catch (err) {
    let errmessage = "Calendar could not be generated";
    if (err.message) errmessage = err.message;
    filteredEvents = [{ name: errmessage }];
    if (process.NODE_ENV !== "test") console.info(err);
  }

  enrichData(filteredEvents, lang);

  const table = [
    { field: "town", name: townName },
    { field: "name", name: titleName },
    { field: "online", name: onlineName },
    { field: "dateString", name: dateName },
    { field: "country_flag", name: countryName }
  ];
  const result =  mdUtil.mdTable(filteredEvents, table);
  return result;
}

function getEventMdCb(lang, cb) {
  getEventMd(lang)
    .then((result) => { return cb(null, result); })
    .catch((err) => { return cb(err); });
}

module.exports.getEventMd = getEventMd;
module.exports.getEventMdCb = getEventMdCb;
module.exports.forTestOnly = {};
module.exports.forTestOnly.filterEvent = filterEvent;
<commit_msg>Do not generat an error, if cache file does not exisit. Cache will be created later on store cach.<commit_after>"use strict";

const axios =   require("axios");
const moment = require("moment");
const path =   require("path");
const fs   =   require("fs");

const mdUtil = require("../util/md_util.js");
const configModule = require("../model/config.js");
const config = require("../config.js");
const language = require("../model/language.js");

const NodeCache = require("node-cache");

const nominatimCacheFile = path.join(__dirname, "..", "cache", "nominatim.cache");
const nominatimCacheDir  = path.join(__dirname, "..", "cache");
const nominatimCache = new NodeCache({ stdTTL: 21 * 24 * 60 * 60, checkperiod: 24 * 60 * 60 });

const osmbcDateFormat = config.getValue("CalendarDateFormat", { mustExist: true });

function createDir(dir, callback) {
  if (fs.existsSync(dir)) return callback();
  return fs.mkdir(dir, callback);
}

function storeCache() {
  function storeCacheFunction() {
    const keys = nominatimCache.keys();
    const dump = nominatimCache.mget(keys);
    const dumpstring = JSON.stringify(dump);
    createDir(nominatimCacheDir, function writeData() {
      fs.writeFile(nominatimCacheFile, dumpstring, (err) => {
        if (err) {
          throw err;
        }
      });
    });
  }
  // Wait 1 second to first return result and give timeslot to frontend
  setTimeout(storeCacheFunction, 1000);
}
const cacheLoaded = false;
function readCache() {
  if (cacheLoaded) return;
  try {
    const dumpstring = fs.readFileSync(nominatimCacheFile);
    const dump = JSON.parse(dumpstring);
    for (const k in dump) {
      nominatimCache.set(k, dump[k]);
    }
  } catch (err) {
    if (err.code !== "ENOENT");
    throw err;
  }
}

async function loadEvents(lang) {
  readCache();
  const url = "https://osmcal.org/api/v2/events/";
  let json;
  let request;
  try {
    request = await axios.get(url);
    json = request.data;
  } catch (err) {
    // ignore error
  }
  if (!Array.isArray(json)) json = [{ name: "osmcal did not reply with Eventlist" }];
  let event;
  for (event of json) {
    if (!event.location) continue;
    if (!event.location.coords) continue;
    const requestString = "https://nominatim.openstreetmap.org/reverse?format=jsonv2&zoom=10&lat=" + encodeURI(event.location.coords[1]) +
    "&lon=" + encodeURI(event.location.coords[0]) +
    "&accept-language=" + lang;

    let loc = nominatimCache.get(requestString);
    if (loc === undefined) {
      try {
        request = await axios.get(requestString, { headers: { "User-Agent": "OSMBC Calendar Generator" } });
        loc = request.data;
      } catch (err) {
        // ignore axios error
      }
      if (loc && !loc.error) nominatimCache.set(requestString, loc);
    }
    if (loc && loc.name) event.town = loc.name; else event.town = "no location";

    // special fix for not delivering town (e.g. Berlin)

    if (loc && loc.addresstype === "postcode" && loc.address && loc.address.state) event.town = loc.address.state;
    if (loc && loc.address && loc.address.country) event.country = loc.address.country;
    if (loc && loc.address && loc.address.country_code) event.country_code = loc.address.country_code;
  }
  storeCache();
  return json;
}

async function filterEvents(events, filter) {
  const result = [];
  let event;
  for (event of events) {
    if (!filterEvent(event, filter)) result.push(event);
  }
  return result;
}

function filterEvent(event, option) {
  let date = new moment();

  const startDate = moment(event.date && event.date.start);
  let endDate = startDate.clone();
  if (event.date && typeof event.date.end !== "undefined") endDate = moment(event.date.end);

  let diff = -3;
  const optionDiff = (option) ? parseInt(option.date) : diff;
  if (!Number.isNaN(optionDiff)) {
    diff = optionDiff;
  }
  date = date.add(diff, "day");
  let duration = 15;
  if (option && option.duration && option.duration !== "") {
    duration = parseInt(option.duration);
  }
  let bigDuration = 23;
  if (option && option.big_duration && option.big_duration !== "") {
    bigDuration = parseInt(option.big_duration);
  }
  const from = date.clone();
  const to = date.clone().add(duration, "days");
  const toForBig = date.clone().add(bigDuration, "days");

  // until in two weeks
  let filtered = false;

  if (endDate.isBefore(from, "day")) filtered = true;
  if (startDate.isAfter(toForBig, "day")) filtered = true;

  if (option && option.includeCountries && event.country_code &&
    option.includeCountries.indexOf(event.country_code) < 0) filtered = true;

  if (option && option.excludeCountries && event.country_code &&
    option.excludeCountries.indexOf(event.country_code) >= 0) filtered = true;

  if (!event.big && startDate.isAfter(to)) filtered = true;
  return filtered;
}

function enrichData(json, lang) {
  const ct = configModule.getConfig("calendartranslation");
  const cf = configModule.getConfig("calendarflags");

  if (!Array.isArray(json)) return;

  if (json.length === 0) return;

  if (typeof json[0] !== "object") return;

  let event;
  for (event of json) {
    // convert online venue to binary online flag
    let online = false;
    if (event.location && ct.locationNoTranslation && ct.locationNoTranslation.indexOf(event.location.venue) >= 0) online = true;
    event.online = online;

    if (event.cancelled) {
      event.name = "~~" + event.name + "~~";
    }

    if (event.url) {
      event.name = event.name + ` [:osmcalpic:](${event.url})`;
    }

    // convert date
    let dateString;
    const sd = moment(event.date && event.date.start);
    const ed = moment(event.date && event.date.end);
    sd.locale(language.momentLocale(lang));
    ed.locale(language.momentLocale(lang));

    if (event.date && event.date.start) {
      dateString = sd.format(osmbcDateFormat);
    }
    if (event.date && event.date.end) {
      if ((sd.startOf("day").isBefore(ed.startOf("day")))) {
        dateString = sd.format(osmbcDateFormat) + " - " + ed.format(osmbcDateFormat);
      }
    }
    event.dateString = dateString;

    // generate Calendar Flags
    event.country_flag = event.country_code;
    if (cf[event.country_code]) event.country_flag = `![flag](${cf[event.country_code]})`;

    if (event.online) {
      if (cf.online) event.online = `![online](${cf.online})`;
      else event.online = "✓";
    } else event.online = "";
  }
}

async function getEventMd(lang) {
  const ef = configModule.getConfig("eventsfilter");
  const ct = configModule.getConfig("calendartranslation");
  let townName = "Town";
  if (ct.town && ct.town[lang]) townName = ct.town[lang];
  let countryName = "Country";
  if (ct.country && ct.country[lang]) countryName = ct.country[lang];
  let titleName = "Title";
  if (ct.title && ct.title[lang]) titleName = ct.title[lang];
  let dateName = "Date";
  if (ct.date && ct.date[lang]) dateName = ct.date[lang];
  let onlineName = "Online";
  if (ct.online && ct.online[lang]) onlineName = ct.online[lang];

  let events;
  let filter;
  let filteredEvents;

  try {
    events = await loadEvents(lang);
    filter = ef[lang];
    filteredEvents = await filterEvents(events, filter);
  } catch (err) {
    let errmessage = "Calendar could not be generated";
    if (err.message) errmessage = err.message;
    filteredEvents = [{ name: errmessage }];
    if (process.NODE_ENV !== "test") console.info(err);
  }

  enrichData(filteredEvents, lang);

  const table = [
    { field: "town", name: townName },
    { field: "name", name: titleName },
    { field: "online", name: onlineName },
    { field: "dateString", name: dateName },
    { field: "country_flag", name: countryName }
  ];
  const result =  mdUtil.mdTable(filteredEvents, table);
  return result;
}

function getEventMdCb(lang, cb) {
  getEventMd(lang)
    .then((result) => { return cb(null, result); })
    .catch((err) => { return cb(err); });
}

module.exports.getEventMd = getEventMd;
module.exports.getEventMdCb = getEventMdCb;
module.exports.forTestOnly = {};
module.exports.forTestOnly.filterEvent = filterEvent;
<|endoftext|>


<commit_before>import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import Sidebar from '../components/Sidebar';

const mapStateToProps = state => {
  return {
    accounts: Object.values(state.accounts),
  };
};

const mapDispatchToProps = () => {
  return {
    onSelectAccount: () => null,
  };
};

export default withRouter(connect(
  mapStateToProps,
  mapDispatchToProps
)(Sidebar));
<commit_msg>refactor(sidebar): remove unused code<commit_after>import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import Sidebar from '../components/Sidebar';

const mapStateToProps = state => {
  return {
    accounts: Object.values(state.accounts),
  };
};

export default withRouter(connect(
  mapStateToProps,
)(Sidebar));
<|endoftext|>


<commit_before>/**
 * Eye sensor has a maximum range and senses walls
 * @class
 * @constructor {object} input
 */
var Eye = function(input) {
  console.log('Creating eye', input);
  this.name             = (input && input.name)?      input.name:'';
  this.angle            = (input && input.angle)?     input.angle:0;
  this.fov              = (input && input.fov)?       input.fov:(15*Math.PI/180); // Default 15deg.
  this.max_range        = (input && input.max_range)? input.max_range:4;
  this.sensed_proximity = this.max_range;
  this.sensed_type      = -1; // what does the eye see?

  // Extra sensor dealing exclusively with goals.
  // TODO: Refactor to binary, "nose". Could be interesting with forward turns.
  this.goal_range       = (input && input.goal_range)?input.goal_range:10;
  this.sensed_goal      = this.goal_range;

  // Watch for updates, syncing framerate to sensors.
  this.updated = false;

  // TODO: Watch for goal updates also?
};

// RatSLAM Goal log for rewarding distance.
var Goal = function(id, dis, rad) {
  //console.log('Creating goal', id, dis, rad);
  this.id  = id;
  this.dis = dis;
  this.rad = rad;
};

/**
 * A single agent
 * @class Agent
 * @param {Ros} ros
 * @param {array} eyes
 * @param {array} actions
 * @param {object} agent_opts
 * @param {object} brain_opts
 */
var Agent = function(ros, eyes, actions, agent_opts, brain_opts) {
  if (!ros) throw new Exception('ROS instance must be passed to RatSLAM.');
  this.ros = ros;

  // Initialise eyes from config passed in.
  this.eyes = [];
  for (var i = 0; i < eyes.length; i++) {
    if (typeof(eyes[i].angle) !== "undefined" && typeof(eyes[i].fov) !== "undefined") {
      this.eyes.push(new Eye(eyes[i]));
    }
  }

  this.actions = (actions)?actions:[
    // Default actions.
    [1.0,0.0],
    [1.0,-3.0],
    [1.0,3.0],
    [0.0,-4.0],
    [0.0,4.0]
  ];

  // Remember RatSLAM goals for rewarding distance.
  this.goals = [];

  var num_inputs      = agent_opts.num_inputs;
  var num_actions     = agent_opts.num_actions;
  var temporal_window = brain_opts.temporal_window; // amount of temporal memory. 0 = agent lives in-the-moment :)
  var network_size = num_inputs*temporal_window + num_actions*temporal_window + num_inputs;

  // the value function network computes a value of taking any of the possible actions
  // given an input state. Here we specify one explicitly the hard way
  // but user could also equivalently instead use opt.hidden_layer_sizes = [20,20]
  // to just insert simple relu hidden layers.
  var layer_defs = [];
  layer_defs.push({type: 'input', out_sx: 1, out_sy: 1, out_depth: network_size});
  layer_defs.push({type: 'fc', num_neurons: 80, activation: 'relu'});
  //layer_defs.push({type:'dropout', drop_prob:0.2}); // Uncertainty approximation.
  layer_defs.push({type: 'fc', num_neurons: 80, activation: 'relu'});
  layer_defs.push({type: 'regression', num_neurons: num_actions});

  brain_opts.layer_defs = layer_defs;

  var brain = new deepqlearn.Brain(num_inputs, num_actions, brain_opts); // woohoo

  this.brain = brain;

  this.reward_bonus = 0.0;
  this.digestion_signal = 0.0;

  // outputs on world
  this.linX = 0.0; // Linear velocity forwards.
  this.angZ = 0.0; // Angular velocity rotation.
};

Agent.prototype = {
  /**
   * Add RatSLAM goal to memory for later reward
   * @method addGoal
   * @param {integer} id
   * @param {float} dis
   * @param {float} rad
   */
  addGoal: function(id, dis, rad) {
    // TODO: If Goal ID has changed, publish an "eat" reward?
    // Does it only change when eaten? Not really, it changes when shortcut too.
    this.goals.push(new Goal(id, dis, rad));
    // Truncate log, only need a few to gauge getting closer.
    this.goals = this.goals.slice(-2);

    return goal;
  },
  forward: function() {
    // in forward pass the agent simply behaves in the environment
    // create input to brain
    // TODO: Signal when loop closure, so net can correlate difference from goal eyes improvement.
    var num_eyes = this.eyes.length;
    var input_array = new Array(num_eyes * 1); // FIXME: ``* 1` Shouldn't it be the size?
    for (var i=0; i<num_eyes; i++) {
      var e = this.eyes[i];
      input_array[i*4] = 1.0; // Wall
      input_array[i*4+1] = 1.0; // Type 1
      input_array[i*4+2] = 1.0; // Type 2
      input_array[i*4+3] = Math.min(e.goal_range, e.sensed_goal)/e.goal_range; // Goal, normalize to [0,1]
      if (e.sensed_type !== -1) {
        // sensed_type is 0 for wall, 1 for food and 2 for poison.
        // lets do a 1-of-k encoding into the input array
        input_array[i*4 + e.sensed_type] = e.sensed_proximity/e.max_range; // normalize to [0,1]
        /*
        console.log('input0: ' + input_array[i*4]);
        console.log('input1: ' + input_array[i*4+1]);
        console.log('input2: ' + input_array[i*4+2]);
        console.log('input3: ' + input_array[i*4+3]);
        */
      }
    }

    // get action from brain
    var actionix = this.brain.forward(input_array);
    var action = this.actions[actionix];
    this.actionix = actionix; //back this up

    // demultiplex into behavior variables
    this.linX = action[0]*1;
    this.angZ = action[1]*1;
  },
  backward: function() {
    // in backward pass agent learns.
    // compute reward
    var proximity_reward = 0.0;
    var num_eyes = this.eyes.length;
    for (var i=0; i<num_eyes; i++) {
      var e = this.eyes[i];
      // agents dont like to see walls, especially up close
      proximity_reward += e.sensed_type === 0 ? e.sensed_proximity/e.max_range : 1.0;

      // Debug log, goal spotting, shown in sync with brain.
      //if (e.sensed_goal < e.goal_range) console.log('a', i, e.sensed_goal, Math.min(e.goal_range, e.sensed_goal)/e.goal_range);
    }
    proximity_reward = proximity_reward/(num_eyes-2); // FIXME: Hack to remove 2 extra eyes.
    proximity_reward = Math.min(1.0, proximity_reward);

    // agents like to be near goals
    var goal_factor = 0.0;
    var goal_reward = 0.0;

    if (this.goals[this.goals.length-1] && this.goals[this.goals.length-1].dis > 0) {
      // FIXME: Only if below max, so there is a reading to correlate with?
      goal_factor = Math.max(0.0, Math.min(1.0, 1/this.goals[this.goals.length-1].dis));
      // FIXME: Redundant, forward bonus and goal view implies this.
      //goal_reward = 0.1 * goal_factor * proximity_reward;
    }

    // agents like to go straight forward, more-so towards goals. // FIXME: "near" goals... side-effect, max towards goal.
    var forward_reward = 0.0;
    // TODO: Reward fast turns only once epsilon drops?
    if ((this.actionix === 0 || this.actionix === 1 || this.actionix === 2) && proximity_reward > 0.85) { // 0.75 a little too close for corners. Rewards stuck wheel.
      // TODO: Closer to goal = more forward. Instead of eye reward, stop goal reward when goal is behind?

      // Some forward reward, some forward goal reward.
      //forward_reward = (0.05 + (0.05 * goal_factor)) * proximity_reward;
      forward_reward = 0.05 * proximity_reward;
      // Half as much for forward turns.
      //if (this.actionix === 1 || this.actionix === 2) {
      //  forward_reward = forward_reward / 2;
      //}
    }

    // agents like to eat good things
    var digestion_reward = this.digestion_signal;
    this.digestion_signal = 0.0;

    var reward = proximity_reward + forward_reward + goal_reward + digestion_reward;

    // Log repeating actions.
    if (this.cnt > 4) {
      console.log(reward.toFixed(5), this.actionix, this.cnt, this.linX.toFixed(1), this.angZ.toFixed(1));
      console.log('rewards', forward_reward, goal_reward);
    }

    // Publish statistics to ROS topics.
    this.ros.pubTopic('/dqn/learning',   'std_msgs/Float32', this.ros.createStdMsg('float', (this.brain.learning)?1:0));
    this.ros.pubTopic('/dqn/reward',     'std_msgs/Float32', this.ros.createStdMsg('float', reward));
    //this.ros.pubTopic('/dqn/action',   'std_msgs/Float32', this.ros.createStdMsg('float', this.actionix));
    this.ros.pubTopic('/dqn/epsilon',    'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.epsilon));
    //this.ros.pubTopic('/dqn/avg_loss', 'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.average_loss_window.get_average()));
    this.ros.pubTopic('/dqn/avg_reward', 'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.average_reward_window.get_average()));
    //this.ros.pubTopic('/dqn/age',      'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.age));

    // pass to brain for learning
    this.brain.backward(reward);
  }
};

module.exports = Agent;
<commit_msg>No need to return goal<commit_after>/**
 * Eye sensor has a maximum range and senses walls
 * @class
 * @constructor {object} input
 */
var Eye = function(input) {
  console.log('Creating eye', input);
  this.name             = (input && input.name)?      input.name:'';
  this.angle            = (input && input.angle)?     input.angle:0;
  this.fov              = (input && input.fov)?       input.fov:(15*Math.PI/180); // Default 15deg.
  this.max_range        = (input && input.max_range)? input.max_range:4;
  this.sensed_proximity = this.max_range;
  this.sensed_type      = -1; // what does the eye see?

  // Extra sensor dealing exclusively with goals.
  // TODO: Refactor to binary, "nose". Could be interesting with forward turns.
  this.goal_range       = (input && input.goal_range)?input.goal_range:10;
  this.sensed_goal      = this.goal_range;

  // Watch for updates, syncing framerate to sensors.
  this.updated = false;

  // TODO: Watch for goal updates also?
};

// RatSLAM Goal log for rewarding distance.
var Goal = function(id, dis, rad) {
  //console.log('Creating goal', id, dis, rad);
  this.id  = id;
  this.dis = dis;
  this.rad = rad;
};

/**
 * A single agent
 * @class Agent
 * @param {Ros} ros
 * @param {array} eyes
 * @param {array} actions
 * @param {object} agent_opts
 * @param {object} brain_opts
 */
var Agent = function(ros, eyes, actions, agent_opts, brain_opts) {
  if (!ros) throw new Exception('ROS instance must be passed to RatSLAM.');
  this.ros = ros;

  // Initialise eyes from config passed in.
  this.eyes = [];
  for (var i = 0; i < eyes.length; i++) {
    if (typeof(eyes[i].angle) !== "undefined" && typeof(eyes[i].fov) !== "undefined") {
      this.eyes.push(new Eye(eyes[i]));
    }
  }

  this.actions = (actions)?actions:[
    // Default actions.
    [1.0,0.0],
    [1.0,-3.0],
    [1.0,3.0],
    [0.0,-4.0],
    [0.0,4.0]
  ];

  // Remember RatSLAM goals for rewarding distance.
  this.goals = [];

  var num_inputs      = agent_opts.num_inputs;
  var num_actions     = agent_opts.num_actions;
  var temporal_window = brain_opts.temporal_window; // amount of temporal memory. 0 = agent lives in-the-moment :)
  var network_size = num_inputs*temporal_window + num_actions*temporal_window + num_inputs;

  // the value function network computes a value of taking any of the possible actions
  // given an input state. Here we specify one explicitly the hard way
  // but user could also equivalently instead use opt.hidden_layer_sizes = [20,20]
  // to just insert simple relu hidden layers.
  var layer_defs = [];
  layer_defs.push({type: 'input', out_sx: 1, out_sy: 1, out_depth: network_size});
  layer_defs.push({type: 'fc', num_neurons: 80, activation: 'relu'});
  //layer_defs.push({type:'dropout', drop_prob:0.2}); // Uncertainty approximation.
  layer_defs.push({type: 'fc', num_neurons: 80, activation: 'relu'});
  layer_defs.push({type: 'regression', num_neurons: num_actions});

  brain_opts.layer_defs = layer_defs;

  var brain = new deepqlearn.Brain(num_inputs, num_actions, brain_opts); // woohoo

  this.brain = brain;

  this.reward_bonus = 0.0;
  this.digestion_signal = 0.0;

  // outputs on world
  this.linX = 0.0; // Linear velocity forwards.
  this.angZ = 0.0; // Angular velocity rotation.
};

Agent.prototype = {
  /**
   * Add RatSLAM goal to memory for later reward
   * @method addGoal
   * @param {integer} id
   * @param {float} dis
   * @param {float} rad
   */
  addGoal: function(id, dis, rad) {
    // TODO: If Goal ID has changed, publish an "eat" reward?
    // Does it only change when eaten? Not really, it changes when shortcut too.
    this.goals.push(new Goal(id, dis, rad));
    // Truncate log, only need a few to gauge getting closer.
    this.goals = this.goals.slice(-2);
  },
  forward: function() {
    // in forward pass the agent simply behaves in the environment
    // create input to brain
    // TODO: Signal when loop closure, so net can correlate difference from goal eyes improvement.
    var num_eyes = this.eyes.length;
    var input_array = new Array(num_eyes * 1); // FIXME: ``* 1` Shouldn't it be the size?
    for (var i=0; i<num_eyes; i++) {
      var e = this.eyes[i];
      input_array[i*4] = 1.0; // Wall
      input_array[i*4+1] = 1.0; // Type 1
      input_array[i*4+2] = 1.0; // Type 2
      input_array[i*4+3] = Math.min(e.goal_range, e.sensed_goal)/e.goal_range; // Goal, normalize to [0,1]
      if (e.sensed_type !== -1) {
        // sensed_type is 0 for wall, 1 for food and 2 for poison.
        // lets do a 1-of-k encoding into the input array
        input_array[i*4 + e.sensed_type] = e.sensed_proximity/e.max_range; // normalize to [0,1]
        /*
        console.log('input0: ' + input_array[i*4]);
        console.log('input1: ' + input_array[i*4+1]);
        console.log('input2: ' + input_array[i*4+2]);
        console.log('input3: ' + input_array[i*4+3]);
        */
      }
    }

    // get action from brain
    var actionix = this.brain.forward(input_array);
    var action = this.actions[actionix];
    this.actionix = actionix; //back this up

    // demultiplex into behavior variables
    this.linX = action[0]*1;
    this.angZ = action[1]*1;
  },
  backward: function() {
    // in backward pass agent learns.
    // compute reward
    var proximity_reward = 0.0;
    var num_eyes = this.eyes.length;
    for (var i=0; i<num_eyes; i++) {
      var e = this.eyes[i];
      // agents dont like to see walls, especially up close
      proximity_reward += e.sensed_type === 0 ? e.sensed_proximity/e.max_range : 1.0;

      // Debug log, goal spotting, shown in sync with brain.
      //if (e.sensed_goal < e.goal_range) console.log('a', i, e.sensed_goal, Math.min(e.goal_range, e.sensed_goal)/e.goal_range);
    }
    proximity_reward = proximity_reward/(num_eyes-2); // FIXME: Hack to remove 2 extra eyes.
    proximity_reward = Math.min(1.0, proximity_reward);

    // agents like to be near goals
    var goal_factor = 0.0;
    var goal_reward = 0.0;

    if (this.goals[this.goals.length-1] && this.goals[this.goals.length-1].dis > 0) {
      // FIXME: Only if below max, so there is a reading to correlate with?
      goal_factor = Math.max(0.0, Math.min(1.0, 1/this.goals[this.goals.length-1].dis));
      // FIXME: Redundant, forward bonus and goal view implies this.
      //goal_reward = 0.1 * goal_factor * proximity_reward;
    }

    // agents like to go straight forward, more-so towards goals. // FIXME: "near" goals... side-effect, max towards goal.
    var forward_reward = 0.0;
    // TODO: Reward fast turns only once epsilon drops?
    if ((this.actionix === 0 || this.actionix === 1 || this.actionix === 2) && proximity_reward > 0.85) { // 0.75 a little too close for corners. Rewards stuck wheel.
      // TODO: Closer to goal = more forward. Instead of eye reward, stop goal reward when goal is behind?

      // Some forward reward, some forward goal reward.
      //forward_reward = (0.05 + (0.05 * goal_factor)) * proximity_reward;
      forward_reward = 0.05 * proximity_reward;
      // Half as much for forward turns.
      //if (this.actionix === 1 || this.actionix === 2) {
      //  forward_reward = forward_reward / 2;
      //}
    }

    // agents like to eat good things
    var digestion_reward = this.digestion_signal;
    this.digestion_signal = 0.0;

    var reward = proximity_reward + forward_reward + goal_reward + digestion_reward;

    // Log repeating actions.
    if (this.cnt > 4) {
      console.log(reward.toFixed(5), this.actionix, this.cnt, this.linX.toFixed(1), this.angZ.toFixed(1));
      console.log('rewards', forward_reward, goal_reward);
    }

    // Publish statistics to ROS topics.
    this.ros.pubTopic('/dqn/learning',   'std_msgs/Float32', this.ros.createStdMsg('float', (this.brain.learning)?1:0));
    this.ros.pubTopic('/dqn/reward',     'std_msgs/Float32', this.ros.createStdMsg('float', reward));
    //this.ros.pubTopic('/dqn/action',   'std_msgs/Float32', this.ros.createStdMsg('float', this.actionix));
    this.ros.pubTopic('/dqn/epsilon',    'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.epsilon));
    //this.ros.pubTopic('/dqn/avg_loss', 'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.average_loss_window.get_average()));
    this.ros.pubTopic('/dqn/avg_reward', 'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.average_reward_window.get_average()));
    //this.ros.pubTopic('/dqn/age',      'std_msgs/Float32', this.ros.createStdMsg('float', this.brain.age));

    // pass to brain for learning
    this.brain.backward(reward);
  }
};

module.exports = Agent;
<|endoftext|>


<commit_before>import Vue from 'vue'

import TouchPan from '../../directives/TouchPan.js'

import slot from '../../utils/slot.js'

export default Vue.extend({
  name: 'QSplitter',

  directives: {
    TouchPan
  },

  props: {
    value: {
      type: Number,
      required: true
    },
    horizontal: Boolean,

    limits: {
      type: Array,
      default: () => [10, 90],
      validator: v => {
        if (v.length !== 2) return false
        if (typeof v[0] !== 'number' || typeof v[1] !== 'number') return false
        return v[0] >= 0 && v[0] <= v[1] && v[1] <= 100
      }
    },

    disable: Boolean,

    dark: Boolean,

    beforeClass: [Array, String, Object],
    afterClass: [Array, String, Object],

    separatorClass: [Array, String, Object],
    separatorStyle: [Array, String, Object]
  },

  watch: {
    value: {
      immediate: true,
      handler (v) {
        this.__normalize(v, this.limits)
      }
    },

    limits: {
      deep: true,
      handler (v) {
        this.__normalize(this.value, v)
      }
    }
  },

  computed: {
    classes () {
      return (this.horizontal ? 'column' : 'row') +
        ` q-splitter--${this.horizontal ? 'horizontal' : 'vertical'}` +
        ` q-splitter--${this.disable === true ? 'disabled' : 'workable'}` +
        (this.dark === true ? ' q-splitter--dark' : '')
    },

    prop () {
      return this.horizontal ? 'height' : 'width'
    },

    beforeStyle () {
      return { [this.prop]: this.value + '%' }
    },

    afterStyle () {
      return { [this.prop]: (100 - this.value) + '%' }
    }
  },

  methods: {
    __pan (evt) {
      if (evt.isFirst) {
        this.__size = this.$el.getBoundingClientRect()[this.prop]
        this.__value = this.value
        this.__dir = this.horizontal ? 'up' : 'left'
        this.__rtlDir = this.horizontal ? 1 : (this.$q.lang.rtl === true ? -1 : 1)

        this.$el.classList.add('q-splitter--active')
        return
      }

      if (evt.isFinal) {
        if (this.__normalized !== this.value) {
          this.$emit('input', this.__normalized)
        }

        this.$el.classList.remove('q-splitter--active')
        return
      }

      const val = this.__value +
        this.__rtlDir *
        (evt.direction === this.__dir ? -100 : 100) *
        evt.distance[this.horizontal ? 'y' : 'x'] / this.__size

      this.__normalized = Math.min(this.limits[1], Math.max(this.limits[0], val))
      this.$refs.before.style[this.prop] = this.__normalized + '%'
      this.$refs.after.style[this.prop] = (100 - this.__normalized) + '%'
    },

    __normalize (val, limits) {
      if (val < limits[0]) {
        this.$emit('input', limits[0])
      }
      else if (val > limits[1]) {
        this.$emit('input', limits[1])
      }
    }
  },

  render (h) {
    return h('div', {
      staticClass: 'q-splitter no-wrap',
      class: this.classes,
      on: this.$listeners
    }, [
      h('div', {
        ref: 'before',
        staticClass: 'q-splitter__panel q-splitter__before',
        style: this.beforeStyle,
        class: this.beforeClass
      }, slot(this, 'before')),

      h('div', {
        staticClass: 'q-splitter__separator',
        style: this.separatorStyle,
        class: this.separatorClass
      }, this.disable === false ? [
        h('div', {
          staticClass: 'absolute-full',
          directives: [{
            name: 'touch-pan',
            value: this.__pan,
            modifiers: {
              horizontal: !this.horizontal,
              vertical: this.horizontal,
              prevent: true,
              mouse: true,
              mouseAllDir: true,
              mousePrevent: true
            }
          }]
        })
      ] : null),

      h('div', {
        ref: 'after',
        staticClass: 'q-splitter__panel q-splitter__after',
        style: this.afterStyle,
        class: this.afterClass
      }, slot(this, 'after'))
    ].concat(slot(this, 'default')))
  }
})
<commit_msg>fix(QSplitter): QSplitter warning and incorrect functionality if textarea is inside #3495<commit_after>import Vue from 'vue'

import TouchPan from '../../directives/TouchPan.js'

import slot from '../../utils/slot.js'
import { stop } from '../../utils/event.js'

export default Vue.extend({
  name: 'QSplitter',

  directives: {
    TouchPan
  },

  props: {
    value: {
      type: Number,
      required: true
    },
    horizontal: Boolean,

    limits: {
      type: Array,
      default: () => [10, 90],
      validator: v => {
        if (v.length !== 2) return false
        if (typeof v[0] !== 'number' || typeof v[1] !== 'number') return false
        return v[0] >= 0 && v[0] <= v[1] && v[1] <= 100
      }
    },

    disable: Boolean,

    dark: Boolean,

    beforeClass: [Array, String, Object],
    afterClass: [Array, String, Object],

    separatorClass: [Array, String, Object],
    separatorStyle: [Array, String, Object]
  },

  watch: {
    value: {
      immediate: true,
      handler (v) {
        this.__normalize(v, this.limits)
      }
    },

    limits: {
      deep: true,
      handler (v) {
        this.__normalize(this.value, v)
      }
    }
  },

  computed: {
    classes () {
      return (this.horizontal ? 'column' : 'row') +
        ` q-splitter--${this.horizontal ? 'horizontal' : 'vertical'}` +
        ` q-splitter--${this.disable === true ? 'disabled' : 'workable'}` +
        (this.dark === true ? ' q-splitter--dark' : '')
    },

    prop () {
      return this.horizontal ? 'height' : 'width'
    },

    beforeStyle () {
      return { [this.prop]: this.value + '%' }
    },

    afterStyle () {
      return { [this.prop]: (100 - this.value) + '%' }
    }
  },

  methods: {
    __pan (evt) {
      if (evt.isFirst) {
        this.__size = this.$el.getBoundingClientRect()[this.prop]
        this.__value = this.value
        this.__dir = this.horizontal ? 'up' : 'left'
        this.__rtlDir = this.horizontal ? 1 : (this.$q.lang.rtl === true ? -1 : 1)

        this.$el.classList.add('q-splitter--active')
        return
      }

      if (evt.isFinal) {
        if (this.__normalized !== this.value) {
          this.$emit('input', this.__normalized)
        }

        this.$el.classList.remove('q-splitter--active')
        return
      }

      const val = this.__value +
        this.__rtlDir *
        (evt.direction === this.__dir ? -100 : 100) *
        evt.distance[this.horizontal ? 'y' : 'x'] / this.__size

      this.__normalized = Math.min(this.limits[1], Math.max(this.limits[0], val))
      this.$refs.before.style[this.prop] = this.__normalized + '%'
      this.$refs.after.style[this.prop] = (100 - this.__normalized) + '%'
    },

    __normalize (val, limits) {
      if (val < limits[0]) {
        this.$emit('input', limits[0])
      }
      else if (val > limits[1]) {
        this.$emit('input', limits[1])
      }
    }
  },

  render (h) {
    return h('div', {
      staticClass: 'q-splitter no-wrap',
      class: this.classes,
      on: this.$listeners
    }, [
      h('div', {
        ref: 'before',
        staticClass: 'q-splitter__panel q-splitter__before',
        style: this.beforeStyle,
        class: this.beforeClass,
        on: { input: stop }
      }, slot(this, 'before')),

      h('div', {
        staticClass: 'q-splitter__separator',
        style: this.separatorStyle,
        class: this.separatorClass
      }, this.disable === false ? [
        h('div', {
          staticClass: 'absolute-full',
          directives: [{
            name: 'touch-pan',
            value: this.__pan,
            modifiers: {
              horizontal: !this.horizontal,
              vertical: this.horizontal,
              prevent: true,
              mouse: true,
              mouseAllDir: true,
              mousePrevent: true
            }
          }]
        })
      ] : null),

      h('div', {
        ref: 'after',
        staticClass: 'q-splitter__panel q-splitter__after',
        style: this.afterStyle,
        class: this.afterClass,
        on: { input: stop }
      }, slot(this, 'after'))
    ].concat(slot(this, 'default')))
  }
})
<|endoftext|>


<commit_before>
  aight.version = "2.1.0";

  var nav = null,
      version = 0,
      ie = false;
  if (typeof navigator === "object") {
    nav = navigator.appName;
    version = navigator.appVersion;
    ie = (nav == 'Microsoft Internet Explorer');
    if (ie) {
      var match = navigator.userAgent.match(/MSIE ([0-9]{1,}[\.0-9]{0,})/);
      version = match ? parseFloat(match[1]) : 0;
    }
  }

  aight.browser = {
    name: nav,
    ie:   ie ? version : false,
    ie9:  ie && (version >= 9 && version <= 10),
    ie8:  ie && (version >= 8 && version <= 9),
    ie7:  ie && (version >= 7 && version <= 8),
    ie6:  ie && (version >= 6 && version <= 7)
  };

  if (typeof window !== "object") return;

  window.aight = aight;

  function aliasInterface(ns, expectedName, nonStandardName) {
    if (ns[nonStandardName] && !ns[expectedName]) {
      ns[expectedName] = ns[nonStandardName];
      return true;
    }
    return false;
  }

  function shimPropertyAccessor(klass, property, shim) {
    if (klass && !(property in klass.prototype)) {
      return shim(klass.prototype, property);
    }
  }

  aliasInterface(window, "HTMLCommentElement", "Comment");
  aliasInterface(window, "HTMLDocument", "Document");
<commit_msg>fix ==, version comparisons, kill old fn<commit_after>
  aight.version = "2.1.0";

  var nav = null,
      version = 0,
      ie = false;
  if (typeof navigator === "object") {
    nav = navigator.appName;
    version = navigator.appVersion;
    ie = (nav === "Microsoft Internet Explorer");
    if (ie) {
      var match = navigator.userAgent.match(/MSIE ([0-9]{1,}[\.0-9]{0,})/);
      version = match ? parseFloat(match[1]) : 0;
    }
  }

  aight.browser = {
    name: nav,
    ie:   ie ? version : false,
    ie9:  ie && (version >= 9 && version < 10),
    ie8:  ie && (version >= 8 && version < 9),
    ie7:  ie && (version >= 7 && version < 8),
    ie6:  ie && (version >= 6 && version < 7)
  };

  if (typeof window !== "object") return;

  window.aight = aight;

  function aliasInterface(ns, expectedName, nonStandardName) {
    if (ns[nonStandardName] && !ns[expectedName]) {
      ns[expectedName] = ns[nonStandardName];
      return true;
    }
    return false;
  }

  aliasInterface(window, "HTMLCommentElement", "Comment");
  aliasInterface(window, "HTMLDocument", "Document");
<|endoftext|>


<commit_before>var keystone = require('keystone'),
	Types = keystone.Field.Types;

// Create model. Additional options allow menu name to be used what auto-generating URLs
var Source = new keystone.List('Source', {
	autokey: { path: 'key', from: 'source', unique: true },
	map: { name: 'source' }
});

// Create fields
Source.add({
	source: { type: Types.Text, label: 'source', required: true, initial: true },
	isMediaOutlet: { type: Types.Boolean, label: 'media outlet', initial: true },
	isActiveMediaOutlet: { type: Types.Boolean, label: 'active media outlet', dependsOn: { isMediaOutlet: true }, initial: true },
	mediaFrequency: { type: Types.Text, label: 'media frequency', dependsOn: { isMediaOutlet: true }, initial: true },
	mediaType: { type: Types.Select, options: 'print, web, TV, radio', label: 'media type', dependsOn: { isMediaOutlet: true }, initial: true }

});

// Define default columns in the admin interface and register the model
Source.defaultColumns = 'source';
Source.register();<commit_msg>#23 | update source model with media type dropdown and more clear language<commit_after>const keystone = require( 'keystone' );
const Types = keystone.Field.Types;

// Create model. Additional options allow menu name to be used what auto-generating URLs
let Source = new keystone.List( 'Source', {
	autokey: { path: 'key', from: 'source', unique: true },
	map: { name: 'source' }
});

// Create fields
Source.add({
	source: { type: Types.Text, label: 'source', required: true, initial: true },
	type: { type: Types.Select, options: 'event, media', label: 'source type', required: true, initial: true },
	isActive: { type: Types.Boolean, label: 'is source active', initial: true },
	mediaFrequency: { type: Types.Text, label: 'media frequency', dependsOn: { type: 'media' }, initial: true },
	mediaType: { type: Types.Select, options: 'print, web, TV, radio', label: 'media type', dependsOn: { type: 'media' }, initial: true }

});

Source.relationship( { ref: 'Media Feature', refPath: 'source', path: 'media-features', label: 'media features' } );

// Define default columns in the admin interface and register the model
Source.defaultColumns = 'source, type, isActive';
Source.register();<|endoftext|>


<commit_before>var express = require( "express" );
var MysqlStore = require( "connect-mysql" )( express );
var routes = require( "./web/routes" );

exports.createServer = createServer;

function createServer( app ) {
	var web = express();

	// Expose DEBT instance to Express app
	web.set( "debt", app );

	// Set all Express options
	Object.keys( app.options.express ).forEach(function( prop ) {
		web.set( prop, app.options.express[ prop ] );
	});

	// Expose application settings to templates via `app`
	web.locals.app = app.options;

	// Expose auth
	web.authorize = app.auth.authorize.bind( app.auth );

	// web.use( express.favicon( "..." ) );
	web.use( express.logger() );
	web.use( express.compress() );
	web.use( express.bodyParser() );
	web.use( express.responseTime() );
	web.use( express.query() );

	// Enable sessions
	web.use( express.cookieParser() );
	web.use( express.session({
		key: "debt.sid",
		secret: app.options.cookieSecret,
		store: new MysqlStore({
			client: app.database.connection
		})
	}));

	// Expose the logged in user to the request and response
	web.use( app.auth.exposeUser.bind( app.auth ) );

	routes( web );

	return web;
}
<commit_msg>Web: Explicitly accept JSON and URL encoded requests<commit_after>var express = require( "express" );
var MysqlStore = require( "connect-mysql" )( express );
var routes = require( "./web/routes" );

exports.createServer = createServer;

function createServer( app ) {
	var web = express();

	// Expose DEBT instance to Express app
	web.set( "debt", app );

	// Set all Express options
	Object.keys( app.options.express ).forEach(function( prop ) {
		web.set( prop, app.options.express[ prop ] );
	});

	// Expose application settings to templates via `app`
	web.locals.app = app.options;

	// Expose auth
	web.authorize = app.auth.authorize.bind( app.auth );

	// web.use( express.favicon( "..." ) );
	web.use( express.logger() );
	web.use( express.compress() );
	web.use( express.json() );
	web.use( express.urlencoded() );
	web.use( express.responseTime() );
	web.use( express.query() );

	// Enable sessions
	web.use( express.cookieParser() );
	web.use( express.session({
		key: "debt.sid",
		secret: app.options.cookieSecret,
		store: new MysqlStore({
			client: app.database.connection
		})
	}));

	// Expose the logged in user to the request and response
	web.use( app.auth.exposeUser.bind( app.auth ) );

	routes( web );

	return web;
}
<|endoftext|>


<commit_before>/*
 * electron-builder
 * https://github.com/loopline-systems/electron-builder
 *
 * Licensed under the MIT license.
 */

'use strict';

var childProcess    = require( 'child_process' );
var os              = require( 'os' );
var writeConfigFile = require( './helper/writeConfigFile' );
var path            = require( 'path' );
var fs              = require( 'fs-extra' );

/**
 * Prototype for the windows installer builder
 * @type {Object}
 */
var WinBuilder = {
  /**
   * Build the installer for windows
   *
   * @param  {Object}   options  options
   * @param  {Function} callback callback
   */
  build : function( options, callback ) {
    options.log( '- Starting creation of installer for ´' + options.platform );

    var nsiTemplate = options.config.win.nsiTemplate || path.join( __dirname, '..', 'templates/installer.nsi.tpl' );

    var configFilePath = writeConfigFile( nsiTemplate, {
      appPath         : _windowsify( options.appPath ),
      name            : options.config.win.title,
      version         : options.config.win.version,
      fileAssociation : options.config.win.fileAssociation,
      out             : _windowsify( options.out )
    });

    _copyAssetsToTmpFolder( options );

    var makensis = childProcess.spawn(
      'makensis',
      [ configFilePath ],
      {
        env : process.env
      }
    );

    makensis.stdout.on( 'data', function ( data ) {
      options.log( 'makensis: ' + data );
    } );

    makensis.stderr.on( 'data', function ( data ) {
      options.log( 'makensis error: ' + data );
    } );

    makensis.on( 'error', function ( err ) {
      if ( err.code === 'ENOENT' ) {
        options.log( '- makensis not found.' );
        options.log( '  Please install "nullsoft scriptable install system"' );
        switch( process.platform ) {
          case 'darwin':
            options.log( '  brew install wine makensis' );
            break;
          case 'win32':
            options.log( '  http://nsis.sourceforge.net/Download' );
            break;
          case 'linux':
            options.log( '  $ add-apt-repository ppa:ubuntu-wine/ppa -y' );
            options.log( '  $ apt-get update' );
            options.log( '  $ apt-get install wine nsis -y' );
            break;
        }
        options.log();
        return callback( new Error( 'makensis failed' ) );
      }
      return callback( err );
    } );

    makensis.on( 'close', function ( code ) {
      options.log( 'Finished makensis with code ' + code );

      if ( code > 0 ) {
        return callback( new Error( 'makensis failed' ) );
      }

      callback();
    } );

    if ( makensis.error || makensis.status > 0 ) {
      return callback( makensis.error || new Error( 'makensis failed' ) );
    }
  }
};

/**
 * Copy files to tmp dir to
 * make them accessible for installer.nsi
 */
function _copyAssetsToTmpFolder( options ) {
  var tmpDir         = os.tmpDir();

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'nsProcess.nsh' ),
    path.join( tmpDir, 'nsProcess.nsh' )
  );

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'FileAssociation.nsh' ),
    path.join( tmpDir, 'FileAssociation.nsh' )
  );

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'nsProcess.dll' ),
    path.join( tmpDir, 'nsProcess.dll' )
  );

  fs.copySync(
    path.resolve( options.config.win.icon ),
    path.join( tmpDir, 'icon.ico' )
  );
}

/**
 * Replace / with \ to write file
 * also, ensure drive character is upper case when run on windows platforms
 * paths for windows
 *
 * @param  {String} path path
 * @return {String}      windows path
 */
function _windowsify( p ) {
  p = path.win32.normalize( p );
  p = p[ 0 ].toUpperCase() + p.substr( 1 );
  return p;
}

/**
 * Expose factory function
 *
 * @type {Object}
 */
module.exports = {
  init : function() {
    return Object.create( WinBuilder );
  }
};
<commit_msg>[test] add an option to define a file association on Windows<commit_after>/*
 * electron-builder
 * https://github.com/loopline-systems/electron-builder
 *
 * Licensed under the MIT license.
 */

'use strict';

var childProcess    = require( 'child_process' );
var os              = require( 'os' );
var writeConfigFile = require( './helper/writeConfigFile' );
var path            = require( 'path' );
var fs              = require( 'fs-extra' );

/**
 * Prototype for the windows installer builder
 * @type {Object}
 */
var WinBuilder = {
  /**
   * Build the installer for windows
   *
   * @param  {Object}   options  options
   * @param  {Function} callback callback
   */
  build : function( options, callback ) {
    options.log( '- Starting creation of installer for ´' + options.platform );

    var nsiTemplate = options.config.win.nsiTemplate || path.join( __dirname, '..', 'templates/installer.nsi.tpl' );

    var configFilePath = writeConfigFile( nsiTemplate, {
      appPath         : _windowsify( options.appPath ),
      name            : options.config.win.title,
      version         : options.config.win.version,
      fileAssociation : options.config.win.fileAssociation,
      out             : _windowsify( options.out )
    } );

    _copyAssetsToTmpFolder( options );

    var makensis = childProcess.spawn(
      'makensis',
      [ configFilePath ],
      {
        env : process.env
      }
    );

    makensis.stdout.on( 'data', function ( data ) {
      options.log( 'makensis: ' + data );
    } );

    makensis.stderr.on( 'data', function ( data ) {
      options.log( 'makensis error: ' + data );
    } );

    makensis.on( 'error', function ( err ) {
      if ( err.code === 'ENOENT' ) {
        options.log( '- makensis not found.' );
        options.log( '  Please install "nullsoft scriptable install system"' );
        switch( process.platform ) {
          case 'darwin':
            options.log( '  brew install wine makensis' );
            break;
          case 'win32':
            options.log( '  http://nsis.sourceforge.net/Download' );
            break;
          case 'linux':
            options.log( '  $ add-apt-repository ppa:ubuntu-wine/ppa -y' );
            options.log( '  $ apt-get update' );
            options.log( '  $ apt-get install wine nsis -y' );
            break;
        }
        options.log();
        return callback( new Error( 'makensis failed' ) );
      }
      return callback( err );
    } );

    makensis.on( 'close', function ( code ) {
      options.log( 'Finished makensis with code ' + code );

      if ( code > 0 ) {
        return callback( new Error( 'makensis failed' ) );
      }

      callback();
    } );

    if ( makensis.error || makensis.status > 0 ) {
      return callback( makensis.error || new Error( 'makensis failed' ) );
    }
  }
};

/**
 * Copy files to tmp dir to
 * make them accessible for installer.nsi
 */
function _copyAssetsToTmpFolder( options ) {
  var tmpDir         = os.tmpDir();

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'nsProcess.nsh' ),
    path.join( tmpDir, 'nsProcess.nsh' )
  );

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'FileAssociation.nsh' ),
    path.join( tmpDir, 'FileAssociation.nsh' )
  );

  fs.copySync(
    path.join( __dirname, '..', 'assets', 'win', 'nsProcess.dll' ),
    path.join( tmpDir, 'nsProcess.dll' )
  );

  fs.copySync(
    path.resolve( options.config.win.icon ),
    path.join( tmpDir, 'icon.ico' )
  );
}

/**
 * Replace / with \ to write file
 * also, ensure drive character is upper case when run on windows platforms
 * paths for windows
 *
 * @param  {String} path path
 * @return {String}      windows path
 */
function _windowsify( p ) {
  p = path.win32.normalize( p );
  p = p[ 0 ].toUpperCase() + p.substr( 1 );
  return p;
}

/**
 * Expose factory function
 *
 * @type {Object}
 */
module.exports = {
  init : function() {
    return Object.create( WinBuilder );
  }
};
<|endoftext|>


<commit_before>"use strict";

// Node.js https module
if (typeof process === 'object' && typeof process.versions === 'object' && process.versions.node) {
  var nodeRequire = require; // Prevent mine.js from seeing this require
  module.exports = nodeRequire('./xhr-node.js');
}

// Browser XHR
else {
  module.exports = function (root, accessToken) {
    var timeout = 2000;
    return request;

    function request(method, url, body, callback) {
      if (typeof body === "function" && callback === undefined) {
        callback = body;
        body = undefined;
      }
      url = url.replace(":root", root);
      if (!callback) return request.bind(this, accessToken, method, url, body);
      var done = false;
      var json;
      var xhr = new XMLHttpRequest();
      xhr.timeout = timeout;
      xhr.open(method, 'https://api.github.com' + url, true);
      xhr.setRequestHeader("Authorization", "token " + accessToken);
      if (body) {
        try { json = JSON.stringify(body); }
        catch (err) { return callback(err); }
      }
      xhr.ontimeout = onTimeout;
      xhr.onreadystatechange = onReadyStateChange;
      xhr.send(json);

      function onReadyStateChange() {
        if (done) return;
        if (xhr.readyState !== 4) return;
        // Give onTimeout a chance to run first if that's the reason status is 0.
        if (!xhr.status) return setTimeout(onReadyStateChange, 0);
        done = true;
        var response = {message:xhr.responseText};
        if (xhr.responseText){
          try { response = JSON.parse(xhr.responseText); }
          catch (err) {}
        }
        return callback(null, xhr, response);
      }

      function onTimeout() {
        if (done) return;
        if (timeout < 8000) {
          timeout *= 2;
          return request(method, url, body, callback);
        }
        done = true;
        callback(new Error("Timeout requesting " + url));
      }
    }
  };
}<commit_msg>Fix to work with atom-shell<commit_after>"use strict";

var isNode = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node;
if (isNode) {
  try { require('https'); }
  catch (err) { isNode = false; }
}

// Node.js https module
if (isNode) {
  var nodeRequire = require; // Prevent mine.js from seeing this require
  module.exports = nodeRequire('./xhr-node.js');
}

// Browser XHR
else {
  module.exports = function (root, accessToken) {
    var timeout = 2000;
    return request;

    function request(method, url, body, callback) {
      if (typeof body === "function" && callback === undefined) {
        callback = body;
        body = undefined;
      }
      url = url.replace(":root", root);
      if (!callback) return request.bind(this, accessToken, method, url, body);
      var done = false;
      var json;
      var xhr = new XMLHttpRequest();
      xhr.timeout = timeout;
      xhr.open(method, 'https://api.github.com' + url, true);
      xhr.setRequestHeader("Authorization", "token " + accessToken);
      if (body) {
        try { json = JSON.stringify(body); }
        catch (err) { return callback(err); }
      }
      xhr.ontimeout = onTimeout;
      xhr.onreadystatechange = onReadyStateChange;
      xhr.send(json);

      function onReadyStateChange() {
        if (done) return;
        if (xhr.readyState !== 4) return;
        // Give onTimeout a chance to run first if that's the reason status is 0.
        if (!xhr.status) return setTimeout(onReadyStateChange, 0);
        done = true;
        var response = {message:xhr.responseText};
        if (xhr.responseText){
          try { response = JSON.parse(xhr.responseText); }
          catch (err) {}
        }
        return callback(null, xhr, response);
      }

      function onTimeout() {
        if (done) return;
        if (timeout < 8000) {
          timeout *= 2;
          return request(method, url, body, callback);
        }
        done = true;
        callback(new Error("Timeout requesting " + url));
      }
    }
  };
}<|endoftext|>


<commit_before>/**
 * Created by sghaida on 5/11/2017.
 */

var mongo   = require('mongoose'),
    Schema  = mongo.Schema;

var applicationSchema = new Schema({
    name: String,
    description: String,
    imageUrl: {type: String, default: ''},
    url: String,
    creationDate: {type: Date, default: Date.now},
    exposedTo: {
        sites: [String],
        countries: [String]
    },
    owner: { type: Schema.Types.ObjectId, ref: 'Department'},
    author: { type: Schema.Types.ObjectId, ref: 'User'},

    tags : [{
        type: Schema.Types.ObjectId,
        ref: 'Tag'
    }],
    isOnline: {type: Boolean, default: true}
});

module.exports = mongo.model('Application', applicationSchema);<commit_msg>add requirePermission attribute<commit_after>/**
 * Created by sghaida on 5/11/2017.
 */

var mongo   = require('mongoose'),
    Schema  = mongo.Schema;

var applicationSchema = new Schema({
    name: String,
    description: String,
    imageUrl: {type: String, default: ''},
    url: String,
    creationDate: {type: Date, default: Date.now},
    exposedTo: {
        sites: [String],
        countries: [String]
    },
    owner: { type: Schema.Types.ObjectId, ref: 'Department'},
    author: { type: Schema.Types.ObjectId, ref: 'User'},

    tags : [{
        type: Schema.Types.ObjectId,
        ref: 'Tag'
    }],
    requirePermission: {type: Boolean, default: false},
    isOnline: {type: Boolean, default: true}
});

module.exports = mongo.model('Application', applicationSchema);<|endoftext|>


<commit_before>var _ = require('underscore');
var cp = require('child_process');
var path = require('path');
var spawn = require('child_process').spawn;
var util = require('util');

function findCmd(name) {
    var paths = process.env['PATH'].split(':');
    var pathLen = paths.length;
    for (var i = 0; i < pathLen; i++) {
        var sp = path.resolve(paths[i]);
        var fname = path.normalize(path.join(sp, name));
        if (path.existsSync(fname)) {
            return fname;
        }
    }

    return null;
}

var zfsBin = findCmd('zfs');
function zfs(args, callback) {
    cp.execFile(zfsBin, args, {}, function (err, stdout, stderr) {
        if (callback && typeof callback === 'function') {
            if (err) {
                callback(err);
            } else if (stderr.length > 0) {
                callback(new Error(stderr.toString().trim()));
            } else {
                callback(null, stdout);
            }
        }
    });
}

function ZFS(info) {
    "use strict";

    var obj = Object.create({});
    if (typeof info === 'string') {
        info = info.split(/\s+/);
    }

    if (info.length !== 5) {
        return null;
    }

    obj.name = info[0];
    obj.used = parseInt(info[1], 10);
    if (info[2] !== '-') { // Snapshots don't have 'avail' field.
        obj.avail = parseInt(info[2], 10);
    }
    obj.refer = parseInt(info[3], 10);
    obj.mountpoint = info[4];

    Object.freeze(obj);
    return obj;
}

function Property(info) {
    "use strict";

    var obj = Object.create({});
    if (typeof info === 'string') {
        info = info.split(/\s+/, 4);
    }

    if (info.length !== 4) {
        return null;
    }

    obj.name = info[0];
    obj.property = info[1];
    obj.value = info[2];
    obj.source = info[3];

    Object.freeze(obj);
    return obj;
}

function list(opts, cb) {
    "use strict";

    if (typeof opts === 'function') {
        cb = opts;
        opts = undefined;
    }

    var params = ['list', '-pH'];

    if (opts && opts.type) {
        params.push('-t');
        params.push(opts.type);
    }

    zfs(params, function (err, stdout) {
        if (cb && typeof cb == 'function') {
            var lines = _.compact(stdout.split('\n'));
            var list = lines.map(function (x) { return new ZFS(x); });
            cb(err, list);
        }
    });
}

function get(opts, cb) {
    "use strict";

    var params = [ 'get', '-pH' ];
    if (opts.source) {
        params.push('-s');
        params.push(opts.source);
    }
    params.push(opts.property);

    zfs(params, function (err, stdout) {
        if (cb && typeof cb == 'function') {
            var lines = _.compact(stdout.split('\n'));
            var list = lines.map(function (x) { return new Property(x); });
            cb(err, list);
        }
    });
}

exports.get = get;
exports.list = list;
<commit_msg>Add zfs snapshot and zfs destroy.<commit_after>var _ = require('underscore');
var cp = require('child_process');
var path = require('path');
var spawn = require('child_process').spawn;
var util = require('util');

function findCmd(name) {
    var paths = process.env['PATH'].split(':');
    var pathLen = paths.length;
    for (var i = 0; i < pathLen; i++) {
        var sp = path.resolve(paths[i]);
        var fname = path.normalize(path.join(sp, name));
        if (path.existsSync(fname)) {
            return fname;
        }
    }

    return null;
}

var zfsBin = findCmd('zfs');
function zfs(args, callback) {
    cp.execFile(zfsBin, args, {}, function (err, stdout, stderr) {
        if (callback && typeof callback === 'function') {
            if (err) {
                callback(err);
            } else if (stderr.length > 0) {
                callback(new Error(stderr.toString().trim()));
            } else {
                callback(null, stdout);
            }
        }
    });
}

function ZFS(info) {
    "use strict";

    var obj = Object.create({});
    if (typeof info === 'string') {
        info = info.split(/\s+/);
    }

    if (info.length !== 5) {
        return null;
    }

    obj.name = info[0];
    obj.used = parseInt(info[1], 10);
    if (info[2] !== '-') { // Snapshots don't have 'avail' field.
        obj.avail = parseInt(info[2], 10);
    }
    obj.refer = parseInt(info[3], 10);
    obj.mountpoint = info[4];

    Object.freeze(obj);
    return obj;
}

function Property(info) {
    "use strict";

    var obj = Object.create({});
    if (typeof info === 'string') {
        info = info.split(/\s+/, 4);
    }

    if (info.length !== 4) {
        return null;
    }

    obj.name = info[0];
    obj.property = info[1];
    obj.value = info[2];
    obj.source = info[3];

    Object.freeze(obj);
    return obj;
}

function list(opts, cb) {
    "use strict";

    if (typeof opts === 'function') {
        cb = opts;
        opts = undefined;
    }

    var params = ['list', '-pH'];

    if (opts && opts.type) {
        params.push('-t');
        params.push(opts.type);
    }

    zfs(params, function (err, stdout) {
        if (cb && typeof cb == 'function') {
            var lines = _.compact(stdout.split('\n'));
            var list = lines.map(function (x) { return new ZFS(x); });
            cb(err, list);
        }
    });
}

function get(opts, cb) {
    "use strict";

    var params = [ 'get', '-pH' ];
    if (opts.source) {
        params.push('-s');
        params.push(opts.source);
    }
    params.push(opts.property);

    zfs(params, function (err, stdout) {
        if (cb && typeof cb == 'function') {
            var lines = _.compact(stdout.split('\n'));
            var list = lines.map(function (x) { return new Property(x); });
            cb(err, list);
        }
    });
}

function destroy(opts, cb) {
    "use strict";

    var params = [ 'destroy' ];
    if (opts.recursive) {
        params.push('-r');
    }
    params.push(opts.name);

    zfs(params, cb);
}

function snapshot(opts, cb) {
    "use strict";

    var params = [ 'snapshot' ];
    if (opts.recursive) {
        params.push('-r');
    }
    params.push(opts.dataset + '@' + opts.name);

    zfs(params, cb);
}

exports.get = get;
exports.list = list;
exports.destroy = destroy;
exports.snapshot = snapshot;
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
import { createBucket } from './lib/grid/createBucket';
import { createOnAfterUpload } from './lib/fsHooks/createOnAfterUpload';
import { createInterceptDownload } from './lib/fsHooks/createInterceptDownload';
import { createOnAfterRemove } from './lib/fsHooks/createOnAfterRemove';

let attachmentBucket;
if (Meteor.isServer) {
  attachmentBucket = createBucket('attachments');
}

const insertActivity = (fileObj, activityType) =>
  Activities.insert({
    userId: fileObj.userId,
    type: 'card',
    activityType,
    attachmentId: fileObj._id,
    // this preserves the name so that notifications can be meaningful after
    // this file is removed
    attachmentName: fileObj.name,
    boardId: fileObj.meta.boardId,
    cardId: fileObj.meta.cardId,
    listId: fileObj.meta.listId,
    swimlaneId: fileObj.meta.swimlaneId,
  });

// XXX Enforce a schema for the Attachments FilesCollection
// see: https://github.com/VeliovGroup/Meteor-Files/wiki/Schema

Attachments = new FilesCollection({
  debug: false, // Change to `true` for debugging
  collectionName: 'attachments',
  allowClientCode: true,
  onAfterUpload: function onAfterUpload(fileRef) {
    createOnAfterUpload(attachmentBucket).call(this, fileRef);
    // If the attachment doesn't have a source field
    // or its source is different than import
    if (!fileRef.meta.source || fileRef.meta.source !== 'import') {
      // Add activity about adding the attachment
      insertActivity(fileRef, 'addAttachment');
    }
  },
  interceptDownload: createInterceptDownload(attachmentBucket),
  onAfterRemove: function onAfterRemove(files) {
    createOnAfterRemove(attachmentBucket).call(this, files);
    files.forEach(fileObj => {
      insertActivity(fileObj, 'deleteAttachment');
    });
  },
  // We authorize the attachment download either:
  // - if the board is public, everyone (even unconnected) can download it
  // - if the board is private, only board members can download it
  protected(fileObj) {
    const board = Boards.findOne(fileObj.meta.boardId);
    if (board.isPublic()) {
      return true;
    }
    return board.hasMember(this.userId);
  },
});

if (Meteor.isServer) {
  Attachments.allow({
    insert(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    update(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    remove(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    fetch: ['meta'],
  });

  Meteor.startup(() => {
    Attachments.collection._ensureIndex({ cardId: 1 });
  });
}

export default Attachments;
<commit_msg>Fix: access denied on second load<commit_after>import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
import { createBucket } from './lib/grid/createBucket';
import { createOnAfterUpload } from './lib/fsHooks/createOnAfterUpload';
import { createInterceptDownload } from './lib/fsHooks/createInterceptDownload';
import { createOnAfterRemove } from './lib/fsHooks/createOnAfterRemove';

let attachmentBucket;
if (Meteor.isServer) {
  attachmentBucket = createBucket('attachments');
}

const insertActivity = (fileObj, activityType) =>
  Activities.insert({
    userId: fileObj.userId,
    type: 'card',
    activityType,
    attachmentId: fileObj._id,
    // this preserves the name so that notifications can be meaningful after
    // this file is removed
    attachmentName: fileObj.name,
    boardId: fileObj.meta.boardId,
    cardId: fileObj.meta.cardId,
    listId: fileObj.meta.listId,
    swimlaneId: fileObj.meta.swimlaneId,
  });

// XXX Enforce a schema for the Attachments FilesCollection
// see: https://github.com/VeliovGroup/Meteor-Files/wiki/Schema

Attachments = new FilesCollection({
  debug: false, // Change to `true` for debugging
  collectionName: 'attachments',
  allowClientCode: true,
  onAfterUpload: function onAfterUpload(fileRef) {
    createOnAfterUpload(attachmentBucket).call(this, fileRef);
    // If the attachment doesn't have a source field
    // or its source is different than import
    if (!fileRef.meta.source || fileRef.meta.source !== 'import') {
      // Add activity about adding the attachment
      insertActivity(fileRef, 'addAttachment');
    }
  },
  interceptDownload: createInterceptDownload(attachmentBucket),
  onAfterRemove: function onAfterRemove(files) {
    createOnAfterRemove(attachmentBucket).call(this, files);
    files.forEach(fileObj => {
      insertActivity(fileObj, 'deleteAttachment');
    });
  },
  // We authorize the attachment download either:
  // - if the board is public, everyone (even unconnected) can download it
  // - if the board is private, only board members can download it
  protected(fileObj) {
    const board = Boards.findOne(fileObj.meta.boardId);
    if (board.isPublic()) {
      return true;
    }
    return board.hasMember(fileObj.userId);
  },
});

if (Meteor.isServer) {
  Attachments.allow({
    insert(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    update(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    remove(userId, fileObj) {
      return allowIsBoardMember(userId, Boards.findOne(fileObj.boardId));
    },
    fetch: ['meta'],
  });

  Meteor.startup(() => {
    Attachments.collection._ensureIndex({ cardId: 1 });
  });
}

export default Attachments;
<|endoftext|>


<commit_before>/* ------------
 * Fill select element with birdnames + draw charts for first bird
 * ------------
*/

$(document).ready(
    function() {
	bird_results = getAllBirdInfo("");
	bird_results.done(function(data) {
	    var birds = data.rows;
	    var len = birds.length;
	    globalData.bird_data = birds;
	    len = birds.length;
	    for (var i=0; i<len; i++) {
		bird = birds[i];
		$("#birdselector").append("<option value=\"" + i + "\">" + bird.bird_name + "</option>");
	    }
	    drawCharts("colony_dist", birds[0]);
	});
    }
);

/* ------------
 * Inititate global stuff
 * ------------
*/

var globalData = {}

/* ------------
 * set some globals
 * These calendars need to be initialized before running the create functions.
 * That's because the create functions are also used for updating the calendars
 * so they start with cal.destroy(), but therefore, cal should already be
 * a calendar.
 * ------------
*/

var hourcal = new CalHeatMap();
hourcal.init({itemSelector: "#hour-month-heatmap"});

/* ------------
 * Charting functions
 * ------------
*/

function drawCharts (data_type, bird_data) {
    insertBirdData(bird_data);
    if (data_type === "colony_dist") {
	var hour_month_cartodbdata = fetchTrackingData_byDayHour(bird_data.device_info_serial, "point("+ bird_data.colony_longitude + "%20" + bird_data.colony_latitude + ")", "");
    } else if (data_type === "dist_trav") {
	var hour_month_cartodbdata = fetchTravelledDist_byHour(bird_data.device_info_serial, "");
    }
    hour_month_cartodbdata.done(function (data) {
	globalData.hour_month_heatdata = toCalHeatmap(data);
	globalData.hour_month_linedata = toNvd3Linedata(data);
	var values = globalData.hour_month_linedata[0].values;
	var min_timestamp = values[0].x;
	var max_timestamp = values[values.length - 1].x;
	var startdate = new Date(min_timestamp);
	drawHourCalHeatmap("#hour-month-heatmap", startdate, globalData.hour_month_heatdata, bird_data);
	drawHourLineChart(globalData.hour_month_linedata, min_timestamp, max_timestamp);
    });

    if (data_type === "colony_dist") {
	var day_month_cartodbdata = fetchTrackingData_byDay(bird_data.device_info_serial, "point("+ bird_data.colony_longitude + "%20" + bird_data.colony_latitude + ")", "");
    } else if (data_type === "dist_trav") {
	var day_month_cartodbdata = fetchTravelledDist_byDay(bird_data.device_info_serial, "");
    }
    setBirdsLayer(window.map, bird_data.device_info_serial, "", "");

}

function drawHourCalHeatmap(element, startdate, data, bird_data) {
    hourcal = hourcal.destroy(function () {
	hourcal = new CalHeatMap();
	hourcal.init({
	    onComplete: addEvents,
	    domain: "month",
	    subDomain: "x_hour",
	    start: startdate,
	    cellSize: 6.5,
	    rowLimit: 24,
	    verticalOrientation: false,
	    itemSelector: element,
	    domainMargin: 10,
	    itemName: ['kilometer', 'kilometers'],
	    displayLegend: true,
	    legend: [0.05, 1, 5, 10, 50, 100],
	    legendColors: {
		range: ["#C2F2C3", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#005a32", "#000000"],
		empty: "#CFCFCF"
	    },
	    legendCellSize: 20,
	    legendCellPadding: 4,
	    data: data,
	    onClick: function(date, distance) {
		start_of_that_day = new Date(date.getFullYear(), date.getMonth(), date.getDate());
		clicked_date_timestamp = start_of_that_day.getTime();
		next_date_timestamp = clicked_date_timestamp + (24 * 60 * 60 * 1000);
		next_date = new Date(next_date_timestamp);
		drawHourLineChart(globalData.hour_month_linedata, clicked_date_timestamp, next_date_timestamp);
		setBirdsLayer(window.map, bird_data.device_info_serial, start_of_that_day, next_date);
	    }
	});
    });
}

function drawHourLineChart(data, focus_min, focus_max) {
    nv.addGraph(function() {
	chart = nv.models.lineWithFocusChart();

	chart.xAxis
	    .axisLabel('Time')
	    .tickFormat(function(d) {return d3.time.format('%d/%m %Hh')(new Date(d)); });

	chart.x2Axis
	    .axisLabel('Time')
	    .ticks(20)
	    .tickFormat(function(d) {   return d3.time.format('%d/%m')(new Date(d)); });

        chart.yAxis
	    .axisLabel('Distance from nest (km)')
	    .tickFormat(d3.format('.02f'))

        chart.y2Axis
	    .axisLabel('Distance from nest (km)')
	    .tickFormat(d3.format('.02f'))

	chart.showLegend(false);
	chart.brushExtent([focus_min, focus_max]);

	d3.select('#linechart svg')
	    .datum(data)
	    .transition().duration(500)
	    .call(chart);

        nv.utils.windowResize(function() { d3.select('#linechart svg').call(chart) });

	return chart;
    });
}

// ----- End of Charting functions ----- //

/* ------------
 * Add events to buttons
 * ------------
*/

// Go button
$("#gobutton").on("click", function(event) {
    globalData.datatype = "total_dist";
    var bird_index = $("#birdselector").val();
    var bird = globalData.bird_data[bird_index];
    var data_type = $("#dataselector").val();
    drawCharts(data_type, bird);
});

// Calendar navigation
$("#cal-next").on("click", function(event) {
    hourcal.next();
});

$("#cal-previous").on("click", function(event) {
    hourcal.previous();
});

// Calendar tabs
$("#show-dist-col").on("click", function(event) {
    $(this).attr("class", "tab active");
    $("#show-dist-trav").attr("class", "tab inactive");
});

$("#show-dist-trav").on("click", function(event) {
    $(this).attr("class", "tab active");
    $("#show-dist-col").attr("class", "tab inactive");
});

/* ------------
 * Add events to cal-heatmap graph-label
 * This function is called as call-back function
 * after the calendar data is loaded.
 * ------------
*/
function addEvents() {
    var bird_index = $("#birdselector").val();
    var bird = globalData.bird_data[bird_index];
    $(".graph-label").on("click", function(event) {
	// get class of parent DOM object. This should be "graph-domain m_A y_B"
	// Where A and B are month and year respectively.
	var pclasses = $(this).parent().attr("class").split(" ");
	var month_nr = parseInt(pclasses[1].split("_")[1]);
	var year_nr = parseInt(pclasses[2].split("_")[1]);
	var month_index = month_nr - 1;
	if (month_nr == 12) {
	    var next_month_index = 0;
	    var next_year = year_nr + 1;
	}
        else {
	    var next_month_index = month_index + 1;
	    var next_year = year_nr;
	}
	var startdate = new Date(year_nr, month_index, 1);
	var enddate = new Date(next_year, next_month_index, 1);
	drawHourLineChart(globalData.hour_month_linedata, startdate.getTime(), enddate.getTime());
	setBirdsLayer(window.map, bird.device_info_serial, startdate, enddate);
    });
}

/* ------------
 * Insert bird data in web page
 * ------------
*/
function insertBirdData(bird_data) {
    $("#name-text").text(" " + bird_data.bird_name);
    $("#species-text").text(" " + bird_data.scientific_name);
    $("#sex-text").text(" " + bird_data.sex);
    $("#max-speed-text").text("");
    $("#max-dist-col").text("");
    var speed_result = fetchMaximumSpeed(bird_data.device_info_serial)
    speed_result.done(function (data) {
	$("#max-speed-text").text(" " + data.rows[0].round + " km/h");
    });
    var dist_result = getMaxDistance(bird_data.device_info_serial, bird_data.colony_longitude, bird_data.colony_latitude);
    dist_result.done(function (data) {
	$("#max-dist-col").text(" " + Math.round(data.rows[0].max / 10) / 100 + " km");
    });
}
<commit_msg>Refactor drawMap function<commit_after>/* ------------
 * Fill select element with birdnames + draw charts for first bird
 * ------------
*/

$(document).ready(
    function() {
	bird_results = getAllBirdInfo("");
	bird_results.done(function(data) {
	    var birds = data.rows;
	    var len = birds.length;
	    globalData.bird_data = birds;
	    len = birds.length;
	    for (var i=0; i<len; i++) {
		bird = birds[i];
		$("#birdselector").append("<option value=\"" + i + "\">" + bird.bird_name + "</option>");
	    }
	    drawMapAndCharts("colony_dist", birds[0]);
	});
    }
);

/* ------------
 * Inititate global stuff
 * ------------
*/

var globalData = {}

/* ------------
 * set some globals
 * These calendars need to be initialized before running the create functions.
 * That's because the create functions are also used for updating the calendars
 * so they start with cal.destroy(), but therefore, cal should already be
 * a calendar.
 * ------------
*/

var hourcal = new CalHeatMap();
hourcal.init({itemSelector: "#hour-month-heatmap"});

/* ------------
 * Charting functions
 * ------------
*/

function drawMapAndCharts(data_type, bird_data) {
    drawCharts(data_type, bird_data);
    setBirdsLayer(window.map, bird_data.device_info_serial, "", "");
}

function drawCharts (data_type, bird_data) {
    insertBirdData(bird_data);
    if (data_type === "colony_dist") {
	var hour_month_cartodbdata = fetchTrackingData_byDayHour(bird_data.device_info_serial, "point("+ bird_data.colony_longitude + "%20" + bird_data.colony_latitude + ")", "");
    } else if (data_type === "dist_trav") {
	var hour_month_cartodbdata = fetchTravelledDist_byHour(bird_data.device_info_serial, "");
    }
    hour_month_cartodbdata.done(function (data) {
	globalData.hour_month_heatdata = toCalHeatmap(data);
	globalData.hour_month_linedata = toNvd3Linedata(data);
	var values = globalData.hour_month_linedata[0].values;
	var min_timestamp = values[0].x;
	var max_timestamp = values[values.length - 1].x;
	var startdate = new Date(min_timestamp);
	drawHourCalHeatmap("#hour-month-heatmap", startdate, globalData.hour_month_heatdata, bird_data);
	drawHourLineChart(globalData.hour_month_linedata, min_timestamp, max_timestamp);
    });
}

function drawHourCalHeatmap(element, startdate, data, bird_data) {
    hourcal = hourcal.destroy(function () {
	hourcal = new CalHeatMap();
	hourcal.init({
	    onComplete: addEvents,
	    domain: "month",
	    subDomain: "x_hour",
	    start: startdate,
	    cellSize: 6.5,
	    rowLimit: 24,
	    verticalOrientation: false,
	    itemSelector: element,
	    domainMargin: 10,
	    itemName: ['kilometer', 'kilometers'],
	    displayLegend: true,
	    legend: [0.05, 1, 5, 10, 50, 100],
	    legendColors: {
		range: ["#C2F2C3", "#a1d99b", "#74c476", "#41ab5d", "#238b45", "#005a32", "#000000"],
		empty: "#CFCFCF"
	    },
	    legendCellSize: 20,
	    legendCellPadding: 4,
	    data: data,
	    onClick: function(date, distance) {
		start_of_that_day = new Date(date.getFullYear(), date.getMonth(), date.getDate());
		clicked_date_timestamp = start_of_that_day.getTime();
		next_date_timestamp = clicked_date_timestamp + (24 * 60 * 60 * 1000);
		next_date = new Date(next_date_timestamp);
		drawHourLineChart(globalData.hour_month_linedata, clicked_date_timestamp, next_date_timestamp);
		setBirdsLayer(window.map, bird_data.device_info_serial, start_of_that_day, next_date);
	    }
	});
    });
}

function drawHourLineChart(data, focus_min, focus_max) {
    nv.addGraph(function() {
	chart = nv.models.lineWithFocusChart();

	chart.xAxis
	    .axisLabel('Time')
	    .tickFormat(function(d) {return d3.time.format('%d/%m %Hh')(new Date(d)); });

	chart.x2Axis
	    .axisLabel('Time')
	    .ticks(20)
	    .tickFormat(function(d) {   return d3.time.format('%d/%m')(new Date(d)); });

        chart.yAxis
	    .axisLabel('Distance from nest (km)')
	    .tickFormat(d3.format('.02f'))

        chart.y2Axis
	    .axisLabel('Distance from nest (km)')
	    .tickFormat(d3.format('.02f'))

	chart.showLegend(false);
	chart.brushExtent([focus_min, focus_max]);

	d3.select('#linechart svg')
	    .datum(data)
	    .transition().duration(500)
	    .call(chart);

        nv.utils.windowResize(function() { d3.select('#linechart svg').call(chart) });

	return chart;
    });
}

// ----- End of Charting functions ----- //

/* ------------
 * Add events to buttons
 * ------------
*/

// Go button
$("#gobutton").on("click", function(event) {
    globalData.datatype = "total_dist";
    var bird_index = $("#birdselector").val();
    var bird = globalData.bird_data[bird_index];
    var data_type = $("#dataselector").val();
    drawMapAndCharts(data_type, bird);
});

// Calendar navigation
$("#cal-next").on("click", function(event) {
    hourcal.next();
});

$("#cal-previous").on("click", function(event) {
    hourcal.previous();
});

// Calendar tabs
$("#show-dist-col").on("click", function(event) {
    $(this).attr("class", "tab active");
    $("#show-dist-trav").attr("class", "tab inactive");
});

$("#show-dist-trav").on("click", function(event) {
    $(this).attr("class", "tab active");
    $("#show-dist-col").attr("class", "tab inactive");
});

/* ------------
 * Add events to cal-heatmap graph-label
 * This function is called as call-back function
 * after the calendar data is loaded.
 * ------------
*/
function addEvents() {
    var bird_index = $("#birdselector").val();
    var bird = globalData.bird_data[bird_index];
    $(".graph-label").on("click", function(event) {
	// get class of parent DOM object. This should be "graph-domain m_A y_B"
	// Where A and B are month and year respectively.
	var pclasses = $(this).parent().attr("class").split(" ");
	var month_nr = parseInt(pclasses[1].split("_")[1]);
	var year_nr = parseInt(pclasses[2].split("_")[1]);
	var month_index = month_nr - 1;
	if (month_nr == 12) {
	    var next_month_index = 0;
	    var next_year = year_nr + 1;
	}
        else {
	    var next_month_index = month_index + 1;
	    var next_year = year_nr;
	}
	var startdate = new Date(year_nr, month_index, 1);
	var enddate = new Date(next_year, next_month_index, 1);
	drawHourLineChart(globalData.hour_month_linedata, startdate.getTime(), enddate.getTime());
	setBirdsLayer(window.map, bird.device_info_serial, startdate, enddate);
    });
}

/* ------------
 * Insert bird data in web page
 * ------------
*/
function insertBirdData(bird_data) {
    $("#name-text").text(" " + bird_data.bird_name);
    $("#species-text").text(" " + bird_data.scientific_name);
    $("#sex-text").text(" " + bird_data.sex);
    $("#max-speed-text").text("");
    $("#max-dist-col").text("");
    var speed_result = fetchMaximumSpeed(bird_data.device_info_serial)
    speed_result.done(function (data) {
	$("#max-speed-text").text(" " + data.rows[0].round + " km/h");
    });
    var dist_result = getMaxDistance(bird_data.device_info_serial, bird_data.colony_longitude, bird_data.colony_latitude);
    dist_result.done(function (data) {
	$("#max-dist-col").text(" " + Math.round(data.rows[0].max / 10) / 100 + " km");
    });
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import styled from 'styled-components';
import classnames from 'classnames';

class Tile extends Component {
  constructor(props) {
    super(props);

    this.onClick = this.onClick.bind(this);
  }

  static propTypes = {
    tileId: PropTypes.number.isRequired,
    width: PropTypes.number.isRequired,
    height: PropTypes.number.isRequired,
    left: PropTypes.number.isRequired,
    top: PropTypes.number.isRequired,
    number: PropTypes.number,
    onClick: PropTypes.func,
    correct: PropTypes.bool,
    visible: PropTypes.bool,
  };

  static defaultProps = {
    number: 0,
    correct: false,
    visible: true,
  };

  render() {
    const { className, number, visible } = this.props;
    const classes = classnames({
      [className]: true,
      'tile-invisible': !visible,
    });

    return (

        {number}

    );
  }

  onClick() {
    this.props.onClick(this.props);
  }
}

export default styled(Tile)`
  border: 1px solid #FFD1AA;
  position: absolute;
  width: ${props => props.width}px;
  height: ${props => props.height}px;
  left: ${props => props.left}px;
  top: ${props => props.top}px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  background-color: ${props => props.correct ? '#226666' : '#D4726A'};
  transition-property: top, left, background-color;
  transition-duration: .300s;
  transition-timing-function: ease-in;

  .tile-number {
    color: #FFD1AA;
    font-weight: 400;
    fontSize: 1.8em;
    user-select: none;
  }

  &.tile-invisible {
    display: none;
  }
`;

export const propTypes = Tile.propTypes;
<commit_msg>Use translate and reduce animation duration<commit_after>import React, { Component, PropTypes } from 'react';
import styled from 'styled-components';
import classnames from 'classnames';

class Tile extends Component {
  constructor(props) {
    super(props);

    this.onClick = this.onClick.bind(this);
  }

  static propTypes = {
    tileId: PropTypes.number.isRequired,
    width: PropTypes.number.isRequired,
    height: PropTypes.number.isRequired,
    left: PropTypes.number.isRequired,
    top: PropTypes.number.isRequired,
    number: PropTypes.number,
    onClick: PropTypes.func,
    correct: PropTypes.bool,
    visible: PropTypes.bool,
  };

  static defaultProps = {
    number: 0,
    correct: false,
    visible: true,
  };

  render() {
    const { className, number, visible } = this.props;
    const classes = classnames({
      [className]: true,
      'tile-invisible': !visible,
    });

    return (

        {number}

    );
  }

  onClick() {
    this.props.onClick(this.props);
  }
}

export default styled(Tile)`
  border: 1px solid #FFD1AA;
  position: absolute;
  width: ${props => props.width}px;
  height: ${props => props.height}px;
  transform: translateX(${props =>
  props.top}px) translateY(${props => props.left}px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  background-color: ${props => props.correct ? '#226666' : '#D4726A'};
  transition-property: transform, background-color;
  transition-duration: .150s;
  transition-timing-function: ease-in-out;

  .tile-number {
    color: #FFD1AA;
    font-weight: 400;
    fontSize: 1.8em;
    user-select: none;
  }

  &.tile-invisible {
    display: none;
  }
`;

export const propTypes = Tile.propTypes;
<|endoftext|>


<commit_before>var map;
var ajaxRequest;
var plotlist;
var plotlayers=[];

function initmap() {
	// set up the map
	map = new L.Map('map');

	// create the tile layer with correct attribution
	var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
	var osmAttrib='Map data © OpenStreetMap contributors';
	var osm = new L.TileLayer(osmUrl, {minZoom: 8, maxZoom: 12, attribution: osmAttrib});
    var localTileLayerUrl = 'http://127.0.0.1:8000/tiles/201108/{z}/{x}/{y}.png';
	var localTileLayer = new L.TileLayer(localTileLayerUrl, {minZoom: 8, maxZoom: 12, attribution: "safecast.org"});

	// start the map in Fukushima
	map.setView(new L.LatLng(37.435793, 140.735437), 10);
	map.addLayer(osm);
	map.addLayer(localTileLayer);
}<commit_msg>setting localTileLayerUrl to to static ip for testing.<commit_after>var map;
var ajaxRequest;
var plotlist;
var plotlayers=[];

function initmap() {
	// set up the map
	map = new L.Map('map');

	// create the tile layer with correct attribution
	var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
	var osmAttrib='Map data © OpenStreetMap contributors';
	var osm = new L.TileLayer(osmUrl, {minZoom: 8, maxZoom: 12, attribution: osmAttrib});
    var localTileLayerUrl = 'http://10.143.166.17:8000/tiles/201108/{z}/{x}/{y}.png';
	var localTileLayer = new L.TileLayer(localTileLayerUrl, {minZoom: 8, maxZoom: 12, attribution: "safecast.org"});

	// start the map in Fukushima
	map.setView(new L.LatLng(37.435793, 140.735437), 10);
	map.addLayer(osm);
	map.addLayer(localTileLayer);
}<|endoftext|>


<commit_before>(function () {
    var notifications = function (Events) {
        var notificationService = {};

        notificationService.isSupported = function () {
            if ("Notification" in window) {
                return true;
            } else {
                console.log("HTML5 notifications are not supported.");
                return false;
            }
        }

        notificationService.getPermissions = function () {
            if (!this.isSupported()) {
                return;
            }

            if (Notification.permission !== "granted") {
	        Notification.requestPermission(function (status) {
	            if (Notification.permission !== status) {
                        Notification.permission = status;
                    }
                });
            }
        }

        notificationService.showNotification = function (title, content) {
            if (!this.isSupported()) {
                return;
            }

            //using the 'tag' to avoid showing duplicate notifications
            var notification = new Notification(title, {'tag': title+content, 'body': content});
            notification.onclick = function () {
                window.focus();
                this.cancel();
                Events.record(currentUser, 'click', 'notification');
            };
        }

        return notificationService;
    }

    angular.module('redash.services')
        .factory('notifications', ['Events', notifications]);
})();
<commit_msg>add 'autoclose' to notifications (i.e. close after 3 seconds)<commit_after>(function () {
    var notifications = function (Events) {
        var notificationService = {};

        notificationService.isSupported = function () {
            if ("Notification" in window) {
                return true;
            } else {
                console.log("HTML5 notifications are not supported.");
                return false;
            }
        }

        notificationService.getPermissions = function () {
            if (!this.isSupported()) {
                return;
            }

            if (Notification.permission !== "granted") {
	        Notification.requestPermission(function (status) {
	            if (Notification.permission !== status) {
                        Notification.permission = status;
                    }
                });
            }
        }

        notificationService.showNotification = function (title, content) {
            if (!this.isSupported()) {
                return;
            }

            //using the 'tag' to avoid showing duplicate notifications
            var notification = new Notification(title, {'tag': title+content, 'body': content});
            setTimeout(function(){
                 notification.close();
                },3000);
            notification.onclick = function () {
                window.focus();
                this.cancel();
                Events.record(currentUser, 'click', 'notification');
            };
        }

        return notificationService;
    }

    angular.module('redash.services')
        .factory('notifications', ['Events', notifications]);
})();
<|endoftext|>


<commit_before>(function(module) {
	"use strict";

	var Vimeo = {},
		embed = '';

    embedUrl = /.+<\/a>/g;

	Vimeo.parse = function(data, callback) {
	    if (!data || !data.postData || !data.postData.content) {
            return callback(null, data);
        }
        if (data.postData.content.match(embedUrl)) {
            data.postData.content = data.postData.content.replace(embedUrl, embed);
        }
        callback(null, data);
    };

	module.exports = Vimeo;
}(module));
<commit_msg>Fix library.js<commit_after>(function(module) {
	"use strict";

	var Vimeo = {},
		embed = '';

    var embedUrl = /.+<\/a>/g;

	Vimeo.parse = function(data, callback) {
	    if (!data || !data.postData || !data.postData.content) {
            return callback(null, data);
        }
        if (data.postData.content.match(embedUrl)) {
            data.postData.content = data.postData.content.replace(embedUrl, embed);
        }
        callback(null, data);
    };

	module.exports = Vimeo;
}(module));
<|endoftext|>