<commit_before>/**
 * Created by khejing on 2015/6/30.
 */

var mqtt = require('mqtt');
var headless = require('headless');
var electronPath = require('electron-prebuilt');
var childProcess = require('child_process');
var portFinder = require('portfinder');
var ffmpeg = require('fluent-ffmpeg');
var moment = require('moment');
var m3u8 = require("m3u8");
var fs = require("fs");

var recordingTopic = "recording";
var mqttClientInstance = mqtt.connect("mqtt://localhost:1883", {clientId: recordingTopic});
mqttClientInstance.on('connect', function () {
    console.log("connect mqtt server success");
});
mqttClientInstance.on('error',function(error) {
    console.log("mqtt connect failed: ", error);
});
mqttClientInstance.subscribe(recordingTopic);

mqttClientInstance.on('message', function(messageTopic, data) {
    var msg = JSON.parse(data);
    var options = {
        display: {width: 1366, height: 768, depth: 24}
    };
    headless(options, function(err, xvfbChildProcess, servernum) {
        // childProcess is a ChildProcess, as returned from child_process.spawn()
        console.log('Xvfb running on server number', servernum);
        console.log('Xvfb pid', xvfbChildProcess.pid);
        console.log('err should be null', err);
        var displayOpt = ":"+servernum+".0";
        // spawn electron after xvfb has been started
        var electronChild = childProcess.spawn(electronPath, [__dirname+"/electron_app"], {env: {DISPLAY: displayOpt, TopicToSubscribe: data}});
        electronChild.stderr.on('data', function(data){
            process.stdout.write(data.toString());
        });
        electronChild.on("exit", function(){
            console.log("electron has been closed");
            xvfbChildProcess.exit();
        });
        portFinder.getPort(function (err, port) {
            console.log("got free port: "+port);
            function ffmpegLog(data){
                console.log(data);
            }
            function ffmpegOutput(command){
                command
                    .audioCodec("aac")
                    .videoCodec("libx264")
                    .outputOptions(["-pix_fmt yuv420p", "-crf 28", "-g 50", "-hls_time 10", "-threads 0", "-shortest"]);
            }
            var filenamePrefix = msg.teacherTopic+"-"+msg.type+"-"+moment().format("YYYYMMDDHHmmss");
            var duration = -1;
            var ffmpegCommand = ffmpeg({logger: {debug: ffmpegLog, info: ffmpegLog, warn: ffmpegLog, error: ffmpegLog}});
            ffmpegCommand
                .input("tcp://localhost:"+port+"?listen=1")
                .input(displayOpt)
                .inputFormat("x11grab")
                .inputFPS(25)
                .inputOptions("-video_size 1366x768")
                .output(filenamePrefix+"-desktop"+".m3u8")
                .size("1280x720")
                .preset(ffmpegOutput)
                .output(filenamePrefix+"-tablet"+".m3u8")
                .size("640x360")
                .preset(ffmpegOutput)
                .outputOptions(["-maxrate 1000K", "-bufsize 2000K"])
                .output(filenamePrefix+"-smartphone"+".m3u8")
                .size("480x320")
                .autopad()
                .preset(ffmpegOutput)
                .outputOptions(["-maxrate 500K", "-bufsize 1000K"])
                .on("start", function(command){console.log(command);})
                .on("codecData", function(data){
                    duration = data.duration;
                    console.log("got time: "+data.timemark);
                })
                .on("end", function(){
                    console.log("ffmpeg ended!!!");
                    var m3u8Content = m3u8.M3U.create();
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-desktop"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 2001000,
                        RESOLUTION: "1280x720"
                    });
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-tablet"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 1001000,
                        RESOLUTION: "640x360"
                    });
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-smartphone"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 510000,
                        RESOLUTION: "480x320"
                    });
                    fs.writeFile(filenamePrefix+".m3u8", m3u.toString(), null, function(err){
                        if(err === null){
                            mqttClientInstance.publish(msg.clientId, JSON.stringify({recording: "DurationAndURL", duration: duration, filenamePrefix: filenamePrefix}));
                        }
                    });
                })
                .run();
            mqttClientInstance.publish(msg.clientId, JSON.stringify({recording: "Port", port: port}));
        });
    });
});
/* when got exit signal, then exit
mqttClientInstance.end();
mqttClientInstance = null;
console.log("mqtt client has been destroyed");
*/<commit_msg>avoid useless send<commit_after>/**
 * Created by khejing on 2015/6/30.
 */

var mqtt = require('mqtt');
var headless = require('headless');
var electronPath = require('electron-prebuilt');
var childProcess = require('child_process');
var portFinder = require('portfinder');
var ffmpeg = require('fluent-ffmpeg');
var moment = require('moment');
var m3u8 = require("m3u8");
var fs = require("fs");

var recordingTopic = "recording";
var mqttClientInstance = mqtt.connect("mqtt://localhost:1883", {clientId: recordingTopic});
mqttClientInstance.on('connect', function () {
    console.log("connect mqtt server success");
});
mqttClientInstance.on('error',function(error) {
    console.log("mqtt connect failed: ", error);
});
mqttClientInstance.subscribe(recordingTopic);

mqttClientInstance.on('message', function(messageTopic, data) {
    var msg = JSON.parse(data);
    var options = {
        display: {width: 1366, height: 768, depth: 24}
    };
    headless(options, function(err, xvfbChildProcess, servernum) {
        // childProcess is a ChildProcess, as returned from child_process.spawn()
        console.log('Xvfb running on server number', servernum);
        console.log('Xvfb pid', xvfbChildProcess.pid);
        console.log('err should be null', err);
        var displayOpt = ":"+servernum+".0";
        // spawn electron after xvfb has been started
        var electronChild = childProcess.spawn(electronPath, [__dirname+"/electron_app"], {env: {DISPLAY: displayOpt, TopicToSubscribe: data}});
        electronChild.stderr.on('data', function(data){
            process.stdout.write(data.toString());
        });
        electronChild.on("exit", function(){
            console.log("electron has been closed");
            xvfbChildProcess.exit();
        });
        portFinder.getPort(function (err, port) {
            console.log("got free port: "+port);
            function ffmpegLog(data){
                console.log(data);
            }
            function ffmpegOutput(command){
                command
                    .audioCodec("aac")
                    .videoCodec("libx264")
                    .outputOptions(["-pix_fmt yuv420p", "-crf 28", "-g 50", "-hls_time 10", "-threads 0", "-shortest"]);
            }
            var filenamePrefix = msg.teacherTopic+"-"+msg.type+"-"+moment().format("YYYYMMDDHHmmss");
            var duration = -1;
            var ffmpegCommand = ffmpeg({logger: {debug: ffmpegLog, info: ffmpegLog, warn: ffmpegLog, error: ffmpegLog}});
            ffmpegCommand
                .input("tcp://localhost:"+port+"?listen=1")
                .input(displayOpt)
                .inputFormat("x11grab")
                .inputFPS(25)
                .inputOptions("-video_size 1366x768")
                .output(filenamePrefix+"-desktop"+".m3u8")
                .size("1280x720")
                .preset(ffmpegOutput)
                .output(filenamePrefix+"-tablet"+".m3u8")
                .size("640x360")
                .preset(ffmpegOutput)
                .outputOptions(["-maxrate 1000K", "-bufsize 2000K"])
                .output(filenamePrefix+"-smartphone"+".m3u8")
                .size("480x320")
                .autopad()
                .preset(ffmpegOutput)
                .outputOptions(["-maxrate 500K", "-bufsize 1000K"])
                .on("start", function(command){
					console.log(command);
					mqttClientInstance.publish(msg.clientId, JSON.stringify({recording: "Port", port: port}));
				})
                .on("codecData", function(data){
                    duration = data.duration;
                    console.log("got time: "+data.timemark);
                })
                .on("end", function(){
                    console.log("ffmpeg ended!!!");
                    var m3u8Content = m3u8.M3U.create();
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-desktop"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 2001000,
                        RESOLUTION: "1280x720"
                    });
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-tablet"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 1001000,
                        RESOLUTION: "640x360"
                    });
                    m3u.addStreamItem ({
                        uri: filenamePrefix+"-smartphone"+".m3u8",
                        "PROGRAM-ID": 1,
                        BANDWIDTH: 510000,
                        RESOLUTION: "480x320"
                    });
                    fs.writeFile(filenamePrefix+".m3u8", m3u.toString(), null, function(err){
                        if(err === null){
                            mqttClientInstance.publish(msg.clientId, JSON.stringify({recording: "DurationAndURL", duration: duration, filenamePrefix: filenamePrefix}));
                        }
                    });
                })
                .run();
        });
    });
});
/* when got exit signal, then exit
mqttClientInstance.end();
mqttClientInstance = null;
console.log("mqtt client has been destroyed");
*/<|endoftext|>


<commit_before>let RNVersionCheck;
if (process.env.RNVC_ENV === 'test') {
  RNVersionCheck = {
    country: 'ko',
    packageName: 'com.reactnative.versioncheck',
    currentBuildNumber: 1,
    currentVersion: '0.0.1',
  };
} else if (process.env.RNVC_EXPO) {
  const { Platform } = require('react-native');
  const { Constants, Util } = require('expo');

  const { manifest = {} } = Constants;
  const {
    version = null,
    android: {
      versionCode = null,
      package: androidPackageName = null
    } = {},
    ios: {
      bundleIdentifier = null,
      buildNumber = null
    } = {}
  } = manifest;

  RNVersionCheck = {
    currentVersion: version,
    country: (async () => await Util.getCurrentDeviceCountryAsync())(),
    currentBuildNumber: Platform.select({
      android: versionCode,
      ios: buildNumber
    }),
    packageName: Platform.select({
      android: androidPackageName,
      ios: bundleIdentifier
    })
  };
} else {
  RNVersionCheck = require('react-native').NativeModules.RNVersionCheck;
}

const COUNTRY = RNVersionCheck.country;
const PACKAGE_NAME = RNVersionCheck.packageName;
const CURRENT_BUILD_NUMBER = RNVersionCheck.currentBuildNumber;
const CURRENT_VERSION = RNVersionCheck.currentVersion;

export default {
  getCountry: () => COUNTRY,
  getPackageName: () => PACKAGE_NAME,
  getCurrentBuildNumber: () => CURRENT_BUILD_NUMBER,
  getCurrentVersion: () => CURRENT_VERSION,
};
<commit_msg>add getCountryAsync and warning message to expo<commit_after>let RNVersionCheck;
const useExpo = !!process.env.RNVC_EXPO;
if (process.env.RNVC_ENV === 'test') {
  RNVersionCheck = {
    country: 'ko',
    packageName: 'com.reactnative.versioncheck',
    currentBuildNumber: 1,
    currentVersion: '0.0.1',
  };
} else if (useExpo) {
  const { Platform } = require('react-native');
  const { Constants, Util } = require('expo');

  const { manifest = {} } = Constants;
  const {
    version = null,
    android: {
      versionCode = null,
      package: androidPackageName = null
    } = {},
    ios: {
      bundleIdentifier = null,
      buildNumber = null
    } = {}
  } = manifest;

  RNVersionCheck = {
    currentVersion: version,
    country: Util.getCurrentDeviceCountryAsync(),
    currentBuildNumber: Platform.select({
      android: versionCode,
      ios: buildNumber
    }),
    packageName: Platform.select({
      android: androidPackageName,
      ios: bundleIdentifier
    })
  };
} else {
  RNVersionCheck = require('react-native').NativeModules.RNVersionCheck;
}

const COUNTRY = RNVersionCheck.country;
const PACKAGE_NAME = RNVersionCheck.packageName;
const CURRENT_BUILD_NUMBER = RNVersionCheck.currentBuildNumber;
const CURRENT_VERSION = RNVersionCheck.currentVersion;

export default {
  getCountry: () => {
    if (useExpo) {
      console.warn('getCountry will return Promise<country>. Use "await getCountry() or await getCountryAsync()"');
    }
    return COUNTRY;
  },
  getCountryAsync: () => Promise.resolve(COUNTRY),
  getPackageName: () => PACKAGE_NAME,
  getCurrentBuildNumber: () => CURRENT_BUILD_NUMBER,
  getCurrentVersion: () => CURRENT_VERSION,
};
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const chalk = require('chalk');
const meow = require('meow');
const redent = require('redent');

const qgen = require('../');

const cli = meow(`
	${chalk.bold('Usage')}
		$ qgen <template name> [dest] [arguments] [options]

	${chalk.bold('Options')}
		-d, --directory <dir>	Templates directory (defaults to ./gqen-templates)
		-c, --config <path>	Path to the JSON config file (defaults to ./qgen.json)

	${chalk.bold('Examples')}
		$ qgen post ${chalk.dim('# generates the post template in the current folder')}
		$ qgen post ./pages ${chalk.dim('# generates the post template inside ./pages')}
		$ qgen post ./pages --page-title "Hello World" ${chalk.dim('# generates the post template in inside ./pages with data field pageTitle="Hello World" to the template rendering engine')}
`, {
	alias: {
		d: 'directory',
		c: 'config'
	}
});

/**
 * Displays list of available templates to stdout
 *
 * @param  {Object} options - options for qgen
 * @return {undefined}
 */
const listTemplates = options => {
	try {
		const templates = qgen(options).templates();
		if (Array.isArray(templates) && templates.length > 0) {
			console.log(redent(`	`, 2)); // For one line space
			console.log(redent(`	${chalk.bold('Available Templates')}`, 2));
			templates.forEach(template => {
				console.log(redent(`${template}`, 4));
			});
		}
	} catch (err) {
		console.log(redent(`	`, 2)); // For one line space
		console.error(err.message);
		process.exit(2);
	}
};

if (cli.input.length === 0) {
	console.log(cli.help);
	listTemplates(cli.flags);
} else {
	try {
		qgen(cli.flags).render(cli.input[0], cli.input[1]);
	} catch (err) {
		console.error(err.message);
		process.exit(1);
	}
}
<commit_msg>fix(cli): changes meow alias to work with latest meow 4.0<commit_after>#!/usr/bin/env node
'use strict';

const chalk = require('chalk');
const meow = require('meow');
const redent = require('redent');

const qgen = require('../');

const cli = meow(`
	${chalk.bold('Usage')}
		$ qgen <template name> [dest] [arguments] [options]

	${chalk.bold('Options')}
		-d, --directory <dir>	Templates directory (defaults to ./gqen-templates)
		-c, --config <path>	Path to the JSON config file (defaults to ./qgen.json)

	${chalk.bold('Examples')}
		$ qgen post ${chalk.dim('# generates the post template in the current folder')}
		$ qgen post ./pages ${chalk.dim('# generates the post template inside ./pages')}
		$ qgen post ./pages --page-title "Hello World" ${chalk.dim('# generates the post template in inside ./pages with data field pageTitle="Hello World" to the template rendering engine')}
`, {
	flags: {
		directory: {
			type: 'string',
			alias: 'd'
		},
		config: {
			alias: 'c'
		}
	}
});

/**
 * Displays list of available templates to stdout
 *
 * @param  {Object} options - options for qgen
 * @return {undefined}
 */
const listTemplates = options => {
	try {
		const templates = qgen(options).templates();
		if (Array.isArray(templates) && templates.length > 0) {
			console.log(redent(`	`, 2)); // For one line space
			console.log(redent(`	${chalk.bold('Available Templates')}`, 2));
			templates.forEach(template => {
				console.log(redent(`${template}`, 4));
			});
		}
	} catch (err) {
		console.log(redent(`	`, 2)); // For one line space
		console.error(err.message);
		process.exit(2);
	}
};

if (cli.input.length === 0) {
	console.log(cli.help);
	listTemplates(cli.flags);
} else {
	try {
		qgen(cli.flags).render(cli.input[0], cli.input[1]);
	} catch (err) {
		console.error(err.message);
		process.exit(1);
	}
}
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var fs = require('fs')
var _ = require('lodash')
var cwd = process.cwd()
var path = require('path')
var settings = require('../boot/settings')
var defaultDirectory = __dirname
var customDirectory = path.join(cwd, 'providers')

function loadProvider (dir, name, template) {
  return require(
    template
      ? path.join(dir, 'templates', name)
      : path.join(dir, name)
  )
}

// Hold on to whatever templates are found in order to avoid unecessary filesystem
// accesses
var templateCache = {}

/**
 * Load providers
 */
function loadProviders (dir, files) {
  files.forEach(function (file) {
    if (path.extname(file) === '.js' && file !== 'index.js') {
      var providerName = path.basename(file, '.js')

      try {
        // Grab the provider from the given directory
        var provider = loadProvider(dir, providerName)(settings)

        // Check if the provider extends any templates
        if (Array.isArray(provider.templates) && provider.templates.length) {
          var templates = []
          var templateName
          // Iterate through the provider's templates, load them, and store them
          // in memory in case we run into them again later
          for (var i = 0; i < provider.templates.length; i++) {
            templateName = provider.templates[i]
            if (!templateCache[templateName]) {
              try {
                templateCache[templateName] = loadProvider(
                  customDirectory, templateName, true
                )
              } catch (err) {
                templateCache[templateName] = loadProvider(
                  defaultDirectory, templateName, true
                )
              }
            }
            // If the provider has any specific configuration to pass to the template,
            // send it along with the settings to the function call
            if (provider.templateConfig && provider.templateConfig[templateName]) {
              templates.push(templateCache[templateName](
                settings, provider.templateConfig[templateName]
              ))
            } else {
              templates.push(templateCache[templateName](settings))
            }
          }
          // Go bottom-up through the list of generated template instances and
          // build up the base provider, then extend the base provider with the
          // top-most provider. Effectively, the result is a provider with the
          // proper order of inheritance for the templates it extends.
          var base = templates[templates.length - 1]
          for (i = templates.length - 2; i >= 0; i--) {
            _.extend(base, templates[i])
          }
          _.extend(base, provider)

          provider = base
        }

        provider.emailVerification = _.extend(
          { enable: !!settings.mailer, require: false },
          settings.emailVerification || {},
          (settings.providers[providerName] &&
          settings.providers[providerName].emailVerification) || {}
        )

        // override the default amr for the provider
        if (settings.providers[providerName]) {
          provider.amr = settings.providers[providerName].amr || provider.amr
        }

        // provider-specific refresh_userinfo setting
        if (settings.providers[providerName]) {
          provider.refresh_userinfo =
            settings.providers[providerName].refresh_userinfo
        }

        module.exports[providerName] = provider

      } catch (e) {
        throw new Error("Can't load " + providerName + ' provider.')
      }
    }
  })
}

try {
  loadProviders(defaultDirectory, fs.readdirSync(defaultDirectory))
} catch (e) {}

try {
  loadProviders(customDirectory, fs.readdirSync(customDirectory))
} catch (e) {}
<commit_msg>fix: Allow overriding amr and refresh_userinfo values with falsy values<commit_after>/**
 * Module dependencies
 */

var fs = require('fs')
var _ = require('lodash')
var cwd = process.cwd()
var path = require('path')
var settings = require('../boot/settings')
var defaultDirectory = __dirname
var customDirectory = path.join(cwd, 'providers')

function loadProvider (dir, name, template) {
  return require(
    template
      ? path.join(dir, 'templates', name)
      : path.join(dir, name)
  )
}

// Hold on to whatever templates are found in order to avoid unecessary filesystem
// accesses
var templateCache = {}

/**
 * Load providers
 */
function loadProviders (dir, files) {
  files.forEach(function (file) {
    if (path.extname(file) === '.js' && file !== 'index.js') {
      var providerName = path.basename(file, '.js')

      try {
        // Grab the provider from the given directory
        var provider = loadProvider(dir, providerName)(settings)

        // Check if the provider extends any templates
        if (Array.isArray(provider.templates) && provider.templates.length) {
          var templates = []
          var templateName
          // Iterate through the provider's templates, load them, and store them
          // in memory in case we run into them again later
          for (var i = 0; i < provider.templates.length; i++) {
            templateName = provider.templates[i]
            if (!templateCache[templateName]) {
              try {
                templateCache[templateName] = loadProvider(
                  customDirectory, templateName, true
                )
              } catch (err) {
                templateCache[templateName] = loadProvider(
                  defaultDirectory, templateName, true
                )
              }
            }
            // If the provider has any specific configuration to pass to the template,
            // send it along with the settings to the function call
            if (provider.templateConfig && provider.templateConfig[templateName]) {
              templates.push(templateCache[templateName](
                settings, provider.templateConfig[templateName]
              ))
            } else {
              templates.push(templateCache[templateName](settings))
            }
          }
          // Go bottom-up through the list of generated template instances and
          // build up the base provider, then extend the base provider with the
          // top-most provider. Effectively, the result is a provider with the
          // proper order of inheritance for the templates it extends.
          var base = templates[templates.length - 1]
          for (i = templates.length - 2; i >= 0; i--) {
            _.extend(base, templates[i])
          }
          _.extend(base, provider)

          provider = base
        }

        provider.emailVerification = _.extend(
          { enable: !!settings.mailer, require: false },
          settings.emailVerification || {},
          (settings.providers[providerName] &&
          settings.providers[providerName].emailVerification) || {}
        )

        // override the default amr for the provider
        if (typeof settings.providers[providerName] !== 'undefined') {
          provider.amr = settings.providers[providerName].amr || provider.amr
        }

        // provider-specific refresh_userinfo setting
        if (typeof settings.providers[providerName] !== 'undefined') {
          provider.refresh_userinfo =
            settings.providers[providerName].refresh_userinfo
        }

        module.exports[providerName] = provider

      } catch (e) {
        throw new Error("Can't load " + providerName + ' provider.')
      }
    }
  })
}

try {
  loadProviders(defaultDirectory, fs.readdirSync(defaultDirectory))
} catch (e) {}

try {
  loadProviders(customDirectory, fs.readdirSync(customDirectory))
} catch (e) {}
<|endoftext|>


<commit_before>require('babel-polyfill')
require('whatwg-fetch')

const roundDate = require('round-date')
const Vue = require('../../node_modules/vue/dist/vue.common.js')

// https://developers.google.com/chart/interactive/docs/release_notes#official-releases
google.charts.load('45.2', {'packages': ['corechart']})

function defaultChartOptions (meterType, vAxisMax) {
  const barColors = {
    electricity: '#FF851B',
    gas: '#0074D9'
  }
  const vAxisTitles = {
    electricity: 'Electricity consumption (W)',
    gas: 'Gas consumption (m³/h)'
  }
  return {
    width: 500,
    height: 200,
    title: '',
    bar: {
      groupWidth: '80%'
    },
    colors: [barColors[meterType]],
    hAxis: {},
    vAxis: {
      title: vAxisTitles[meterType],
      viewWindow: {
        min: 0,
        max: vAxisMax
      }
    },
    chartArea: {
      left: 50,
      width: 450,
      top: 25,
      height: 150,
    },
    legend: {
      position: 'none'
    }
  }
}

function roundUpToNiceNumber (value) {
  if (value <= 0) {
    return 0
  }
  const multipleOf10 = Math.pow(10, Math.floor(Math.log10(value)))
  const mantissa = value / multipleOf10
  const niceNumbers = [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]
  const roundedMantissa = niceNumbers.find(n => n >= mantissa)
  if (!roundedMantissa) {
    return value // This should not happen.
  }
  return roundedMantissa * multipleOf10
}

Vue.component('MeterReadings', {
  props: {
    meterId: String,
    meterType: String
  },
  data: function () {
    const yColumn = {
      electricity: 'currentConsumptionW',
      gas: 'currentConsumptionM3PerH'
    }[this.meterType]
    const now = new Date()
    const days = []
    for (let i = 0; i < 7; i++) {
      days.push(new Date(now.getFullYear(), now.getMonth(), now.getDate() - i))
    }
    return {
      yColumn: yColumn,
      days: days,
      readingsByHour: null,
      readingsByMinute: null,
      vAxisMax: 0,
      error: null,
    }
  },
  methods: {
    optionsForDay: function (day) {
      const options = defaultChartOptions(this.meterType, this.$data.vAxisMax)
      options.title = day.toDateString()
      const nextDay = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1)
      options.hAxis = {
        format: 'HH:mm', // For days, use: 'EEE\nd MMM'
        viewWindow: {
          min: day,
          max: nextDay
        },
        gridlines: {
          count: 8
        },
        minorGridlines: {
          count: 2
        }
      }
      return options
    },
    optionsForHour: function () {
      const options = defaultChartOptions(this.meterType, this.$data.vAxisMax)
      options.title = 'Past hour'
      options.hAxis = {
        format: 'HH:mm',
        gridlines: {
          count: 6,
        },
        minorGridlines: {
          count: 9
        }
      }
      return options
    }
  },
  mounted: async function () {
    const fetchReadings = async (query) => {
      const encodedQuery = Object.entries(query)
        .map(([ key, value ]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
        .join('&')
      const response = await fetch(`/meters/${this.meterId}/readings?${encodedQuery}`, { credentials: 'same-origin' })
      if (!response.ok) {
        this.$data.error = response.statusText
        return
      }

      const readings = await response.json()

      const secondsPerHour = 60 * 60
      const intervalSeconds = {
        second: 1,
        minute: 60,
        hour: 60 * 60,
        day: 24 * 60 * 60
      }[query.resolution]
      switch (this.meterType) {
        case 'electricity':
          addDeltaColumn(readings, ['totalConsumptionKwhLow', 'totalConsumptionKwhHigh'], 'currentConsumptionW', intervalSeconds, 1000 * secondsPerHour)
          break
        case 'gas':
          addDeltaColumn(readings, ['totalConsumptionM3'], 'currentConsumptionM3PerH', intervalSeconds, secondsPerHour)
          break
      }

      const timestampIndex = readings[0].indexOf('timestamp')
      const centerTimestampIndex = readings[0].indexOf('centerTimestamp')
      for (let i = 1; i < readings.length; i++) {
        const row = readings[i]
        row[timestampIndex] = new Date(row[timestampIndex] * 1000)
        row[centerTimestampIndex] = new Date(row[centerTimestampIndex] * 1000)
      }

      return readings
    }

    const nowMillis = Date.now()
    const oneHourAgoMillis = new Date(nowMillis - 60 * 60 * 1000).getTime();
    const oneWeekAgoMillis = new Date(nowMillis - 7 * 24 * 60 * 60 * 1000).getTime();

    const [ readingsByMinute, readingsByHour ] = await Promise.all([
      await fetchReadings({ startTime: oneHourAgoMillis, endTime: nowMillis, resolution: 'minute' }),
      await fetchReadings({ startTime: oneWeekAgoMillis, endTime: nowMillis, resolution: 'hour' })
    ])
    const maxValue = (readings) => {
      let max = 0
      let columnIndex = readings[0].indexOf(this.$data.yColumn)
      for (let i = 1; i < readings.length; i++) {
        const reading = readings[i][columnIndex]
        if (!isNaN(reading)) {
          max = Math.max(max, reading)
        }
      }
      return max
    }

    this.$data.readingsByHour = readingsByHour;
    this.$data.readingsByMinute = readingsByMinute;
    this.$data.vAxisMax = roundUpToNiceNumber(Math.max(maxValue(readingsByMinute), maxValue(readingsByHour)))

    // TODO this is needed because optionsForDay(day) changed, but is horrendously bad style -- refactor to fix
    this.$forceUpdate()
  },
  template:
`

    <ColumnChart :data="readingsByMinute" x-column="centerTimestamp" :y-column="yColumn" :options="optionsForHour()"/>

    <ColumnChart :data="readingsByHour" x-column="centerTimestamp" :y-column="yColumn" :options="optionsForDay(day)"/>

Error fetching meter readings: {{ error }}

Loading…
`
})

Vue.component('ColumnChart', googleChartsComponent({
  props: {
    data: Array,
    xColumn: String,
    yColumn: String,
    options: Object
  },
  template: '
',
  mounted: function () {
    const dataTable = google.visualization.arrayToDataTable(this.data)
    const dataView = new google.visualization.DataView(dataTable)
    function getColumnIndex (label) {
      const n = dataView.getNumberOfColumns()
      for (let i = 0; i < n; i++) {
        if (dataView.getColumnLabel(i) === label) {
          return i
        }
      }
      return -1
    }
    dataView.setColumns([this.xColumn, this.yColumn].map(getColumnIndex))

    const chart = new google.visualization.ColumnChart(this.$el)
    chart.draw(dataView, this.options)
  }
}))

function googleChartsComponent (component) {
  return function (resolve, reject) {
    // Adding a callback after it's already loaded will just immediately call
    // the callback. This is undocumented, but sensible enough that we can rely
    // on it.
    google.charts.setOnLoadCallback(function () {
      resolve(component)
    })
  }
}

function addDeltaColumn (readings, totalKeys, deltaKey, intervalSeconds, timeUnitSeconds) {
  // TODO ensure that the server always sends headings, even if the data is empty, then remove this
  if (readings.length <= 1) {
    return
  }
  const timestampIndex = readings[0].indexOf('timestamp')
  const totalIndices = totalKeys.map(totalKey => readings[0].indexOf(totalKey))
  readings[0].push('centerTimestamp', deltaKey)
  let previousRow = readings[1]
  previousRow.push(NaN, NaN)
  for (let i = 2; i < readings.length; i++) {
    const currentRow = readings[i]
    const deltaTime = currentRow[timestampIndex] - previousRow[timestampIndex]
    let deltaValue = 0
    for (const totalIndex of totalIndices) {
      const d = currentRow[totalIndex] - previousRow[totalIndex]
      if (d < 0) {
        deltaValue = NaN
      }
      deltaValue += d
    }
    const centerTimestamp = (currentRow[timestampIndex] + previousRow[timestampIndex]) / 2
    const centerTimestampRounded = roundDate.floor(intervalSeconds, new Date(centerTimestamp * 1000 - intervalSeconds / 2)).getTime() / 1000 + intervalSeconds / 2
    const delta = deltaValue / deltaTime * timeUnitSeconds
    currentRow.push(centerTimestampRounded, delta)
    previousRow = currentRow
  }
}

new Vue({
  el: '#main'
})
<commit_msg>Refactor to get rid of forced update<commit_after>require('babel-polyfill')
require('whatwg-fetch')

const roundDate = require('round-date')
const Vue = require('../../node_modules/vue/dist/vue.common.js')

// https://developers.google.com/chart/interactive/docs/release_notes#official-releases
google.charts.load('45.2', {'packages': ['corechart']})

function defaultChartOptions (meterType, vAxisMax) {
  const barColors = {
    electricity: '#FF851B',
    gas: '#0074D9'
  }
  const vAxisTitles = {
    electricity: 'Electricity consumption (W)',
    gas: 'Gas consumption (m³/h)'
  }
  return {
    width: 500,
    height: 200,
    title: '',
    bar: {
      groupWidth: '80%'
    },
    colors: [barColors[meterType]],
    hAxis: {},
    vAxis: {
      title: vAxisTitles[meterType],
      viewWindow: {
        min: 0,
        max: vAxisMax
      }
    },
    chartArea: {
      left: 50,
      width: 450,
      top: 25,
      height: 150,
    },
    legend: {
      position: 'none'
    }
  }
}

function roundUpToNiceNumber (value) {
  if (value <= 0) {
    return 0
  }
  const multipleOf10 = Math.pow(10, Math.floor(Math.log10(value)))
  const mantissa = value / multipleOf10
  const niceNumbers = [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10]
  const roundedMantissa = niceNumbers.find(n => n >= mantissa)
  if (!roundedMantissa) {
    return value // This should not happen.
  }
  return roundedMantissa * multipleOf10
}

Vue.component('MeterReadings', {
  props: {
    meterId: String,
    meterType: String
  },
  data: function () {
    const now = new Date()
    const days = []
    for (let i = 0; i < 7; i++) {
      days.push(new Date(now.getFullYear(), now.getMonth(), now.getDate() - i))
    }
    const yColumn = {
      electricity: 'currentConsumptionW',
      gas: 'currentConsumptionM3PerH'
    }[this.$props.meterType]
    return {
      now: now,
      days: days,
      yColumn: yColumn,
      readingsByHour: null,
      readingsByMinute: null,
      vAxisMax: 0,
      error: null,
    }
  },
  mounted: async function () {
    const fetchReadings = async (query) => {
      const encodedQuery = Object.entries(query)
        .map(([ key, value ]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
        .join('&')
      const response = await fetch(`/meters/${this.meterId}/readings?${encodedQuery}`, { credentials: 'same-origin' })
      if (!response.ok) {
        this.$data.error = response.statusText
        return
      }

      const readings = await response.json()

      const secondsPerHour = 60 * 60
      const intervalSeconds = {
        second: 1,
        minute: 60,
        hour: 60 * 60,
        day: 24 * 60 * 60
      }[query.resolution]
      switch (this.meterType) {
        case 'electricity':
          addDeltaColumn(readings, ['totalConsumptionKwhLow', 'totalConsumptionKwhHigh'], 'currentConsumptionW', intervalSeconds, 1000 * secondsPerHour)
          break
        case 'gas':
          addDeltaColumn(readings, ['totalConsumptionM3'], 'currentConsumptionM3PerH', intervalSeconds, secondsPerHour)
          break
      }

      const timestampIndex = readings[0].indexOf('timestamp')
      const centerTimestampIndex = readings[0].indexOf('centerTimestamp')
      for (let i = 1; i < readings.length; i++) {
        const row = readings[i]
        row[timestampIndex] = new Date(row[timestampIndex] * 1000)
        row[centerTimestampIndex] = new Date(row[centerTimestampIndex] * 1000)
      }

      return readings
    }

    const nowMillis = this.$data.now.getTime()
    const oneHourAgoMillis = new Date(nowMillis - 60 * 60 * 1000).getTime();
    const oneWeekAgoMillis = new Date(nowMillis - 7 * 24 * 60 * 60 * 1000).getTime();

    const [ readingsByMinute, readingsByHour ] = await Promise.all([
      await fetchReadings({ startTime: oneHourAgoMillis, endTime: nowMillis, resolution: 'minute' }),
      await fetchReadings({ startTime: oneWeekAgoMillis, endTime: nowMillis, resolution: 'hour' })
    ])

    const maxValue = (readings) => {
      let max = 0
      let columnIndex = readings[0].indexOf(this.$data.yColumn)
      for (let i = 1; i < readings.length; i++) {
        const reading = readings[i][columnIndex]
        if (!isNaN(reading)) {
          max = Math.max(max, reading)
        }
      }
      return max
    }

    this.$data.readingsByHour = readingsByHour;
    this.$data.readingsByMinute = readingsByMinute;
    this.$data.vAxisMax = roundUpToNiceNumber(Math.max(maxValue(readingsByMinute), maxValue(readingsByHour)))
  },
  template: `

        <MeterReadingsChart
            :meterType="meterType"
            :data="readingsByMinute"
            :title="'Past hour'"
            :yColumn="yColumn"
            :vAxisMax="vAxisMax"
            :endTime="now"
            :duration="60 * 60 * 1000"
            :majorGridlines="6"
            :minorGridlines="10"/>

        <MeterReadingsChart
            :meterType="meterType"
            :data="readingsByHour"
            :title="day.toDateString()"
            :yColumn="yColumn"
            :vAxisMax="vAxisMax"
            :endTime="day"
            :duration="24 * 60 * 60 * 1000"
            :majorGridlines="8"
            :minorGridlines="3"/>

Error fetching meter readings: {{ error }}

Loading…

  `
})

Vue.component('MeterReadingsChart', {
  props: {
    meterType: String,
    data: Array,
    title: String,
    yColumn: String,
    vAxisMax: Number,
    endTime: Date,
    duration: Number,
    majorGridlines: Number,
    minorGridlines: Number
  },
  computed: {
    options: function () {
      const options = defaultChartOptions(this.$props.meterType, this.$props.vAxisMax)
      options.title = this.$props.title
      options.hAxis = {
        format: 'HH:mm', // For days, use: 'EEE\nd MMM'
        viewWindow: {
          min: new Date(this.$props.endTime.getTime() - this.$props.duration),
          max: this.$props.endTime
        },
        gridlines: {
          count: this.$props.majorGridlines // It's subdivisions, not lines.
        },
        minorGridlines: {
          count: this.$props.minorGridlines - 1 // It's lines, not subdivisions.
        }
      }
      return options
    }
  },
  template: `
    <ColumnChart
      :data="data"
      :x-column="'centerTimestamp'"
      :y-column="yColumn"
      :options="options"
    />
  `
})

Vue.component('ColumnChart', googleChartsComponent({
  props: {
    data: Array,
    xColumn: String,
    yColumn: String,
    options: Object
  },
  template: '
',
  mounted: function () {
    const dataTable = google.visualization.arrayToDataTable(this.data)
    const dataView = new google.visualization.DataView(dataTable)
    function getColumnIndex (label) {
      const n = dataView.getNumberOfColumns()
      for (let i = 0; i < n; i++) {
        if (dataView.getColumnLabel(i) === label) {
          return i
        }
      }
      return -1
    }
    dataView.setColumns([this.xColumn, this.yColumn].map(getColumnIndex))

    const chart = new google.visualization.ColumnChart(this.$el)
    chart.draw(dataView, this.options)
  }
}))

function googleChartsComponent (component) {
  return function (resolve, reject) {
    // Adding a callback after it's already loaded will just immediately call
    // the callback. This is undocumented, but sensible enough that we can rely
    // on it.
    google.charts.setOnLoadCallback(function () {
      resolve(component)
    })
  }
}

function addDeltaColumn (readings, totalKeys, deltaKey, intervalSeconds, timeUnitSeconds) {
  // TODO ensure that the server always sends headings, even if the data is empty, then remove this
  if (readings.length <= 1) {
    return
  }
  const timestampIndex = readings[0].indexOf('timestamp')
  const totalIndices = totalKeys.map(totalKey => readings[0].indexOf(totalKey))
  readings[0].push('centerTimestamp', deltaKey)
  let previousRow = readings[1]
  previousRow.push(NaN, NaN)
  for (let i = 2; i < readings.length; i++) {
    const currentRow = readings[i]
    const deltaTime = currentRow[timestampIndex] - previousRow[timestampIndex]
    let deltaValue = 0
    for (const totalIndex of totalIndices) {
      const d = currentRow[totalIndex] - previousRow[totalIndex]
      if (d < 0) {
        deltaValue = NaN
      }
      deltaValue += d
    }
    const centerTimestamp = (currentRow[timestampIndex] + previousRow[timestampIndex]) / 2
    const centerTimestampRounded = roundDate.floor(intervalSeconds, new Date(centerTimestamp * 1000 - intervalSeconds / 2)).getTime() / 1000 + intervalSeconds / 2
    const delta = deltaValue / deltaTime * timeUnitSeconds
    currentRow.push(centerTimestampRounded, delta)
    previousRow = currentRow
  }
}

new Vue({
  el: '#main'
})
<|endoftext|>


<commit_before>$(document).ready(function() {

  //createTimesheets([TimeTools.testTimesheet,TimeTools.testTimesheet,TimeTools.testTimesheet])
  // Database.listTimesheetsByUserId(GnomonSession.userid).done(function(result) {
  //   var timesheets = result['timesheets'];
  //   createTimesheets(timesheets);
  // });

  function createTimesheets(timesheets) {
    if(timesheets.length === 0) {

    }
    var rowDiv = null;
    for(var i=0; i<timesheets.length; i++){
      if(i%2 === 0) {
        rowDiv = createNewRow();
      }
      $(rowDiv).append(createNewClock(timesheets[i]));
    }
  }

  function createNewClock(timesheet) {

    var weeks = TimeTools.getWeeks(timesheet['clockIn'], timesheet['clockOut']);
    var weekTime = 0;
    var dayTime = 0;
    if(weeks.length > 0) {
      var week = weeks[weeks.length-1];
      weekTime = TimeTools.getTimeTotal(week['in'], week['out']);

      var days = TimeTools.getDays(week['in'], week['out']);
      if(days.length > 0) {
        var day = days[days.length-1];
        day = TimeTools.getTimeTotal(day['in'], week['out']);
      }
    }

    var cloned = $("#clock-in-template").clone();
    cloned.removeAttr('id');
    cloned.removeAttr('style');

    var clonedBtn = cloned.find(".clock-in-btn").first();
    if(timesheet['clockIn'].length > timesheet['clockOut'].length) {
      clonedBtn.addClass("btn-danger");
      clonedBtn.html("Clock Out");
      clonedBtn.click(function() {
        Database.clockOut(timesheet['id']).done(function(){
          reloadDom();
        })
      });
    }
    else {
      clonedBtn.addClass("btn-success");
      clonedBtn.html("Clock In");
      clonedBtn.click(function(){
        Database.clockIn(timesheet['id']).done(function(){
          reloadDom();
        })
      });
    }

    cloned.find(".clock-in-btn").click(function(){
      console.log('here');
    });

    cloned.find(".clock-in-title-text").html("loading...");

    Database.getJob(timesheet['jobId']).done(function(result) {
      cloned.find(".clock-in-title-text").html(result['job']['name']);
      cloned.find(".clock-in-image").attr("src", "https://www.gravatar.com/avatar/" + result['job']['id'] + "?f=y&d=identicon")
    });
    cloned.find(".timesheet-link").attr("href", "/timesheet/"+timesheet['id']);
    cloned.find(".clock-in-week").html("Week: "+TimeTools.msToReadable(weekTime));
    cloned.find(".clock-in-day").html("Day: "+TimeTools.msToReadable(dayTime));

    return cloned;
  }
  function createNewRow() {
    var rowDiv = $(document.createElement("div"));
    $("#clock-in-list").append(rowDiv);
    rowDiv.attr("class", "row");

    var fillerColumn = $(document.createElement("div"));
    rowDiv.append(fillerColumn);
    fillerColumn.attr("class", "col-sm-1 col-md-2 col-lg-3");

    return rowDiv;
  }
  function reloadDom() {

    Database.listTimesheetsByUserId(GnomonSession.userid).done(function(result) {
      var timesheets = result['timesheets'];
      if(timesheets.length > 0) {
        createTimesheets(timesheets);
        $('#clock-in-list').empty();
      }
      else {
        $('#clock-in-list').append($("
Sorry, You Don't Have Any Jobs
"));
      }

    });
  }
  reloadDom();
});
<commit_msg>Added cwig's changes to the clock in page.<commit_after>$(document).ready(function() {

  //createTimesheets([TimeTools.testTimesheet,TimeTools.testTimesheet,TimeTools.testTimesheet])
  // Database.listTimesheetsByUserId(GnomonSession.userid).done(function(result) {
  //   var timesheets = result['timesheets'];
  //   createTimesheets(timesheets);
  // });

  function createTimesheets(timesheets) {
    if(timesheets.length === 0) {

    }
    var rowDiv = null;
    for(var i=0; i<timesheets.length; i++){
      if(i%2 === 0) {
        rowDiv = createNewRow();
      }
      $(rowDiv).append(createNewClock(timesheets[i]));
    }
  }

  function createNewClock(timesheet) {

    var weeks = TimeTools.getWeeks(timesheet['clockIn'], timesheet['clockOut']);
    var weekTime = 0;
    var dayTime = 0;
    if(weeks.length > 0) {
      var week = weeks[weeks.length-1];
      weekTime = TimeTools.getTimeTotal(week['in'], week['out']);

      var days = TimeTools.getDays(week['in'], week['out']);
      if(days.length > 0) {
        var day = days[days.length-1];
        day = TimeTools.getTimeTotal(day['in'], week['out']);
      }
    }

    var cloned = $("#clock-in-template").clone();
    cloned.removeAttr('id');
    cloned.removeAttr('style');

    var clonedBtn = cloned.find(".clock-in-btn").first();
    if(timesheet['clockIn'].length > timesheet['clockOut'].length) {
      clonedBtn.addClass("btn-danger");
      clonedBtn.html("Clock Out");
      clonedBtn.click(function() {
        Database.clockOut(timesheet['id']).done(function(){
          reloadDom();
        })
      });
    }
    else {
      clonedBtn.addClass("btn-success");
      clonedBtn.html("Clock In");
      clonedBtn.click(function(){
        Database.clockIn(timesheet['id']).done(function(){
          reloadDom();
        })
      });
    }

    cloned.find(".clock-in-btn").click(function(){
      console.log('here');
    });

    cloned.find(".clock-in-title-text").html("loading...");

    Database.getJob(timesheet['jobId']).done(function(result) {
      cloned.find(".clock-in-title-text").html(result['job']['name']);
      cloned.find(".clock-in-image").attr("src", "https://www.gravatar.com/avatar/" + result['job']['id'] + "?f=y&d=identicon")
    });
    cloned.find(".timesheet-link").attr("href", "/timesheet/"+timesheet['id']);
    cloned.find(".clock-in-week").html("Week: "+TimeTools.msToReadable(weekTime));
    cloned.find(".clock-in-day").html("Day: "+TimeTools.msToReadable(dayTime));

    return cloned;
  }
  function createNewRow() {
    var rowDiv = $(document.createElement("div"));
    $("#clock-in-list").append(rowDiv);
    rowDiv.attr("class", "row");

    var fillerColumn = $(document.createElement("div"));
    rowDiv.append(fillerColumn);
    fillerColumn.attr("class", "col-sm-1 col-md-2 col-lg-3");

    return rowDiv;
  }
  function reloadDom() {

    Database.listTimesheetsByUserId(GnomonSession.userid).done(function(result) {
      var timesheets = result['timesheets'];
      if(timesheets.length > 0) {
        $('#clock-in-list').empty();
        createTimesheets(timesheets);
      }
      else {
        $('#clock-in-list').append($("
Sorry, You Don't Have Any Jobs
"));
      }

    });
  }
  reloadDom();
});
<|endoftext|>


<commit_before>
var getBunteData = require('./interfaceToBunte').getAnalysis;

var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
String.prototype.trim = function () {
  return this.replace(rtrim, "");
}

// seems to always include an empty word -> doesn't matter because it won't
// really affect computeSimilarity
var tokenize = function(string) {
	return string.replace(/[.,;'"!?]/g, '').replace(/[\n]/g, " ").split(" ");
}

// computes the # of exact word matches from the tweet and headlines
var computeSimilarity = function (tweetTokens, headline, subheadline, shortText) {
	similarity = 0;
	var headlineTokens = tokenize(headline.trim());
	var subheadlineTokens = tokenize(subheadline.trim());
	var shortTextTokens = tokenize(shortText.trim());

	var currToken;
	var stopwords = ['der', 'die', 'das', 'ein', 'eine', 'einer', 'dieser'];
	for (var i = 0; i < tweetTokens.length; i++) {
		currToken = tweetTokens[i];
		if (stopwords.indexOf(currToken) != -1) {
			continue;
		}

		for (var j = 0; j < headlineTokens.length; j++) {
			if (currToken.toLowerCase() === headlineTokens[j].toLowerCase()) {
				similarity++;
			}
		};

		for (var j = 0; j < subheadlineTokens.length; j++) {
			if (currToken.toLowerCase() === subheadlineTokens[j].toLowerCase()) {
				similarity++;
			}
		};

		for (var j = 0; j < shortTextTokens.length; j++) {
			if (shortTextTokens[j].length < 3) {
				continue;
			} else if (currToken.toLowerCase() === shortTextTokens[j].toLowerCase()) {
				similarity++;
			}
		};
	};
	return similarity;
}

exports.getHeadlines = function(tweet, next) {
    var headline = "Wetten, dass..?";
    var title = "Schlechteste Quote aller Zeiten!";

    var headlines = [];

    var tweetTokens = tweet.replace(/\n/g, " " ).split( " " );

    getBunteData(function(error, data) {
    	var articles = data.articleArray;

    	var currArticle, currHeadline, currSubheadline, currSimilarity,
    	    currShortText, newItem;
    	for (var i = 0; i < articles.length; i++) {
    		currArticle = articles[i];
    		currHeadline = currArticle.headlineText;
    		currSubheadline = currArticle.title;
    		currShortText = currArticle.shortText;
    		currSimilarity = computeSimilarity(tweetTokens, currHeadline, currSubheadline, currShortText);

    		newItem = {
    			headline: currHeadline,
    			subheadline: currSubheadline,
    			similarity: similarity,
    			id: currArticle.articleID
    		}

    		if (similarity == 0) {
    			continue;
    		}

    		// insert new item into headlines w/ descending similarity
    		var notYetInserted = true;
    		for (var j = 0; j < headlines.length; j++) {
    			if (currSimilarity >= headlines[j].similarity) {
    				headlines.splice(j, 0, newItem);
    				notYetInserted = false;
    				break;
    			} else {
    				continue;
    			}
    		};
    		if (notYetInserted) {
    			headlines.push(newItem);
    		}
    	};

    	console.log(headlines);
        next(null, headlines);
    });
};<commit_msg>fixed bunte bug<commit_after>
var getBunteData = require('./interfaceToBunte').getAnalysis;

var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
String.prototype.trim = function () {
  return this.replace(rtrim, "");
}

// seems to always include an empty word -> doesn't matter because it won't
// really affect computeSimilarity
var tokenize = function(string) {
	return string.replace(/[.,;'"\#!?]/g, '').replace(/[\n]/g, " ").split(" ");
}

// computes the # of exact word matches from the tweet and headlines
var computeSimilarity = function (tweetTokens, headline, subheadline, shortText) {
	similarity = 0;
	var headlineTokens = tokenize(headline.trim());
	var subheadlineTokens = tokenize(subheadline.trim());
	var shortTextTokens = tokenize(shortText.trim());

	var currToken;
	var stopwords = ['der', 'die', 'das', 'ein', 'eine', 'einer', 'dieser'];
	for (var i = 0; i < tweetTokens.length; i++) {
		currToken = tweetTokens[i];
		if (stopwords.indexOf(currToken) != -1) {
			continue;
		}

		for (var j = 0; j < headlineTokens.length; j++) {
			if (currToken.toLowerCase() === headlineTokens[j].toLowerCase()) {
				similarity++;
			}
		};

		for (var j = 0; j < subheadlineTokens.length; j++) {
			if (currToken.toLowerCase() === subheadlineTokens[j].toLowerCase()) {
				similarity++;
			}
		};

		for (var j = 0; j < shortTextTokens.length; j++) {
			if (shortTextTokens[j].length < 3) {
				continue;
			} else if (currToken.toLowerCase() === shortTextTokens[j].toLowerCase()) {
				similarity++;
			}
		};
	};
	return similarity;
}

exports.getHeadlines = function(tweet, next) {
    var headline = "Wetten, dass..?";
    var title = "Schlechteste Quote aller Zeiten!";

    var headlines = [];

    var tweetTokens = tokenize(tweet);

    getBunteData(function(error, data) {
    	var articles = data.articleArray;

    	var currArticle, currHeadline, currSubheadline, currSimilarity,
    	    currShortText, newItem;
    	for (var i = 0; i < articles.length; i++) {
    		currArticle = articles[i];
    		currHeadline = currArticle.headlineText;
    		currSubheadline = currArticle.title;
    		currShortText = currArticle.shortText;
    		currSimilarity = computeSimilarity(tweetTokens, currHeadline, currSubheadline, currShortText);

    		newItem = {
    			headline: currHeadline,
    			subheadline: currSubheadline,
    			similarity: similarity,
    			id: currArticle.articleID
    		}

    		if (similarity == 0) {
    			continue;
    		}

    		// insert new item into headlines w/ descending similarity
    		var notYetInserted = true;
    		for (var j = 0; j < headlines.length; j++) {
    			if (currSimilarity >= headlines[j].similarity) {
    				headlines.splice(j, 0, newItem);
    				notYetInserted = false;
    				break;
    			} else {
    				continue;
    			}
    		};
    		if (notYetInserted) {
    			headlines.push(newItem);
    		}
    	};

    	console.log(headlines);
        next(null, headlines);
    });
};<|endoftext|>


<commit_before>
Tinytest.addAsync(
  'Hijacks - Methods - default',
  function (test, next) {
    Zone.Reporters.removeAll();
    Zone.Reporters.add('test-reporter', function (zone) {

      // test whether zone has correct owner info
      var owner = zone.owner;
      var expectedOwner = {
        args: ['arg1', 'arg2'],
        name: 'test',
        // time: 123,
        type: 'Meteor.call',
        // zoneId: 123
      };

      test.equal('object', typeof owner);
      test.equal('number', typeof owner.time);
      delete owner.time;
      test.equal('number', typeof owner.zoneId);
      delete owner.zoneId;
      test.equal(expectedOwner, owner);

      // test whether zone has correct info
      // the parent zone contains method info
      var info = zone.infoMap[zone.id];
      console.log('-- info', info)
      var expectedInfo = {
        'Meteor.call': {
          type: 'Meteor.call',
          name: 'test',
          // time: 123,
          args: ['arg1', 'arg2'],
        }
      };

      test.equal('object', typeof info);
      test.equal('number', typeof info['Meteor.call'].time);
      delete info['Meteor.call'].time;
      test.equal(expectedInfo, info);

      // reset zone for other tests and continue
      Zone.Reporters.add(Zone.longStackTrace);
      Zone.Reporters.remove('test-reporter');
      next();
    });

    Meteor.call('test', 'arg1', 'arg2', function () {
      throw new Error('test-error');
    });
  }
);
<commit_msg>Remove console.log<commit_after>
Tinytest.addAsync(
  'Hijacks - Methods - default',
  function (test, next) {
    Zone.Reporters.removeAll();
    Zone.Reporters.add('test-reporter', function (zone) {

      // test whether zone has correct owner info
      var owner = zone.owner;
      var expectedOwner = {
        args: ['arg1', 'arg2'],
        name: 'test',
        // time: 123,
        type: 'Meteor.call',
        // zoneId: 123
      };

      test.equal('object', typeof owner);
      test.equal('number', typeof owner.time);
      delete owner.time;
      test.equal('number', typeof owner.zoneId);
      delete owner.zoneId;
      test.equal(expectedOwner, owner);

      // test whether zone has correct info
      // the parent zone contains method info
      var info = zone.infoMap[zone.id];
      var expectedInfo = {
        'Meteor.call': {
          type: 'Meteor.call',
          name: 'test',
          // time: 123,
          args: ['arg1', 'arg2'],
        }
      };

      test.equal('object', typeof info);
      test.equal('number', typeof info['Meteor.call'].time);
      delete info['Meteor.call'].time;
      test.equal(expectedInfo, info);

      // reset zone for other tests and continue
      Zone.Reporters.add(Zone.longStackTrace);
      Zone.Reporters.remove('test-reporter');
      next();
    });

    Meteor.call('test', 'arg1', 'arg2', function () {
      throw new Error('test-error');
    });
  }
);
<|endoftext|>


<commit_before>/**
 * @file The starting point of Bastion
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

const Discord = require('discord.js');
const BASTION = new Discord.Client({
  disabledEvents: [
    'USER_NOTE_UPDATE',
    'TYPING_START',
    'RELATIONSHIP_ADD',
    'RELATIONSHIP_REMOVE'
  ]
});

/**
 * Add necessary files as a global object.
 */
BASTION.package = require('./package.json');
BASTION.credentials = require('./settings/credentials.json');
BASTION.config = require('./settings/config.json');
BASTION.colors = require('./settings/colors.json');
BASTION.commands = new Discord.Collection();
BASTION.aliases = new Discord.Collection();

/**
 * Log handler
 */
require('./handlers/logHandler')(BASTION);
/**
 * Event handler
 */
require('./handlers/eventHandler')(BASTION);
/**
 * Module handler
 */
require('./handlers/moduleHandler')(BASTION);

// Will use after updating to `discord.js v11.2.0+` as `discord.js v11.1.0` has problems with send() when using array prototypes
// require('./functions/Array.prototype');

/**
 * Log Bastion in as a Discord client.
 */
BASTION.login(BASTION.credentials.token).catch(e => {
  BASTION.log.error(e.stack);
});

/**
 * Handle unhandled rejections
 */
process.on('unhandledRejection', rejection => {
  // eslint-disable-next-line no-console
  console.warn('\n[unhandledRejection]\n\n', rejection, '\n\n[/unhandledRejection]\n');
});
<commit_msg>Minor Improvement<commit_after>/**
 * @file The starting point of Bastion
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

const Discord = require('discord.js');
const BASTION = new Discord.Client({
  disabledEvents: [
    'USER_NOTE_UPDATE',
    'TYPING_START',
    'RELATIONSHIP_ADD',
    'RELATIONSHIP_REMOVE'
  ]
});

/**
 * Add necessary files as a global object.
 */
BASTION.package = require('./package.json');
BASTION.credentials = require('./settings/credentials.json');
BASTION.config = require('./settings/config.json');
BASTION.colors = require('./settings/colors.json');
BASTION.commands = new Discord.Collection();
BASTION.aliases = new Discord.Collection();
BASTION.db = require('sqlite');
BASTION.db.open('./data/Bastion.sqlite');

/**
 * Log handler
 */
require('./handlers/logHandler')(BASTION);
/**
 * Event handler
 */
require('./handlers/eventHandler')(BASTION);
/**
 * Module handler
 */
require('./handlers/moduleHandler')(BASTION);

// Will use after updating to `discord.js v11.2.0+` as `discord.js v11.1.0` has problems with send() when using array prototypes
// require('./functions/Array.prototype');

/**
 * Log Bastion in as a Discord client.
 */
BASTION.login(BASTION.credentials.token).catch(e => {
  BASTION.log.error(e.stack);
});

/**
 * Handle unhandled rejections
 */
process.on('unhandledRejection', rejection => {
  // eslint-disable-next-line no-console
  console.warn('\n[unhandledRejection]\n\n', rejection, '\n\n[/unhandledRejection]\n');
});
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
   <commit_msg>Incompatible dimensions found, Cthuhlu Error 666<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  console.info("Writing from %s to %s, with up to %s seconds between commits", inFile, outFile, max_sleep)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    console.info("Bytes: %s", length)
    try {
      child_process.execFileSync('/usr/bin/git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    <|endoftext|>


<commit_before>import * as ACTION_TYPES from '../constants/action_types'

export function stream(state = {}, action = { type: '' }) {
  if (action.type.indexOf('LOAD_STREAM') === -1) {
    return state
  }
  return {
    ...state,
    error: action.error,
    meta: action.meta,
    payload: action.payload,
    type: action.type,
  }
}

export function staticPage(state = {}, action = { type: '' }) {
  if (action.type.indexOf('STATIC_PAGE') === -1) {
    return state
  }
  return {
    ...state,
    error: action.error,
    meta: action.meta,
    payload: action.payload,
    type: action.type,
  }
}

function addModels(state, type, data) {
  // add state['modelType']
  if (!state[type]) { state[type] = {} }
  const ids = []
  if (data[type] && data[type].length) {
    // add arrays of models to state['modelType']['id']
    data[type].map((model) => {
      state[type][model.id] = Object.assign(state[type][model.id] || {}, model)
      ids.push(model.id)
    })
  } else if (data[type] && typeof data[type] === 'object') {
    // add single model objects to state['modelType']['id']
    const model = data[type]
    state[type][model.id] = Object.assign(state[type][model.id] || {}, model)
    ids.push(model.id)
  }
  return ids
}

export function json(state = {}, action = { type: '' }) {
  const newState = Object.assign({}, state)
  if (action.type === ACTION_TYPES.LOAD_STREAM_REQUEST) {
    // clear out result since it should only be populated on success
    newState.result = {}
    return newState
  } else if (action.type !== ACTION_TYPES.LOAD_STREAM_SUCCESS) {
    return state
  }
  const { response } = action.payload
  // parse linked
  if (response.linked) {
    for (const linkedType in response.linked) {
      if ({}.hasOwnProperty.call(response.linked, linkedType)) {
        addModels(newState, linkedType, response.linked)
      }
    }
  }
  // parse main part of request into the state, and save result as this is the main payload
  const { mappingType, resultFilter } = action.meta
  // set the result to the resultFilter if it exists
  if (resultFilter && typeof resultFilter === 'function') {
    newState.result = resultFilter(response[mappingType])
  } else {
    newState.result = { type: mappingType, ids: addModels(newState, mappingType, response) }
  }
  return newState
}

<commit_msg>Always call addModels<commit_after>import * as ACTION_TYPES from '../constants/action_types'

export function stream(state = {}, action = { type: '' }) {
  if (action.type.indexOf('LOAD_STREAM') === -1) {
    return state
  }
  return {
    ...state,
    error: action.error,
    meta: action.meta,
    payload: action.payload,
    type: action.type,
  }
}

export function staticPage(state = {}, action = { type: '' }) {
  if (action.type.indexOf('STATIC_PAGE') === -1) {
    return state
  }
  return {
    ...state,
    error: action.error,
    meta: action.meta,
    payload: action.payload,
    type: action.type,
  }
}

function addModels(state, type, data) {
  // add state['modelType']
  if (!state[type]) { state[type] = {} }
  const ids = []
  if (data[type] && data[type].length) {
    // add arrays of models to state['modelType']['id']
    data[type].map((model) => {
      state[type][model.id] = Object.assign(state[type][model.id] || {}, model)
      ids.push(model.id)
    })
  } else if (data[type] && typeof data[type] === 'object') {
    // add single model objects to state['modelType']['id']
    const model = data[type]
    state[type][model.id] = Object.assign(state[type][model.id] || {}, model)
    ids.push(model.id)
  }
  return ids
}

export function json(state = {}, action = { type: '' }) {
  const newState = Object.assign({}, state)
  if (action.type === ACTION_TYPES.LOAD_STREAM_REQUEST) {
    // clear out result since it should only be populated on success
    newState.result = {}
    return newState
  } else if (action.type !== ACTION_TYPES.LOAD_STREAM_SUCCESS) {
    return state
  }
  const { response } = action.payload
  // parse linked
  if (response.linked) {
    for (const linkedType in response.linked) {
      if ({}.hasOwnProperty.call(response.linked, linkedType)) {
        addModels(newState, linkedType, response.linked)
      }
    }
  }
  // parse main part of request into the state, and save result as this is the main payload
  const { mappingType, resultFilter } = action.meta
  const ids = addModels(newState, mappingType, response)
  // set the result to the resultFilter if it exists
  if (resultFilter && typeof resultFilter === 'function') {
    newState.result = resultFilter(response[mappingType])
  } else {
    newState.result = { type: mappingType, ids: ids }
  }
  return newState
}

<|endoftext|>


<commit_before>var through = require("through2"),
	gutil = require("gulp-util"),
	_ = require("lodash");

module.exports = function (options) {
	"use strict";

	// if necessary check for required options(s), e.g. options hash, etc.
	if (!options) {
		throw new gutil.PluginError("gulp-translate-html", "No options supplied");
	}

	// delimiters setting
	if(options.templateSettings) {
		_.assign(_.templateSettings, options.templateSettings);
	}

	/**
	 * compile html file with object
	 * @param  {Object} file input file
	 * @return {Object} compiled Template Object
	 */
	function compiler(file) {
		var compiled = _.template(file.contents);
		return compiled(options.messages);
	}

	// see "Writing a plugin"
	// https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/README.md
	function translateHtml(file, enc, callback) {
		/*jshint validthis:true*/

		// Do nothing if no contents
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		if (file.isStream()) {

			// http://nodejs.org/api/stream.html
			// http://nodejs.org/api/child_process.html
			// https://github.com/dominictarr/event-stream

			// accepting streams is optional
			this.emit("error",
				new gutil.PluginError("gulp-translate-html", "Stream content is not supported"));
			return callback();
		}

		// check if file.contents is a `Buffer`
		if (file.isBuffer()) {
			var compiled = compiler(file);

			// manipulate buffer in some way
			// http://nodejs.org/api/buffer.html
			file.contents = new Buffer(compiled);
			this.push(file);

		}
		return callback();
	}

	return through.obj(translateHtml);
};
<commit_msg>add error handling<commit_after>var through = require("through2"),
	gutil = require("gulp-util"),
	_ = require("lodash");

module.exports = function (options) {
	"use strict";

	// if necessary check for required options(s), e.g. options hash, etc.
	if (!options) {
		throw new gutil.PluginError("gulp-translate-html", "No options supplied");
	}

	// delimiters setting
	if(options.templateSettings) {
		_.assign(_.templateSettings, options.templateSettings);
	}

	/**
	 * compile html file with object
	 * @param  {Object} file input file
	 * @return {Object} compiled Template Object
	 */
	function compiler(file) {
		var compiled = _.template(file.contents);
		return compiled(options.messages);
	}

	// see "Writing a plugin"
	// https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/README.md
	function translateHtml(file, enc, callback) {
		/*jshint validthis:true*/

		// Do nothing if no contents
		if (file.isNull()) {
			this.push(file);
			return callback();
		}

		if (file.isStream()) {

			// http://nodejs.org/api/stream.html
			// http://nodejs.org/api/child_process.html
			// https://github.com/dominictarr/event-stream

			// accepting streams is optional
			this.emit("error",
				new gutil.PluginError("gulp-translate-html", "Stream content is not supported"));
			return callback();
		}

		try {
			var compiled = compiler(file);

			// manipulate buffer in some way
			// http://nodejs.org/api/buffer.html
			file.contents = new Buffer(compiled);
			this.push(file);
		} catch(err) {
			this.emit('error', new gutil.PluginError('gulp-translate-html', err, {fileName: file.path}));
		}
		return callback();
	}

	return through.obj(translateHtml);
};
<|endoftext|>


<commit_before>import { parse } from 'papaparse'
import {
    compose, filter, find, flatten, identity,
    join, map, match, not, skip, takeWhile
} from 'ramda'

const clean = compose(filter(identity), flatten)

const dataRegexp = match(RegExp('^(\\d{4}|Year)$'))

function isData (row) {
    return !!find(dataRegexp, row)
}

function getRows (csv) {
    const parsed = parse(csv, {
        dynamicTyping: false,
        header: false,
    })

    return parsed.data
}

function splitHeaders (rows) {
    const header = takeWhile(not(isData), rows)
    const content = takeWhile(isData, skip(header.length, rows))
    const footer = skip(header.length + content.length, rows)

    return {
        content,
        header: clean(header),
        footer: clean(footer),
    }
}

export function cleanup (rawData) {
    const { header, content, footer } = splitHeaders(getRows(rawData))
    const text = join('\n', map(join('\t'), content))

    // Reparse data rows with dynamic typing
    const reparsed = parse(text, {
        header: true,
        dynamicTyping: true,
    })

    if (reparsed.errors.length > 0) {
        console.error('Errors while parsing raw data:', reparsed.errors)
    }

    return Object.assign(reparsed, { header, footer })
}
<commit_msg>eslint: Use regex literal instead of constructor<commit_after>import { parse } from 'papaparse'
import {
    compose, filter, find, flatten, identity,
    join, map, match, not, skip, takeWhile
} from 'ramda'

const clean = compose(filter(identity), flatten)

const dataRegexp = match(/^(\\d{4}|Year)$/)

function isData (row) {
    return !!find(dataRegexp, row)
}

function getRows (csv) {
    const parsed = parse(csv, {
        dynamicTyping: false,
        header: false,
    })

    return parsed.data
}

function splitHeaders (rows) {
    const header = takeWhile(not(isData), rows)
    const content = takeWhile(isData, skip(header.length, rows))
    const footer = skip(header.length + content.length, rows)

    return {
        content,
        header: clean(header),
        footer: clean(footer),
    }
}

export function cleanup (rawData) {
    const { header, content, footer } = splitHeaders(getRows(rawData))
    const text = join('\n', map(join('\t'), content))

    // Reparse data rows with dynamic typing
    const reparsed = parse(text, {
        header: true,
        dynamicTyping: true,
    })

    if (reparsed.errors.length > 0) {
        console.error('Errors while parsing raw data:', reparsed.errors)
    }

    return Object.assign(reparsed, { header, footer })
}
<|endoftext|>


<commit_before>'use strict';

(function() {
  var xhr = new XMLHttpRequest();

  xhr.open('GET', '/api/posts');
  xhr.send(null);

  xhr.onreadystatechange = function() {
    var DONE = 4; // readyState 4 means the request is done.
    var OK = 200; // status 200 is a successful return.
    var post, posts, i;

    if (xhr.readyState === DONE) {
      if (xhr.status === OK) {

        posts = JSON.parse(xhr.responseText);
        console.log(posts);

        for (i = 0; i < posts.length; i++) {
          var card        = document.createElement("div");
          var cardContent = document.createElement("div");
          var cardAction  = document.createElement("div");
          var link        = document.createElement("a");
          var title       = document.createElement("span");
          var titleText   = document.createTextNode(posts[i].title);
          var content     = document.createElement("p");
          var contentText = document.createTextNode(posts[i].content);
          var element     = document.getElementById("posts-container");

          card.appendChild(cardContent);
          card.className += "card blue-grey darken-1";

          cardContent.appendChild(title)
          cardContent.className += "card-content white-text";
          cardContent.appendChild(content)
          cardContent.appendChild(cardAction);

          cardAction.className += "card-action";
          cardAction.appendChild(link);

          link.innerHTML = "Click to Read";
          link.setAttribute("href", "#");

          title.appendChild(titleText);
          title.className += "card-title";

          content.appendChild(contentText);

          element.appendChild(card);
        }
      }
    }
  };
})();
<commit_msg>Style card<commit_after>'use strict';

(function() {
  var xhr = new XMLHttpRequest();

  xhr.open('GET', '/api/posts');
  xhr.send(null);

  xhr.onreadystatechange = function() {
    var DONE = 4; // readyState 4 means the request is done.
    var OK = 200; // status 200 is a successful return.
    var post, posts, i;

    if (xhr.readyState === DONE) {
      if (xhr.status === OK) {

        posts = JSON.parse(xhr.responseText);
        console.log(posts);

        for (i = 0; i < posts.length; i++) {
          var card        = document.createElement("div");
          var cardContent = document.createElement("div");
          var cardAction  = document.createElement("div");
          var link        = document.createElement("a");
          var button      = document.createElement("button");
          var title       = document.createElement("span");
          var titleText   = document.createTextNode(posts[i].title);
          var content     = document.createElement("p");
          var contentText = document.createTextNode(posts[i].content);
          var element     = document.getElementById("posts-container");

          card.appendChild(cardContent);
          card.className += "card grey lighten-2";

          cardContent.appendChild(title)
          cardContent.className += "card-content black-text";
          cardContent.appendChild(content)
          cardContent.appendChild(cardAction);

          cardAction.className += "card-action";
          cardAction.appendChild(link);

          button.innerHTML = "Click to Read";
          button.className += "btn waves-effect red darken-1";

          link.setAttribute("href", "#");
          link.appendChild(button)
          link.className += "";

          title.appendChild(titleText);
          title.className += "card-title";

          content.appendChild(contentText);

          element.appendChild(card);
        }
      }
    }
  };
})();
<|endoftext|>


<commit_before>var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var MongoStore =  require('connect-mongo')(session);
var path = require('path');
var secrets = require('./secrets');
var flash = require('express-flash');
var methodOverride = require('method-override');

module.exports = function (app, passport) {
  app.set('port', (process.env.PORT || 3000));

  // X-Powered-By header has no functional value.
  // Keeping it makes it easier for an attacker to build the site's profile
  // It can be removed safely
  app.disable('x-powered-by');
  app.set('views', path.join(__dirname, '..', 'views'));

  app.set('view cache', false);

  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded
  app.use(methodOverride());
  app.use(express.static(path.join(__dirname, '../..', 'public')));

  // I am adding this here so that the Heroku deploy will work
  // Indicates the app is behind a front-facing proxy,
  // and to use the X-Forwarded-* headers to determine the connection and the IP address of the client.
  // NOTE: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
  // trust proxy is disabled by default.
  // When enabled, Express attempts to determine the IP address of the client connected through the front-facing proxy, or series of proxies.
  // The req.ips property, then, contains an array of IP addresses the client is connected through.
  // To enable it, use the values described in the trust proxy options table.
  // The trust proxy setting is implemented using the proxy-addr package. For more information, see its documentation.
  // loopback - 127.0.0.1/8, ::1/128
  app.set('trust proxy', 'loopback');
  // Create a session middleware with the given options
  // Note session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
  // Options: resave: forces the session to be saved back to the session store, even if the session was never
  //                  modified during the request. Depending on your store this may be necessary, but it can also
  //                  create race conditions where a client has two parallel requests to your server and changes made
  //                  to the session in one request may get overwritten when the other request ends, even if it made no
  //                  changes(this behavior also depends on what store you're using).
  //          saveUnitialized: Forces a session that is uninitialized to be saved to the store. A session is uninitialized when
  //                  it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage
  //                  usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with
  //                  race conditions where a client makes multiple parallel requests without a session
  //          secret: This is the secret used to sign the session ID cookie.
  //          name: The name of the session ID cookie to set in the response (and read from in the request).
  //          cookie: Please note that secure: true is a recommended option.
  //                  However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies.
  //                  If secure is set, and you access your site over HTTP, the cookie will not be set.
  var sess = {
    resave: true,
    saveUninitialized: false,
    secret: secrets.sessionSecret,
    name: 'sessionId',
    // Add HTTPOnly, Secure attributes on Session Cookie
    // If secure is set, and you access your site over HTTP, the cookie will not be set
    cookie: {
      httpOnly: true,
      secure: false,
    },
    store: new MongoStore(
      {
        url: secrets.db,
        autoReconnect: true
      }
    )
  };

  var node_env = process.env.NODE_ENV;
  console.log('Environment: ' + node_env);
  if(node_env === 'production') {
    sess.cookie.secure = true; // Serve secure cookies
  }

  app.use(session(sess));

  app.use(passport.initialize());
  app.use(passport.session());

  app.use(flash());

};
<commit_msg>Add proxy setting to express session<commit_after>var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var MongoStore =  require('connect-mongo')(session);
var path = require('path');
var secrets = require('./secrets');
var flash = require('express-flash');
var methodOverride = require('method-override');

module.exports = function (app, passport) {
  app.set('port', (process.env.PORT || 3000));

  // X-Powered-By header has no functional value.
  // Keeping it makes it easier for an attacker to build the site's profile
  // It can be removed safely
  app.disable('x-powered-by');
  app.set('views', path.join(__dirname, '..', 'views'));

  app.set('view cache', false);

  app.use(bodyParser.json());
  app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded
  app.use(methodOverride());
  app.use(express.static(path.join(__dirname, '../..', 'public')));

  // I am adding this here so that the Heroku deploy will work
  // Indicates the app is behind a front-facing proxy,
  // and to use the X-Forwarded-* headers to determine the connection and the IP address of the client.
  // NOTE: X-Forwarded-* headers are easily spoofed and the detected IP addresses are unreliable.
  // trust proxy is disabled by default.
  // When enabled, Express attempts to determine the IP address of the client connected through the front-facing proxy, or series of proxies.
  // The req.ips property, then, contains an array of IP addresses the client is connected through.
  // To enable it, use the values described in the trust proxy options table.
  // The trust proxy setting is implemented using the proxy-addr package. For more information, see its documentation.
  // loopback - 127.0.0.1/8, ::1/128
  app.set('trust proxy', 'loopback');
  // Create a session middleware with the given options
  // Note session data is not saved in the cookie itself, just the session ID. Session data is stored server-side.
  // Options: resave: forces the session to be saved back to the session store, even if the session was never
  //                  modified during the request. Depending on your store this may be necessary, but it can also
  //                  create race conditions where a client has two parallel requests to your server and changes made
  //                  to the session in one request may get overwritten when the other request ends, even if it made no
  //                  changes(this behavior also depends on what store you're using).
  //          saveUnitialized: Forces a session that is uninitialized to be saved to the store. A session is uninitialized when
  //                  it is new but not modified. Choosing false is useful for implementing login sessions, reducing server storage
  //                  usage, or complying with laws that require permission before setting a cookie. Choosing false will also help with
  //                  race conditions where a client makes multiple parallel requests without a session
  //          secret: This is the secret used to sign the session ID cookie.
  //          name: The name of the session ID cookie to set in the response (and read from in the request).
  //          cookie: Please note that secure: true is a recommended option.
  //                  However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies.
  //                  If secure is set, and you access your site over HTTP, the cookie will not be set.
  var sess = {
    resave: true,
    saveUninitialized: false,
    secret: secrets.sessionSecret,
    proxy: true, // The "X-Forwarded-Proto" header will be used.
    name: 'sessionId',
    // Add HTTPOnly, Secure attributes on Session Cookie
    // If secure is set, and you access your site over HTTP, the cookie will not be set
    cookie: {
      httpOnly: true,
      secure: false,
    },
    store: new MongoStore(
      {
        url: secrets.db,
        autoReconnect: true
      }
    )
  };

  var node_env = process.env.NODE_ENV;
  console.log('Environment: ' + node_env);
  if(node_env === 'production') {
    sess.cookie.secure = true; // Serve secure cookies
  }

  app.use(session(sess));

  app.use(passport.initialize());
  app.use(passport.session());

  app.use(flash());

};
<|endoftext|>