<commit_before>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  BlockQuote,
  Code,
  Deck,
  Heading,
  Fit,
  Image,
  Link,
  List,
  ListItem,
  Quote,
  Slide,
  S,
  Text
} from "spectacle";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");

const theme = createTheme(
  {
    primary: "rgb(70, 72, 61)",
    secondary: "rgba(255, 255, 255, 0.8)",
    highlight: "rgba(190, 211, 64, 1)"
  },
  {
    primary: "Montserrat",
    secondary: "Helvetica"
  }
);

// =============== reusable content for slides...

const images = {
  lnugLogo: require("../assets/lnug-logo.svg"),
  nearFormLogo: require("../assets/logos/NF__Primary_Logo_Reversed_Horizontal.svg"),
  condeNastLogo: require("../assets/logos/Conde_Nast_logo.svg"),
  pusherLogo: require("../assets/logos/pusher_logo_white.png"),
  pusherPromo: require("../assets/announcements/Pusher_promo.jpg"),
  nexmoslide: require("../assets/announcements/Nexmo_LNUG.001.png"),
  spaceStartupslide: require("../assets/announcements/SWOnePager.png"),
  ijsLogo: require("../assets/logos/iJS-logo_desktop@2x.png"),
  pizza: require("../assets/pizza-1.gif"),
  cheers: require("../assets/cheers.gif")
};

const emcee = {
  name: "Aga",
  twitter: "aga_code"
};

// get this from the latest from https://github.com/lnug/website/blob/master/data/this-month.json and add twitter details if desired
const speakers = [
  {
    name: "Forbes Lindesay",
    url: "https://github.com/ForbesLindesay",
    title: "Security in Node.js"
  },
  {
    name: "Thomas Ankcorn",
    url: "https://github.com/Ankcorn",
    title: "Indie Hacking with Postgraphile"
  }
];
const thisMonth = {
  title: "#87 - August 2019"
};

const nextMonth = {
  date: "25th September 2019",

  speakers: [
    {
      name: "Jason Ian Green",
      title: "Concurrent editing with JSON Patch and Operational Transformation"
    },
    {
      name: "Nick O'Leary",
      title: "Managing multiple npm modules in a single repo"
    }
  ]
};

// ================== rusable components

const SpeakerSlide = ({ speaker }) => {
  if (!speaker) {
    return null;
  }

  return (
    <Slide id={speaker.name.replace(" ", "-")}>
      <Heading size={5} textColor="highlight" margin={50}>
        Next Up
      </Heading>
      <Heading size={4} textColor="secondary">
        {speaker.name}
      </Heading>
      <Heading size={6} textColor="secondary">
        <S type="italics">{speaker.title}</S>
      </Heading>
    </Slide>
  );
};

const SummarySlide = ({ id }) => (
  <Slide align={"center center"} id={id}>
    <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
    <Heading size={6} textColor="highlight">
      {thisMonth.title}
    </Heading>
    {speakers.map(speaker => (
      <Fit key={speaker.title} textColor="secondary" textSize={38} margin="20px 0">
        {speaker.name}{" "}
        <S type="italics" textSize={24}>
          {" "}

          {speaker.title}{" "}
        </S>
        <Text textColor="secondary" textSize={20}>
          {speaker.twitter && Twitter: @{speaker.twitter} }

          {speaker.github && Github: @{speaker.github}}
        </Text>
      </Fit>
    ))}
  </Slide>
);

// ====================

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={["zoom", "slide"]} transitionDuration={500} theme={theme} progress={"none"}>
        <SummarySlide id={"start"} />

        <Slide id={"safety"}>
          <Heading size={3} lineHeight={3} textColor="secondary">
            Important
          </Heading>
          <Appear>
            <Heading size={5} textColor="secondary">
              🚻 Toilets: ask for a pass{" "}
            </Heading>
          </Appear>
          <Appear>
            <Heading size={5} textColor="secondary">
              🚒 Fire Exits: next to the toilets{" "}
            </Heading>
          </Appear>
          <Appear>
            <Heading size={5} textColor="secondary">
              📡 Wifi: CN Guest{" "}
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"code-of-conduct"}>
          <Heading size={5} textColor="secondary">
            ⭐ Code of Conduct{" "}
          </Heading>
          <Appear>

              <Quote textColor="highlight" textSize="24px" lineHeight={5}>

                  LNUG is dedicated to providing a harassment-free meetup experience for everyone. We do not tolerate
                  harassment of meetup participants in any form...

                  This code of conduct applies to attendees, speakers, and organisers at the monthly meetups and in
                  related social events. This includes slide decks and listings on the job board.

              </Quote>

          </Appear>
          <Appear>
            <Text textColor="secondary">lnug.org/code-of-conduct.html</Text>
          </Appear>
        </Slide>

        <Slide id={"hashtags"}>
          <Heading size={5} textColor="secondary">
            Tweet
          </Heading>
          <Heading size={2} textColor="highlight">
            @lnugORG
          </Heading>
          <Heading size={4} textColor="secondary">
            #LNUG #node #javascript #london
          </Heading>
          <Appear>
            <Heading size={6} textColor="secondary" margin="20px 0" textSize="20px" textColor="highlight">
              tweet me too @{emcee.twitter}
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"gitter"}>
          <Heading size={3} textColor="highlight">
            discuss!
          </Heading>
          <Heading size={4} textColor="secondary">
            <Link href="http://gitter.im/lnug/discuss" target="_blank">
              gitter.im/lnug/discuss
            </Link>
          </Heading>
        </Slide>

        <Slide id={"jobs"}>
          <Heading size={3} textColor="highlight">
            jobs!
          </Heading>
          <Heading size={4} textColor="secondary">
            <Link href="https://gitter.im/lnug/london-node-jobs" target="_blank">
              gitter.im/lnug/london-node-jobs
            </Link>
          </Heading>
          <Appear>
            <Heading size={6} textColor="secondary" margin="20px 0" textSize="20px" textColor="highlight">
              Make sure you speak to companies at the jobs table
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"venue"}>
          <Heading size={5} textColor="highlight">
            Venue
          </Heading>
          <Image src={images.condeNastLogo} margin="0px auto 40px" width="800px" padding="10px" />
        </Slide>

        <Slide id={"food-and-drink"}>
          <Heading size={5} textColor="highlight">
            Food and drink
          </Heading>
          <Image src={images.nearFormLogo} margin="0px auto 40px" height="293px" padding="10px" />
        </Slide>

        <Slide id={"video-production"}>
          <Heading size={5} textColor="highlight">
            Video
          </Heading>
          <Image src={images.pusherLogo} margin="0px auto 40px" width="800px" />
        </Slide>

        <Slide id={"pusher-promo"}>
          <Image src={images.pusherPromo} margin="0px auto 40px" width="100%" />
        </Slide>

        <SummarySlide id="ready" />

        <SpeakerSlide speaker={speakers[0]} />

        <Slide id={"community-announcments"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={3} textColor="highlight" margin={50}>
            Community Announcements
          </Heading>
          <Heading size={5} textColor="secondary">
            Have something to share?
          </Heading>
        </Slide>

        <Slide id={"submit-a-talk"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={3} textColor="highlight">
            Submit a talk proposal!
          </Heading>

            github.com/lnug/speakers

        </Slide>

        {speakers.length > 1 && <SpeakerSlide speaker={speakers[1]} />}

        <Slide id={"get-involved"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={5} textColor="highlight">
            Get Involved
          </Heading>
          <Heading size={6} textColor="secondary">
            Feedback

              github.com/lnug/feedback

          </Heading>
          <Heading size={6} textColor="secondary">
            Gitter

              gitter.com/lnug/discuss

          </Heading>
        </Slide>

        {speakers.length > 2 && <SpeakerSlide speaker={speakers[2]} />}

        <Slide id={"nex-time"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="140px" />
          <Heading size={5} textColor="highlight">
            Next Time
          </Heading>
          <Heading size={5} textColor="secondary">
            {nextMonth.date}
          </Heading>
          <List margin="20px 5%">
            {nextMonth.speakers.map(speaker => (
              <ListItem key={speaker.title} textColor="secondary" textSize={30} margin="20px 0">
                {speaker.name} <S type="italics"> - {speaker.title}</S>
              </ListItem>
            ))}
          </List>

            meetup.com/london-nodejs

          <Text textColor="highlight" italic margin={20}>
            The 4th Wednesday of the month
          </Text>
        </Slide>

        <Slide align={"center center"}>

            <Image src={images.lnugLogo} margin="10px" height="153px" />
            <Heading size={3} textColor="highlight">
              Thank You
            </Heading>
            <Heading size={5} textColor="secondary">
              Had a great time? Let us know!
            </Heading>
            <Text textColor="highlight">github.com/lnug/feedback</Text>

            and thanks again...

            <Image src={images.condeNastLogo} margin="10" height="60" />
            <Image src={images.pusherLogo} margin="10" height="80" />
            <Image src={images.nearFormLogo} margin="10" height="80" />

        </Slide>

        <Slide>
          <Heading size={5} textColor="highlight" margin={30}>
            After Party
          </Heading>
          <Heading size={5} textColor="secondary">
            Theodore Bullfrog
          </Heading>
          <Text textColor="secondary" margin={10}>
            26-30 John Adam St, London WC2N 6HL
          </Text>
          <Image src={images.cheers.replace("/", "")} margin="40px auto 0px" height="200px" />
          <Heading size={5} textColor="highlight">
            Before you go...
          </Heading>
          Tidy up after yourself! Get involved!
        </Slide>
      </Deck>
    );
  }
}
<commit_msg>september 2019<commit_after>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Appear,
  BlockQuote,
  Code,
  Deck,
  Heading,
  Fit,
  Image,
  Link,
  List,
  ListItem,
  Quote,
  Slide,
  S,
  Text
} from "spectacle";

// Import theme
import createTheme from "spectacle/lib/themes/default";

// Require CSS
require("normalize.css");

const theme = createTheme(
  {
    primary: "rgb(70, 72, 61)",
    secondary: "rgba(255, 255, 255, 0.8)",
    highlight: "rgba(190, 211, 64, 1)"
  },
  {
    primary: "Montserrat",
    secondary: "Helvetica"
  }
);

// =============== reusable content for slides...

const images = {
  lnugLogo: require("../assets/lnug-logo.svg"),
  nearFormLogo: require("../assets/logos/NF__Primary_Logo_Reversed_Horizontal.svg"),
  condeNastLogo: require("../assets/logos/Conde_Nast_logo.svg"),
  pusherLogo: require("../assets/logos/pusher_logo_white.png"),
  pusherPromo: require("../assets/announcements/Pusher_promo.jpg"),
  nexmoslide: require("../assets/announcements/Nexmo_LNUG.001.png"),
  spaceStartupslide: require("../assets/announcements/SWOnePager.png"),
  ijsLogo: require("../assets/logos/iJS-logo_desktop@2x.png"),
  pizza: require("../assets/pizza-1.gif"),
  cheers: require("../assets/cheers.gif")
};

const emcee = {
  name: "adam",
  twitter: "admataz"
};

// get this from the latest from https://github.com/lnug/website/blob/master/data/this-month.json and add twitter details if desired
const speakers = [
  {
    name: "Jason Ian Green",
    title: "Concurrent editing with JSON Patch and Operational Transformation"
  },
  {
    name: "Nick O'Leary",
    title: "Managing multiple npm modules in a single repo"
  }
];
const thisMonth = {
  title: "#88 - September 2019"
};

const nextMonth = {
  date: "23rd October 2019",

  speakers: [
    {
      name: "🤔",
      title: "node.js stuff"
    }
  ]
};

// ================== rusable components

const SpeakerSlide = ({ speaker }) => {
  if (!speaker) {
    return null;
  }

  return (
    <Slide id={speaker.name.replace(" ", "-")}>
      <Heading size={5} textColor="highlight" margin={50}>
        Next Up
      </Heading>
      <Heading size={4} textColor="secondary">
        {speaker.name}
      </Heading>
      <Heading size={6} textColor="secondary">
        <S type="italics">{speaker.title}</S>
      </Heading>
    </Slide>
  );
};

const SummarySlide = ({ id }) => (
  <Slide align={"center center"} id={id}>
    <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
    <Heading size={6} textColor="highlight">
      {thisMonth.title}
    </Heading>
    {speakers.map(speaker => (
      <Fit key={speaker.title} textColor="secondary" textSize={38} margin="20px 0">
        {speaker.name}{" "}
        <S type="italics" textSize={24}>
          {" "}

          {speaker.title}{" "}
        </S>
        <Text textColor="secondary" textSize={20}>
          {speaker.twitter && Twitter: @{speaker.twitter} }

          {speaker.github && Github: @{speaker.github}}
        </Text>
      </Fit>
    ))}
  </Slide>
);

// ====================

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={["zoom", "slide"]} transitionDuration={500} theme={theme} progress={"none"}>
        <SummarySlide id={"start"} />

        <Slide id={"safety"}>
          <Heading size={3} lineHeight={3} textColor="secondary">
            Important
          </Heading>
          <Appear>
            <Heading size={5} textColor="secondary">
              🚻 Toilets: ask for a pass{" "}
            </Heading>
          </Appear>
          <Appear>
            <Heading size={5} textColor="secondary">
              🚒 Fire Exits: next to the toilets{" "}
            </Heading>
          </Appear>
          <Appear>
            <Heading size={5} textColor="secondary">
              📡 Wifi: CN Guest{" "}
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"code-of-conduct"}>
          <Heading size={5} textColor="secondary">
            ⭐ Code of Conduct{" "}
          </Heading>
          <Appear>

              <Quote textColor="highlight" textSize="24px" lineHeight={5}>

                  LNUG is dedicated to providing a harassment-free meetup experience for everyone. We do not tolerate
                  harassment of meetup participants in any form...

                  This code of conduct applies to attendees, speakers, and organisers at the monthly meetups and in
                  related social events. This includes slide decks and listings on the job board.

              </Quote>

          </Appear>
          <Appear>
            <Text textColor="secondary">lnug.org/code-of-conduct.html</Text>
          </Appear>
        </Slide>

        <Slide id={"hashtags"}>
          <Heading size={5} textColor="secondary">
            Tweet
          </Heading>
          <Heading size={2} textColor="highlight">
            @lnugORG
          </Heading>
          <Heading size={4} textColor="secondary">
            #LNUG #node #javascript #london
          </Heading>
          <Appear>
            <Heading size={6} textColor="secondary" margin="20px 0" textSize="20px" textColor="highlight">
              tweet me too @{emcee.twitter}
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"gitter"}>
          <Heading size={3} textColor="highlight">
            discuss!
          </Heading>
          <Heading size={4} textColor="secondary">
            <Link href="http://gitter.im/lnug/discuss" target="_blank">
              gitter.im/lnug/discuss
            </Link>
          </Heading>
        </Slide>

        <Slide id={"jobs"}>
          <Heading size={3} textColor="highlight">
            jobs!
          </Heading>
          <Heading size={4} textColor="secondary">
            <Link href="https://gitter.im/lnug/london-node-jobs" target="_blank">
              gitter.im/lnug/london-node-jobs
            </Link>
          </Heading>
          <Appear>
            <Heading size={6} textColor="secondary" margin="20px 0" textSize="20px" textColor="highlight">
              Make sure you speak to companies at the jobs table
            </Heading>
          </Appear>
        </Slide>

        <Slide id={"venue"}>
          <Heading size={5} textColor="highlight">
            Venue
          </Heading>
          <Image src={images.condeNastLogo} margin="0px auto 40px" width="800px" padding="10px" />
        </Slide>

        <Slide id={"food-and-drink"}>
          <Heading size={5} textColor="highlight">
            Food and drink
          </Heading>
          <Image src={images.nearFormLogo} margin="0px auto 40px" height="293px" padding="10px" />
        </Slide>

        <Slide id={"video-production"}>
          <Heading size={5} textColor="highlight">
            Video
          </Heading>
          <Image src={images.pusherLogo} margin="0px auto 40px" width="800px" />
        </Slide>

        <Slide id={"pusher-promo"}>
          <Image src={images.pusherPromo} margin="0px auto 40px" width="100%" />
        </Slide>

        <SummarySlide id="ready" />

        <SpeakerSlide speaker={speakers[0]} />

        <Slide id={"community-announcments"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={3} textColor="highlight" margin={50}>
            Community Announcements
          </Heading>
          <Heading size={5} textColor="secondary">
            Have something to share?
          </Heading>
        </Slide>

        <Slide id={"submit-a-talk"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={3} textColor="highlight">
            Submit a talk proposal!
          </Heading>

            github.com/lnug/speakers

        </Slide>

        {speakers.length > 1 && <SpeakerSlide speaker={speakers[1]} />}

        <Slide id={"get-involved"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="200px" />
          <Heading size={5} textColor="highlight">
            Get Involved
          </Heading>
          <Heading size={6} textColor="secondary">
            Feedback

              github.com/lnug/feedback

          </Heading>
          <Heading size={6} textColor="secondary">
            Gitter

              gitter.com/lnug/discuss

          </Heading>
        </Slide>

        {speakers.length > 2 && <SpeakerSlide speaker={speakers[2]} />}

        <Slide id={"nex-time"}>
          <Image src={images.lnugLogo} margin="0px auto 0px" height="140px" />
          <Heading size={5} textColor="highlight">
            Next Time
          </Heading>
          <Heading size={5} textColor="secondary">
            {nextMonth.date}
          </Heading>
          <List margin="20px 5%">
            {nextMonth.speakers.map(speaker => (
              <ListItem key={speaker.title} textColor="secondary" textSize={30} margin="20px 0">
                {speaker.name} <S type="italics"> - {speaker.title}</S>
              </ListItem>
            ))}
          </List>

            meetup.com/london-nodejs

          <Text textColor="highlight" italic margin={20}>
            The 4th Wednesday of the month
          </Text>
        </Slide>

        <Slide align={"center center"}>

            <Image src={images.lnugLogo} margin="10px" height="153px" />
            <Heading size={3} textColor="highlight">
              Thank You
            </Heading>
            <Heading size={5} textColor="secondary">
              Had a great time? Let us know!
            </Heading>
            <Text textColor="highlight">github.com/lnug/feedback</Text>

            and thanks again...

            <Image src={images.condeNastLogo} margin="10" height="60" />
            <Image src={images.pusherLogo} margin="10" height="80" />
            <Image src={images.nearFormLogo} margin="10" height="80" />

        </Slide>

        <Slide>
          <Heading size={5} textColor="highlight" margin={30}>
            After Party
          </Heading>
          <Heading size={5} textColor="secondary">
            Theodore Bullfrog
          </Heading>
          <Text textColor="secondary" margin={10}>
            26-30 John Adam St, London WC2N 6HL
          </Text>
          <Image src={images.cheers.replace("/", "")} margin="40px auto 0px" height="200px" />
          <Heading size={5} textColor="highlight">
            Before you go...
          </Heading>
          Tidy up after yourself! Get involved!
        </Slide>
      </Deck>
    );
  }
}
<|endoftext|>


<commit_before>var utp = require('utp');
var net = require('net');
var fifo = require('fifo');
var once = require('once');
var speedometer = require('speedometer');
var peerWireProtocol = require('peer-wire-protocol');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var HANDSHAKE_TIMEOUT = 25000;
var CONNECTION_TIMEOUT = 3000;
var RECONNECT_WAIT = [4000, 8000, 12000];
var DEFAULT_SIZE = 100;

var toBuffer = function(str, encoding) {
	return Buffer.isBuffer(str) ? str : new Buffer(str, encoding);
};

var toAddress = function(wire) {
	if (typeof wire === 'string') return wire;
	return wire.peerAddress;
};

var onwire = function(swarm, connection, onhandshake, isServer) {
	var wire = peerWireProtocol(swarm._pwp);

	var destroy = function() {
		connection.destroy();
		connection.emit('timeout');
	};

	var connectTimeout = !isServer && setTimeout(destroy, swarm.connectTimeout);
	var handshakeTimeout = setTimeout(destroy, swarm.handshakeTimeout);

	if (handshakeTimeout.unref) handshakeTimeout.unref();
	if (connectTimeout.unref) connectTimeout.unref();

	connection.on('connect', function() {
		clearTimeout(connectTimeout);
	});

	wire.once('handshake', function(infoHash, peerId) {
		clearTimeout(handshakeTimeout);
		onhandshake(infoHash, peerId);
	});

	connection.on('end', function() {
		connection.destroy();
	});

	connection.on('error', function() {
		connection.destroy();
	});

	connection.on('close', function() {
		clearTimeout(connectTimeout);
		clearTimeout(handshakeTimeout);
		wire.destroy();
	});

	connection.pipe(wire).pipe(connection);
	return wire;
};

var pools = {};

var leave = function(port, swarm) {
	if (!pools[port]) return;
	delete pools[port].swarms[swarm.infoHash.toString('hex')];

	if (Object.keys(pools[port].swarms).length) return;
	pools[port].servers.forEach(function(server) {
		server.close();
	});
	delete pools[port];
};

var join = function(port, swarm) {
	var pool = pools[port];

	if (!pool) {
		var swarms = {};
		var servers = [];

		var onconnection = function(connection) {
			var wire = onwire(swarm, connection, function(infoHash, peerId) {
				var swarm = swarms[infoHash.toString('hex')];
				if (!swarm) return connection.destroy();
				swarm._onincoming(connection, wire);
			}, true);
		}

		servers.push(net.createServer(onconnection));
		if (swarm.utp) servers.push(utp.createServer(onconnection));

		var loop = function(i) {
			if (i < servers.length) return servers[i].listen(port, loop.bind(null, i+1))
			pool.listening = true;
			Object.keys(swarms).forEach(function(infoHash) {
				swarms[infoHash].emit('listening');
			});
		}

		loop(0)

		pool = pools[port] = {
			servers: servers,
			swarms: swarms,
			listening: false
		};
	}

	var infoHash = swarm.infoHash.toString('hex');

	if (pool.listening) {
		process.nextTick(function() {
			swarm.emit('listening');
		});
	}
	if (pool.swarms[infoHash]) {
		process.nextTick(function() {
			swarm.emit('error', new Error('port and info hash already in use'));
		});
		return;
	}

	pool.swarms[infoHash] = swarm;
};

var Swarm = function(infoHash, peerId, options) {
	if (!(this instanceof Swarm)) return new Swarm(infoHash, peerId, options);
	EventEmitter.call(this);

	options = options || {};
	this.handshake = options.handshake;

	this.port = 0;
	this.size = options.size || DEFAULT_SIZE;
	this.utp = options.utp || false;
	this.handshakeTimeout = options.handshakeTimeout || HANDSHAKE_TIMEOUT;
	this.connectTimeout = options.connectTimeout || CONNECTION_TIMEOUT;

	this.infoHash = toBuffer(infoHash, 'hex');
	this.peerId = toBuffer(peerId, 'utf-8');

	this.downloaded = 0;
	this.uploaded = 0;
	this.connections = [];
	this.wires = [];
	this.paused = false;

	this.uploaded = 0;
	this.downloaded = 0;

	this.downloadSpeed = speedometer();
	this.uploadSpeed = speedometer();

	this._destroyed = false;
	this._queues = [fifo()];
	this._peers = {};
	this._pwp = {speed:options.speed};
};

util.inherits(Swarm, EventEmitter);

Swarm.prototype.__defineGetter__('queued', function() {
	return this._queues.reduce(function(prev, queue) {
		return prev + queue.length;
	}, 0);
});

Swarm.prototype.pause = function() {
	this.paused = true;
};

Swarm.prototype.resume = function() {
	this.paused = false;
	this._drain();
};

Swarm.prototype.priority = function(addr, level) {
	addr = toAddress(addr);
	var peer = this._peers[addr];

	if (!peer) return 0;
	if (typeof level !== 'number' || peer.priority === level) return level;

	if (!this._queues[level]) this._queues[level] = fifo();

	if (peer.node) {
		this._queues[peer.priority].remove(peer.node);
		peer.node = this._queues[level].push(addr);
	}

	return peer.priority = level;
};

Swarm.prototype.add = function(addr) {
	if (this._destroyed || this._peers[addr]) return;

	var port = Number(addr.split(':')[1]);
	if (!(port > 0 && port < 65535)) return;

	this._peers[addr] = {
		node: this._queues[0].push(addr),
		wire: null,
		timeout: null,
		reconnect: false,
		priority: 0,
		retries: 0,
		noUtp: false,
	};

	this._drain();
};

Swarm.prototype.remove = function(addr) {
	this._remove(toAddress(addr));
	this._drain();
};

Swarm.prototype.listen = function(port, onlistening) {
	if (onlistening) this.once('listening', onlistening);
	this.port = port;
	join(this.port, this);
};

Swarm.prototype.destroy = function() {
	this._destroyed = true;

	var self = this;
	Object.keys(this._peers).forEach(function(addr) {
		self._remove(addr);
	});

	leave(this.port, this);
	process.nextTick(function() {
		self.emit('close');
	});
};

Swarm.prototype._remove = function(addr) {
	var peer = this._peers[addr];
	if (!peer) return;
	delete this._peers[addr];
	if (peer.node) this._queues[peer.priority].remove(peer.node);
	if (peer.timeout) clearTimeout(peer.timeout);
	if (peer.wire) peer.wire.destroy();
};

Swarm.prototype._drain = function() {
	if (this.connections.length >= this.size || this.paused) return;

	var self = this;
	var addr = this._shift();
	if (!addr) return;

	var peer = this._peers[addr];
	if (!peer) return;

	var repush = function() {
		peer.node = self._queues[peer.priority].push(addr);
		self._drain();
	};

	var parts = addr.split(':');
	var connection;

	if(this.utp && !peer.noUtp) {
		connection = utp.connect(parts[1], parts[0]);
		connection.on('timeout', function() {
			// Unable to connect to peer with uTP
			// Assume it doesn't support it.
			peer.noUtp = true;
			repush();
		});
	} else {
		connection = net.connect(parts[1], parts[0]);
	}

	if (peer.timeout) clearTimeout(peer.timeout);

	peer.node = null;
	peer.timeout = null;

	var wire = onwire(this, connection, function(infoHash) {
		if (infoHash.toString('hex') !== self.infoHash.toString('hex')) return connection.destroy();
		peer.reconnect = true;
		peer.retries = 0;
		self._onwire(connection, wire);
	});

	wire.on('close', function() {
		peer.wire = null;
		if (!peer.reconnect || self._destroyed || peer.retries >= RECONNECT_WAIT.length) return self._remove(addr);
		peer.timeout = setTimeout(repush, RECONNECT_WAIT[peer.retries++]);
	});

	peer.wire = wire;
	self._onconnection(connection);

	wire.peerAddress = addr;
	wire.handshake(this.infoHash, this.peerId, this.handshake);
};

Swarm.prototype._shift = function() {
	for (var i = this._queues.length-1; i >= 0; i--) {
		if (this._queues[i] && this._queues[i].length) return this._queues[i].shift();
	}
	return null;
};

Swarm.prototype._onincoming = function(connection, wire) {
	wire.peerAddress = connection.address().address + ':' + connection.address().port;
	wire.handshake(this.infoHash, this.peerId, this.handshake);

	this._onconnection(connection);
	this._onwire(connection, wire);
};

Swarm.prototype._onconnection = function(connection) {
	var self = this;

	connection.once('close', function() {
		self.connections.splice(self.connections.indexOf(connection), 1);
		self._drain();
	});

	this.connections.push(connection);
};

Swarm.prototype._onwire = function(connection, wire) {
	var self = this;

	wire.on('download', function(downloaded) {
		self.downloaded += downloaded;
		self.downloadSpeed(downloaded);
		self.emit('download', downloaded);
	});

	wire.on('upload', function(uploaded) {
		self.uploaded += uploaded;
		self.uploadSpeed(uploaded);
		self.emit('upload', uploaded);
	});

	var cleanup = once(function() {
		self.emit('wire-disconnect', wire, connection);
		self.wires.splice(self.wires.indexOf(wire), 1);
		connection.destroy();
	});

	connection.on('close', cleanup);
	connection.on('error', cleanup);
	connection.on('end', cleanup);
	wire.on('end', cleanup);
	wire.on('close', cleanup);
	wire.on('finish', cleanup);

	this.wires.push(wire);
	this.emit('wire', wire, connection);
};

module.exports = Swarm;
<commit_msg>add connection tries to peer-wire-swarm<commit_after>var utp = require('utp');
var net = require('net');
var fifo = require('fifo');
var once = require('once');
var speedometer = require('speedometer');
var peerWireProtocol = require('peer-wire-protocol');
var EventEmitter = require('events').EventEmitter;
var util = require('util');

var HANDSHAKE_TIMEOUT = 25000;
var CONNECTION_TIMEOUT = 3000;
var RECONNECT_WAIT = [4000, 8000, 12000];
var DEFAULT_SIZE = 100;

var toBuffer = function(str, encoding) {
	return Buffer.isBuffer(str) ? str : new Buffer(str, encoding);
};

var toAddress = function(wire) {
	if (typeof wire === 'string') return wire;
	return wire.peerAddress;
};

var onwire = function(swarm, connection, onhandshake, isServer) {
	var wire = peerWireProtocol(swarm._pwp);

	var destroy = function() {
		connection.destroy();
		connection.emit('timeout');
	};

	var connectTimeout = !isServer && setTimeout(destroy, swarm.connectTimeout);
	var handshakeTimeout = setTimeout(destroy, swarm.handshakeTimeout);

	if (handshakeTimeout.unref) handshakeTimeout.unref();
	if (connectTimeout.unref) connectTimeout.unref();

	connection.on('connect', function() {
		clearTimeout(connectTimeout);
	});

	wire.once('handshake', function(infoHash, peerId) {
		clearTimeout(handshakeTimeout);
		onhandshake(infoHash, peerId);
	});

	connection.on('end', function() {
		connection.destroy();
	});

	connection.on('error', function() {
		connection.destroy();
	});

	connection.on('close', function() {
		clearTimeout(connectTimeout);
		clearTimeout(handshakeTimeout);
		wire.destroy();
	});

	connection.pipe(wire).pipe(connection);
	return wire;
};

var pools = {};

var leave = function(port, swarm) {
	if (!pools[port]) return;
	delete pools[port].swarms[swarm.infoHash.toString('hex')];

	if (Object.keys(pools[port].swarms).length) return;
	pools[port].servers.forEach(function(server) {
		server.close();
	});
	delete pools[port];
};

var join = function(port, swarm) {
	var pool = pools[port];

	if (!pool) {
		var swarms = {};
		var servers = [];

		var onconnection = function(connection) {
			var wire = onwire(swarm, connection, function(infoHash, peerId) {
				var swarm = swarms[infoHash.toString('hex')];
				if (!swarm) return connection.destroy();
				swarm._onincoming(connection, wire);
			}, true);
		}

		servers.push(net.createServer(onconnection));
		if (swarm.utp) servers.push(utp.createServer(onconnection));

		var loop = function(i) {
			if (i < servers.length) return servers[i].listen(port, loop.bind(null, i+1))
			pool.listening = true;
			Object.keys(swarms).forEach(function(infoHash) {
				swarms[infoHash].emit('listening');
			});
		}

		loop(0)

		pool = pools[port] = {
			servers: servers,
			swarms: swarms,
			listening: false
		};
	}

	var infoHash = swarm.infoHash.toString('hex');

	if (pool.listening) {
		process.nextTick(function() {
			swarm.emit('listening');
		});
	}
	if (pool.swarms[infoHash]) {
		process.nextTick(function() {
			swarm.emit('error', new Error('port and info hash already in use'));
		});
		return;
	}

	pool.swarms[infoHash] = swarm;
};

var Swarm = function(infoHash, peerId, options) {
	if (!(this instanceof Swarm)) return new Swarm(infoHash, peerId, options);
	EventEmitter.call(this);

	options = options || {};
	this.handshake = options.handshake;

	this.port = 0;
	this.size = options.size || DEFAULT_SIZE;
	this.utp = options.utp || false;
	this.handshakeTimeout = options.handshakeTimeout || HANDSHAKE_TIMEOUT;
	this.connectTimeout = options.connectTimeout || CONNECTION_TIMEOUT;

	this.infoHash = toBuffer(infoHash, 'hex');
	this.peerId = toBuffer(peerId, 'utf-8');

	this.downloaded = 0;
	this.uploaded = 0;
	this.connections = [];
	this.wires = [];
	this.paused = false;

	this.tries = 0;

	this.uploaded = 0;
	this.downloaded = 0;

	this.downloadSpeed = speedometer();
	this.uploadSpeed = speedometer();

	this._destroyed = false;
	this._queues = [fifo()];
	this._peers = {};
	this._pwp = {speed:options.speed};
};

util.inherits(Swarm, EventEmitter);

Swarm.prototype.__defineGetter__('queued', function() {
	return this._queues.reduce(function(prev, queue) {
		return prev + queue.length;
	}, 0);
});

Swarm.prototype.pause = function() {
	this.paused = true;
};

Swarm.prototype.resume = function() {
	this.paused = false;
	this._drain();
};

Swarm.prototype.priority = function(addr, level) {
	addr = toAddress(addr);
	var peer = this._peers[addr];

	if (!peer) return 0;
	if (typeof level !== 'number' || peer.priority === level) return level;

	if (!this._queues[level]) this._queues[level] = fifo();

	if (peer.node) {
		this._queues[peer.priority].remove(peer.node);
		peer.node = this._queues[level].push(addr);
	}

	return peer.priority = level;
};

Swarm.prototype.add = function(addr) {
	if (this._destroyed || this._peers[addr]) return;

	var port = Number(addr.split(':')[1]);
	if (!(port > 0 && port < 65535)) return;

	this._peers[addr] = {
		node: this._queues[0].push(addr),
		wire: null,
		timeout: null,
		reconnect: false,
		priority: 0,
		retries: 0,
		noUtp: false,
	};

	this._drain();
};

Swarm.prototype.remove = function(addr) {
	this._remove(toAddress(addr));
	this._drain();
};

Swarm.prototype.listen = function(port, onlistening) {
	if (onlistening) this.once('listening', onlistening);
	this.port = port;
	join(this.port, this);
};

Swarm.prototype.destroy = function() {
	this._destroyed = true;

	var self = this;
	Object.keys(this._peers).forEach(function(addr) {
		self._remove(addr);
	});

	leave(this.port, this);
	process.nextTick(function() {
		self.emit('close');
	});
};

Swarm.prototype._remove = function(addr) {
	var peer = this._peers[addr];
	if (!peer) return;
	delete this._peers[addr];
	if (peer.node) this._queues[peer.priority].remove(peer.node);
	if (peer.timeout) clearTimeout(peer.timeout);
	if (peer.wire) peer.wire.destroy();
};

Swarm.prototype._drain = function() {
	if (this.connections.length >= this.size || this.paused) return;

	var self = this;
	var addr = this._shift();
	if (!addr) return;

	var peer = this._peers[addr];
	if (!peer) return;

	self.tries++;

	var repush = function() {
		peer.node = self._queues[peer.priority].push(addr);
		self._drain();
	};

	var parts = addr.split(':');
	var connection;

	if(this.utp && !peer.noUtp) {
		connection = utp.connect(parts[1], parts[0]);
		connection.on('timeout', function() {
			// Unable to connect to peer with uTP
			// Assume it doesn't support it.
			peer.noUtp = true;
			repush();
		});
	} else {
		connection = net.connect(parts[1], parts[0]);
	}

	if (peer.timeout) clearTimeout(peer.timeout);

	peer.node = null;
	peer.timeout = null;

	var wire = onwire(this, connection, function(infoHash) {
		if (infoHash.toString('hex') !== self.infoHash.toString('hex')) return connection.destroy();
		peer.reconnect = true;
		peer.retries = 0;
		self._onwire(connection, wire);
	});

	wire.on('close', function() {
		peer.wire = null;
		if (!peer.reconnect || self._destroyed || peer.retries >= RECONNECT_WAIT.length) return self._remove(addr);
		peer.timeout = setTimeout(repush, RECONNECT_WAIT[peer.retries++]);
	});

	peer.wire = wire;
	self._onconnection(connection);

	wire.peerAddress = addr;
	wire.handshake(this.infoHash, this.peerId, this.handshake);
};

Swarm.prototype._shift = function() {
	for (var i = this._queues.length-1; i >= 0; i--) {
		if (this._queues[i] && this._queues[i].length) return this._queues[i].shift();
	}
	return null;
};

Swarm.prototype._onincoming = function(connection, wire) {
	wire.peerAddress = connection.address().address + ':' + connection.address().port;
	wire.handshake(this.infoHash, this.peerId, this.handshake);

	this._onconnection(connection);
	this._onwire(connection, wire);
};

Swarm.prototype._onconnection = function(connection) {
	var self = this;

	connection.once('close', function() {
		self.connections.splice(self.connections.indexOf(connection), 1);
		self._drain();
	});

	this.connections.push(connection);
};

Swarm.prototype._onwire = function(connection, wire) {
	var self = this;

	wire.on('download', function(downloaded) {
		self.downloaded += downloaded;
		self.downloadSpeed(downloaded);
		self.emit('download', downloaded);
	});

	wire.on('upload', function(uploaded) {
		self.uploaded += uploaded;
		self.uploadSpeed(uploaded);
		self.emit('upload', uploaded);
	});

	var cleanup = once(function() {
		self.emit('wire-disconnect', wire, connection);
		self.wires.splice(self.wires.indexOf(wire), 1);
		connection.destroy();
	});

	connection.on('close', cleanup);
	connection.on('error', cleanup);
	connection.on('end', cleanup);
	wire.on('end', cleanup);
	wire.on('close', cleanup);
	wire.on('finish', cleanup);

	this.wires.push(wire);
	this.emit('wire', wire, connection);
};

module.exports = Swarm;
<|endoftext|>


<commit_before>namespace('Sy');

Sy.EntityInterface = function () {

};

Sy.EntityInterface.prototype = Object.create(Object.prototype, {

    set: {
        value: function (attr, value) {

            return this;

        }
    },

    get: {
        value: function (attr) {}
    },

    register: {
        value: function (attr) {}
    }

});<commit_msg>#4 modified definition to match specifications<commit_after>namespace('Sy');

/**
 * Entity interface
 *
 * @package Sy
 * @interface
 */

Sy.EntityInterface = function () {

};

Sy.EntityInterface.prototype = Object.create(Object.prototype, {

    /**
     * Set an attribute value to the entity
     *
     * @param {string} attr
     * @param {mixed} value
     *
     * @return {Sy.EntityInterface}
     */

    set: {
        value: function (attr, value) {

            return this;

        }
    },

    /**
     * Return an attribute value
     *
     * @param {string} attr
     *
     * @return {mixed}
     */

    get: {
        value: function (attr) {}
    },

    /**
     * Register an attribute as index or as a connection to another entity
     *
     * @param {string} attr
     * @param {string} entity If set it will link the attribute to another entity, this param must follow this pattern: \w+::\w+
     *
     * @return {Sy.EntityInterface}
     */

    register: {
        value: function (attr, entity) {}
    },

    /**
     * Block the available attributes for this entity. Once set, the list won't be mutable.
     *
     * @param {Array} attributes
     *
     * @return {Sy.EntityInterface}
     */

    lock: {
        value: function (attributes) {}
    }

});<|endoftext|>


<commit_before>function observeMergeButton() {
  var target = document.querySelector('body');
  var config = {
    childList: true,
    subtree: true,
    characterData: true
  };

  var observer = new MutationObserver(function(mutations, self) {
    mutations.forEach(function(mutation) {
      if (mutation.type === 'childList') {
        var elements = document.querySelectorAll('.merge-branch-action');
        Array.prototype.forEach.call(elements, function(element) {
          if (document.getElementsByClassName("js-issue-title")[0].textContent.indexOf("WIP") > -1) {
            if (element.className.indexOf("primary") > -1) {
              element.className = element.className.replace(/primary/g, 'disabled').replace(/js-details-target/g, '');
            }
          } else {
            if (element.className.indexOf("disabled") > -1) {
              element.className = element.className.replace(/disabled/g, 'primary js-details-target');
            }
          }
        });
      }
    });
  });

  observer.observe(target, config);
}

window.onload = observeMergeButton;
<commit_msg>extract toggleMergeButton method<commit_after>function toggleMergeButton(element) {
  if (document.getElementsByClassName("js-issue-title")[0].textContent.indexOf("WIP") > -1) {
    if (element.className.indexOf("primary") > -1) {
      element.className = element.className.replace(/primary/g, 'disabled').replace(/js-details-target/g, '');
    }
  } else {
    if (element.className.indexOf("disabled") > -1) {
      element.className = element.className.replace(/disabled/g, 'primary js-details-target');
    }
  }
}

function observeMergeButton() {
  var target = document.querySelector('body');
  var config = {
    childList: true,
    subtree: true,
    characterData: true
  };

  var observer = new MutationObserver(function(mutations, self) {
    mutations.forEach(function(mutation) {
      if (mutation.type === 'childList') {
        var elements = document.querySelectorAll('.merge-branch-action');
        Array.prototype.forEach.call(elements, function(element) {
          toggleMergeButton(element);
        });
      }
    });
  });

  observer.observe(target, config);
}

window.onload = observeMergeButton;
<|endoftext|>


<commit_before>/**
 * Created by 이호세아 on 2016-05-17.
 */

angular.module("homeApp", [
    'chart.js',
    'ngAnimate',
    'ui.router',
    'ngFileUpload',
    'angular-storage',
    'ui.bootstrap',
    'angular-jqcloud',
    'ui.bootstrap.alert',
    'angular-confirm',
    'duScroll'
])

    .config(function (storeProvider) {
        storeProvider.setStore('sessionStorage');
    })
    .controller("findPASSCtrl", __FindPassCtrl)
    .controller("joinCtrl", __JoinCtrl)
    .controller("leftSideBarCtrl", __LeftSidebarCtrl)
    .controller("loginCtrl", __LoginCtrl)
    .controller("indexCtrl", __IndexCtrl)
    .controller("diaryCtrl", __DiaryCtrl)
    .controller("diaryManageCtrl", __DiaryManageCtrl)
    .controller("patientEvaluateCtrl", __PatientEvaluateCtrl)
    .controller("patientListCtrl", __PatientListCtrl)
    .controller("patientManageCtrl", __PatientManageCtrl)
    .controller("statusCtrl", __StatusCtrl)
    .controller("diaryDetailCtrl", __DiaryDetailCtrl)

    .controller('scroll', function ($scope, $document) {
            $scope.toTheTop = function () {
                $document.scrollTopAnimated(0, 5000).then(function () {
                    console && console.log('You just scrolled to the top!');
                });
            }
            var section3 = angular.element(document.getElementById('section-3'));
            $scope.toSection3 = function () {
                $document.scrollToElementAnimated(section3);
            }
        }
    ).value('duScrollOffset', 30)

    .run(function ($rootScope, $state, store) {
        $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
            var requireLogin = toState.data.requireLogin;
            if (requireLogin && store.get('obj') == null) {
                event.preventDefault();
                $state.go('login');
            }
        });
    })

    .filter('unique', function () {
        return function (collection, keyname) {
            var output = [],
                keys = [];

            angular.forEach(collection, function (item) {
                var key = item[keyname];
                if (keys.indexOf(key) === -1) {
                    keys.push(key);
                    output.push(item);
                }
            });

            return output;
        };
    })

    //게시물을 end 숫자 까지 잘라서 보여줌
    .filter('slice', function () {
        return function (arr, start, end) {
            return arr.slice(start, end);
        };
    })

    //스크롤 이벤트가 필요한 부분만 추가한다.
    .directive("scroll", function ($window) {
        return function (scope, element, attrs) {
            angular.element($window).bind("scroll", function () {

                var windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
                var body = document.body, html = document.documentElement;
                var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
                var windowBottom = windowHeight + window.pageYOffset;
                if (windowBottom >= docHeight) {
                    scope.quantity = scope.quantity + 4;
                }
                scope.$apply();
            });
        };
    })

    //윈도우 크기 재구성
    .directive('resize', function ($window) {
        return function (scope, element) {
            var w = angular.element($window);
            scope.getWindowDimensions = function () {
                return {
                    'h': w.height(),
                    'w': w.width()
                };
            };
            scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
                scope.windowHeight = newValue.h;
                scope.windowWidth = newValue.w;

                scope.style = function () {
                    return {
                        'height': (newValue.h - 100) + 'px',
                        'width': (newValue.w - 100) + 'px'
                    };
                };

            }, true);

            w.bind('resize', function () {
                scope.$apply();
            });
        }
    })

    // 댓글 엔터 입력 처리
    .directive('ngEnter', function () {
        return function (scope, element, attrs) {
            element.bind("keydown keypress", function (event) {
                if (event.which === 13) {
                    scope.$apply(function () {
                        scope.$eval(attrs.ngEnter);
                    });
                    event.preventDefault();
                }
            });
        };
    })

    .constant('HOST', 'http://localhost:8080')
    // .constant('HOST', 'http://52.41.218.18:8080')

    .config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
        $stateProvider
            .state('login', {
                url: '/',
                templateUrl: 'login.html',
                controller: 'loginCtrl',
                controllerAs: 'loginCtrl',
                data: {
                    requireLogin: false
                }
            })

            .state('re_login', {
                url: '/',
                templateUrl: 'login.html',
                controller: 'loginCtrl',
                controllerAs: 'loginCtrl',
                data: {
                    requireLogin: false
                }
            })

            .state('main', {
                url: '/main',
                templateUrl: 'main.html',
                controller: 'indexCtrl',
                controllerAs: 'index',
                data: {
                    requireLogin: true
                }
            })

        .state('diary', {
            url: '/diary',
            templateUrl: 'diary.html',
            controller: 'diaryCtrl',
            controllerAs: 'diary',
            data: {
                requireLogin: true
            }
        })

            .state('diaryDetail', {
                url: '/diaryDetail',
                templateUrl: 'diaryDetail.html',
                controller: 'diaryDetailCtrl',
                controllerAs: 'diaryDetail',
                data: {
                    requireLogin: true
                }
            })

            .state('diaryManage', {
            url: '/diaryManage',
            templateUrl: 'diaryManage.html',
            controller: 'diaryManageCtrl',
            controllerAs: 'diaryManage',
            data: {
                requireLogin: true
            }
        })

        .state('patientEvaluate', {
            url: '/patientEvaluate',
            templateUrl: 'patientEvaluate.html',
            controller: 'patientEvaluateCtrl',
            controllerAs: 'patientEvaluate',
            data: {
                requireLogin: true
            }
        })

        .state('patientList', {
            url: '/patientList',
            templateUrl: 'patientList.html',
            controller: 'patientListCtrl',
            controllerAs: 'patientList',
            data: {
                requireLogin: true
            }
        })

        .state('patientManage', {
            url: '/patientManage',
            templateUrl: 'patientManage.html',
            controller: 'patientManageCtrl',
            controllerAs: 'patientManage',
            data: {
                requireLogin: true
            }
        })

        .state('status', {
            url: '/status',
            templateUrl: 'status.html',
            controller: 'statusCtrl',
            controllerAs: 'status',
            data: {
                requireLogin: true
            }
        });

        $urlRouterProvider.otherwise('/');
        $httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
    })
    .factory('Excel',function($window){
        var uri='data:application/vnd.ms-excel;base64,',
            template=' <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
{table}
',
            base64=function(s){return $window.btoa(unescape(encodeURIComponent(s)));},
            format=function(s,c){return s.replace(/{(\w+)}/g,function(m,p){return c[p];})};
        return {
            tableToExcel:function(tableId,worksheetName){
                var table=$(tableId),
                    ctx={worksheet:worksheetName,table:table.html()},
                    href=uri+base64(format(template,ctx));
                return href;
            }
        };
    });

<commit_msg>IP주소 수정<commit_after>/**
 * Created by 이호세아 on 2016-05-17.
 */

angular.module("homeApp", [
    'chart.js',
    'ngAnimate',
    'ui.router',
    'ngFileUpload',
    'angular-storage',
    'ui.bootstrap',
    'angular-jqcloud',
    'ui.bootstrap.alert',
    'angular-confirm',
    'duScroll'
])

    .config(function (storeProvider) {
        storeProvider.setStore('sessionStorage');
    })
    .controller("findPASSCtrl", __FindPassCtrl)
    .controller("joinCtrl", __JoinCtrl)
    .controller("leftSideBarCtrl", __LeftSidebarCtrl)
    .controller("loginCtrl", __LoginCtrl)
    .controller("indexCtrl", __IndexCtrl)
    .controller("diaryCtrl", __DiaryCtrl)
    .controller("diaryManageCtrl", __DiaryManageCtrl)
    .controller("patientEvaluateCtrl", __PatientEvaluateCtrl)
    .controller("patientListCtrl", __PatientListCtrl)
    .controller("patientManageCtrl", __PatientManageCtrl)
    .controller("statusCtrl", __StatusCtrl)
    .controller("diaryDetailCtrl", __DiaryDetailCtrl)

    .controller('scroll', function ($scope, $document) {
            $scope.toTheTop = function () {
                $document.scrollTopAnimated(0, 5000).then(function () {
                    console && console.log('You just scrolled to the top!');
                });
            }
            var section3 = angular.element(document.getElementById('section-3'));
            $scope.toSection3 = function () {
                $document.scrollToElementAnimated(section3);
            }
        }
    ).value('duScrollOffset', 30)

    .run(function ($rootScope, $state, store) {
        $rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
            var requireLogin = toState.data.requireLogin;
            if (requireLogin && store.get('obj') == null) {
                event.preventDefault();
                $state.go('login');
            }
        });
    })

    .filter('unique', function () {
        return function (collection, keyname) {
            var output = [],
                keys = [];

            angular.forEach(collection, function (item) {
                var key = item[keyname];
                if (keys.indexOf(key) === -1) {
                    keys.push(key);
                    output.push(item);
                }
            });

            return output;
        };
    })

    //게시물을 end 숫자 까지 잘라서 보여줌
    .filter('slice', function () {
        return function (arr, start, end) {
            return arr.slice(start, end);
        };
    })

    //스크롤 이벤트가 필요한 부분만 추가한다.
    .directive("scroll", function ($window) {
        return function (scope, element, attrs) {
            angular.element($window).bind("scroll", function () {

                var windowHeight = "innerHeight" in window ? window.innerHeight : document.documentElement.offsetHeight;
                var body = document.body, html = document.documentElement;
                var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
                var windowBottom = windowHeight + window.pageYOffset;
                if (windowBottom >= docHeight) {
                    scope.quantity = scope.quantity + 4;
                }
                scope.$apply();
            });
        };
    })

    //윈도우 크기 재구성
    .directive('resize', function ($window) {
        return function (scope, element) {
            var w = angular.element($window);
            scope.getWindowDimensions = function () {
                return {
                    'h': w.height(),
                    'w': w.width()
                };
            };
            scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
                scope.windowHeight = newValue.h;
                scope.windowWidth = newValue.w;

                scope.style = function () {
                    return {
                        'height': (newValue.h - 100) + 'px',
                        'width': (newValue.w - 100) + 'px'
                    };
                };

            }, true);

            w.bind('resize', function () {
                scope.$apply();
            });
        }
    })

    // 댓글 엔터 입력 처리
    .directive('ngEnter', function () {
        return function (scope, element, attrs) {
            element.bind("keydown keypress", function (event) {
                if (event.which === 13) {
                    scope.$apply(function () {
                        scope.$eval(attrs.ngEnter);
                    });
                    event.preventDefault();
                }
            });
        };
    })

    // .constant('HOST', 'http://localhost:8080')
    .constant('HOST', 'http://52.41.218.18:8080')

    .config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
        $stateProvider
            .state('login', {
                url: '/',
                templateUrl: 'login.html',
                controller: 'loginCtrl',
                controllerAs: 'loginCtrl',
                data: {
                    requireLogin: false
                }
            })

            .state('re_login', {
                url: '/',
                templateUrl: 'login.html',
                controller: 'loginCtrl',
                controllerAs: 'loginCtrl',
                data: {
                    requireLogin: false
                }
            })

            .state('main', {
                url: '/main',
                templateUrl: 'main.html',
                controller: 'indexCtrl',
                controllerAs: 'index',
                data: {
                    requireLogin: true
                }
            })

        .state('diary', {
            url: '/diary',
            templateUrl: 'diary.html',
            controller: 'diaryCtrl',
            controllerAs: 'diary',
            data: {
                requireLogin: true
            }
        })

            .state('diaryDetail', {
                url: '/diaryDetail',
                templateUrl: 'diaryDetail.html',
                controller: 'diaryDetailCtrl',
                controllerAs: 'diaryDetail',
                data: {
                    requireLogin: true
                }
            })

            .state('diaryManage', {
            url: '/diaryManage',
            templateUrl: 'diaryManage.html',
            controller: 'diaryManageCtrl',
            controllerAs: 'diaryManage',
            data: {
                requireLogin: true
            }
        })

        .state('patientEvaluate', {
            url: '/patientEvaluate',
            templateUrl: 'patientEvaluate.html',
            controller: 'patientEvaluateCtrl',
            controllerAs: 'patientEvaluate',
            data: {
                requireLogin: true
            }
        })

        .state('patientList', {
            url: '/patientList',
            templateUrl: 'patientList.html',
            controller: 'patientListCtrl',
            controllerAs: 'patientList',
            data: {
                requireLogin: true
            }
        })

        .state('patientManage', {
            url: '/patientManage',
            templateUrl: 'patientManage.html',
            controller: 'patientManageCtrl',
            controllerAs: 'patientManage',
            data: {
                requireLogin: true
            }
        })

        .state('status', {
            url: '/status',
            templateUrl: 'status.html',
            controller: 'statusCtrl',
            controllerAs: 'status',
            data: {
                requireLogin: true
            }
        });

        $urlRouterProvider.otherwise('/');
        $httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = '*';
    })
    .factory('Excel',function($window){
        var uri='data:application/vnd.ms-excel;base64,',
            template=' <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
{table}
',
            base64=function(s){return $window.btoa(unescape(encodeURIComponent(s)));},
            format=function(s,c){return s.replace(/{(\w+)}/g,function(m,p){return c[p];})};
        return {
            tableToExcel:function(tableId,worksheetName){
                var table=$(tableId),
                    ctx={worksheet:worksheetName,table:table.html()},
                    href=uri+base64(format(template,ctx));
                return href;
            }
        };
    });

<|endoftext|>


<commit_before>#!/usr/bin/env node

/*
	load config
	start service
 */

var express = require('express'),
	app = express(),
	https = require('https'),
	server = require('http').createServer(app),
	secureServer,
	log4js = require('log4js'),
	pack = require('../package'),
	program = require('commander'),
	fs = require('fs'),
	path = require('path'),
	config = require('../services/ConfigLoader.js')(program),
	web = require('../services/WebServer.js'),
	socket = require('../services/SocketServer.js'),
	push = require('../services/PushServer.js'),
	oauth = require('../services/OAuthServer.js'),
	twitter = require('../services/TwitterMonitor.js'),
	ssl;

program.version(pack.version)
	.option("-c --config <configPath>", "Path to config file")
	.parse(process.argv);

var configPath = program.config || './config.private';
config.initialize(configPath);
config.path = configPath + '/';

(function(fullconfig) {
	var _config = fullconfig.get('ssl');
	_config.path = fullconfig.path;

	// check Key file & Certificate file
	if(fs.existsSync(_config.path + _config.key) && fs.existsSync(_config.path + _config.cert)) {
		ssl = {};
		_config.key && (ssl.key = fs.readFileSync(_config.path + _config.key));
		_config.cert && (ssl.cert = fs.readFileSync(_config.path + _config.cert));
		_config.ca && (ssl.ca = fs.readFileSync(_config.path + _config.ca));
		_config.requestCert && (ssl.requestCert = _config.requestCert);
		_config.rejectUnauthorized && (ssl.rejectUnauthorized = _config.rejectUnauthorized);
		_config.passphrase && (ssl.passphrase = _config.passphrase);
	}
	else {
		ssl = false;
	}
})(config);

log4js.configure(config.get('log4js'));
var logger = log4js.getLogger('Kamato.INFO');
logger.setLevel('INFO');

ssl && (secureServer = secureServer = https.createServer(ssl, app));

web.configure(config, app, server, secureServer, oauth, log4js, logger);
socket.configure(config, server, secureServer, logger);
push.configure(config, logger);
twitter.configure(config, logger);

socket.start();
//twitter.start();
web.start();<commit_msg>Debug<commit_after>#!/usr/bin/env node

/*
	load config
	start service
 */

var express = require('express'),
	app = express(),
	https = require('https'),
	server = require('http').createServer(app),
	secureServer,
	log4js = require('log4js'),
	pack = require('../package'),
	program = require('commander'),
	fs = require('fs'),
	path = require('path'),
	config = require('../services/ConfigLoader.js')(program),
	web = require('../services/WebServer.js'),
	socket = require('../services/SocketServer.js'),
	push = require('../services/PushServer.js'),
	oauth = require('../services/OAuthServer.js'),
	twitter = require('../services/TwitterMonitor.js'),
	ssl;

program.version(pack.version)
	.option("-c --config <configPath>", "Path to config file")
	.parse(process.argv);

var configPath = program.config || './config.private';
config.initialize(configPath);
config.path = configPath + '/';

(function(fullconfig) {
	var _config = fullconfig.get('ssl');
	_config.path = fullconfig.path;

	// check Key file & Certificate file
	if(fs.existsSync(_config.path + _config.key) && fs.existsSync(_config.path + _config.cert)) {
		ssl = {};
		_config.key && (ssl.key = fs.readFileSync(_config.path + _config.key));
		_config.cert && (ssl.cert = fs.readFileSync(_config.path + _config.cert));
		_config.ca && (ssl.ca = fs.readFileSync(_config.path + _config.ca));
		_config.requestCert && (ssl.requestCert = _config.requestCert);
		_config.rejectUnauthorized && (ssl.rejectUnauthorized = _config.rejectUnauthorized);
		_config.passphrase && (ssl.passphrase = _config.passphrase);
	}
	else {
		ssl = false;
	}
})(config);

log4js.configure(config.get('log4js'));
var logger = log4js.getLogger('Kamato.INFO');
logger.setLevel('INFO');

ssl && (secureServer = https.createServer(ssl, app));

web.configure(config, app, server, secureServer, oauth, log4js, logger);
socket.configure(config, server, secureServer, logger);
push.configure(config, logger);
twitter.configure(config, logger);

socket.start();
//twitter.start();
web.start();<|endoftext|>


<commit_before>var vows = require('vows'),
    assert = require('assert');

d3 = require('d3');

var grid = require("../d3.layout.grid.js");

vows.describe('d3.layout.grid').addBatch({
  'Grid layout' : {
    topic: function() { return d3.layout.grid; },
    'equally distributes 4 nodes within a 1x1 space, left to right, top to bottom': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    '1 data point is in the center (is this good or should it be at [0,0]?)': function(grid) {
      var l = grid().points();
      var nodes = [{}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0.5, y: 0.5}
      ]);
    },
    'equally distributes 5 nodes within a 1x1 space': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 0.5, y: 1}
      ]);
    },
    'equally distributes 5 nodes within a 300x500 space': function(grid) {
      var l = grid().points()
        .size([300, 500]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 150, y: 0},
        {x: 300, y: 0},
        {x: 0, y: 500},
        {x: 150, y: 500}
      ]);
    },
    'fixed amount of cols': function(grid) {
      var l = grid().points().cols(2);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);
    },
    'fixed amount of rows': function(grid) {
      var l = grid().points().rows(3);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);
    },
    'fixed amount of cols and rows': function(grid) {
      var l = grid().points().cols(2).rows(5);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.25},
        {x: 1, y: 0.25},
        {x: 0, y: 0.5}
      ]);
    },
    '1 row': function(grid) {
      var l = grid().points().rows(1);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0.5},
        {x: 0.25, y: 0.5},
        {x: 0.5, y: 0.5},
        {x: 0.75, y: 0.5},
        {x: 1, y: 0.5}
      ]);
    },
    'fixed node sizes': function(grid) {
      var l = grid().points().nodeSize([1, 1]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.equal(l.size(), null);
      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 2, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    'reset rows/cols after each call': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 0.5, y: 1}
      ]);

      nodes = [{}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    'fixed amount of cols stays the same': function(grid) {
      var l = grid().points().cols(2);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);

      nodes = [{}, {}, {}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1/3},
        {x: 1, y: 1/3},
        {x: 0, y: 2/3},
        {x: 1, y: 2/3},
        {x: 0, y: 1},

      ]);
    },
    'bands': function(grid) {
      var l = grid().bands();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1/3, y: 0},
        {x: 2/3, y: 0},
        {x: 0, y: 0.5},
        {x: 1/3, y: 0.5}
      ]);

      l.cols(2);

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 0, y: 1/3},
        {x: 0.5, y: 1/3},
        {x: 0, y: 2/3}
      ]);
    },
    'bands with padding': function(grid) {
      var l = grid().bands().padding([0.5, 0.5]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.4, y: 0},
        {x: 0.8, y: 0},
        {x: 0, y: 2/3},
        {x: 0.4, y: 2/3}
      ]);

      l.cols(2);

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 2/3, y: 0},
        {x: 0, y: 0.4},
        {x: 2/3, y: 0.4},
        {x: 0, y: 0.8}
      ]);
    }
  }
}).export(module);

function layout(node) {
  return {
    x: node.x,
    y: node.y
  };
}<commit_msg>Add failing test for filling order if rows are fixed<commit_after>var vows = require('vows'),
    assert = require('assert');

d3 = require('d3');

var grid = require("../d3.layout.grid.js");

vows.describe('d3.layout.grid').addBatch({
  'Grid layout' : {
    topic: function() { return d3.layout.grid; },
    'equally distributes 4 nodes within a 1x1 space, left to right, top to bottom': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    '1 data point is in the center (is this good or should it be at [0,0]?)': function(grid) {
      var l = grid().points();
      var nodes = [{}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0.5, y: 0.5}
      ]);
    },
    'equally distributes 5 nodes within a 1x1 space': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 0.5, y: 1}
      ]);
    },
    'equally distributes 5 nodes within a 300x500 space': function(grid) {
      var l = grid().points()
        .size([300, 500]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 150, y: 0},
        {x: 300, y: 0},
        {x: 0, y: 500},
        {x: 150, y: 500}
      ]);
    },
    'fixed amount of cols': function(grid) {
      var l = grid().points().cols(2);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);
    },
    'fixed amount of rows': function(grid) {
      var l = grid().points().rows(3);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);
    },
    'fixed amount of cols and rows': function(grid) {
      var l = grid().points().cols(2).rows(5);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.25},
        {x: 1, y: 0.25},
        {x: 0, y: 0.5}
      ]);
    },
    '1 row': function(grid) {
      var l = grid().points().rows(1);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0.5},
        {x: 0.25, y: 0.5},
        {x: 0.5, y: 0.5},
        {x: 0.75, y: 0.5},
        {x: 1, y: 0.5}
      ]);
    },
    // TODO: This needs some more thought ...
    // '4 rows, 5 data points': function(grid) {
    //   var l = grid().points().rows(4);
    //   var nodes = [{}, {}, {}, {}, {}];

    //   assert.deepEqual(l(nodes).map(layout), [
    //     {x: 0, y: 0},
    //     {x: 0, y: 1/3},
    //     {x: 0, y: 2/3},
    //     {x: 0, y: 1},
    //     {x: 1, y: 0}
    //   ]);
    // },
    'fixed node sizes': function(grid) {
      var l = grid().points().nodeSize([1, 1]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.equal(l.size(), null);
      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 2, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    'reset rows/cols after each call': function(grid) {
      var l = grid().points();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 0.5, y: 1}
      ]);

      nodes = [{}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1},
        {x: 1, y: 1}
      ]);
    },
    'fixed amount of cols stays the same': function(grid) {
      var l = grid().points().cols(2);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 0.5},
        {x: 1, y: 0.5},
        {x: 0, y: 1}
      ]);

      nodes = [{}, {}, {}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1, y: 0},
        {x: 0, y: 1/3},
        {x: 1, y: 1/3},
        {x: 0, y: 2/3},
        {x: 1, y: 2/3},
        {x: 0, y: 1},

      ]);
    },
    'bands': function(grid) {
      var l = grid().bands();
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 1/3, y: 0},
        {x: 2/3, y: 0},
        {x: 0, y: 0.5},
        {x: 1/3, y: 0.5}
      ]);

      l.cols(2);

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.5, y: 0},
        {x: 0, y: 1/3},
        {x: 0.5, y: 1/3},
        {x: 0, y: 2/3}
      ]);
    },
    'bands with padding': function(grid) {
      var l = grid().bands().padding([0.5, 0.5]);
      var nodes = [{}, {}, {}, {}, {}];

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 0.4, y: 0},
        {x: 0.8, y: 0},
        {x: 0, y: 2/3},
        {x: 0.4, y: 2/3}
      ]);

      l.cols(2);

      assert.deepEqual(l(nodes).map(layout), [
        {x: 0, y: 0},
        {x: 2/3, y: 0},
        {x: 0, y: 0.4},
        {x: 2/3, y: 0.4},
        {x: 0, y: 0.8}
      ]);
    }
  }
}).export(module);

function layout(node) {
  return {
    x: node.x,
    y: node.y
  };
}<|endoftext|>


<commit_before>'use strict';

// cahcing some jQuery references
// ------------------------------
var $news = $('.news')

// hacking into jQuery ajax to be notified
// once the pagination ajax completed
, onPaginationComplete = function() {
    getAvatarsForUsers( function( data ) {
        printImages( data.items );
    });
}

// generate search url for a
// list of github usernames
// ------------------------
, generateUrl = function( array, pagination ) {
    for( var i in array ) {
        array[ i ] = 'user%3A' + array[ i ];
    }
    return '//api.github.com/search/users?q=' + array.join( '+' ) + ( pagination ? '&per_page=' + pagination : '' );
}

// drop duplicated items from an array
// -----------------------------------
, unique = function( array ) {
    var temp = {};
    for( var i in array ) {
        temp[ array[i] ] = {};
    }
    return Object.keys( temp );
}

// get new users
// -------------
, prepareNewUsersOnPage = function() {
    var users = $news.find('.alert').not('.push, .avatar-ready').find('.title a:eq(0)').map(function() {
        var $self = $(this)
        , username = $self.text();

        $self.addClass(username);

        $self.parent().addClass('avatar-container')

        // store username
        $self.closest('.alert')
            .attr('data-username', username);

        return username;
    }).toArray();

    return unique( users );
}

// for debugging
// print all users gravatars into DOM
// ----------------------------------
, printImages = function( items ) {
    for( var item in items ) {
        var $img = $('<img />').addClass('github-avatar').attr( 'src', items[ item ].avatar_url );

        $('.alert:not(.avatar-ready) .' + items[ item ].login ).each(function() {
            var $self = $(this);

            $img.clone().insertBefore( $self );
            $self.closest( '.alert' ).addClass('avatar-ready');
        });
    }
}

, getAvatarsForUsers = function( callback ) {
    $.get( generateUrl( prepareNewUsersOnPage(), 31 ), callback );
}

// tricking first element in feed
// ------------------------------
var $first = $('.news .alert').eq(0)
, $clone;

$first.clone().insertBefore($first);
$clone = $first.prev();
$first.css('border', 'none');
$clone.css({
      height: 0
    , padding: 0
});

// query github API
// ----------------
getAvatarsForUsers( function( data ) {
    printImages( data.items );
});

// hacking into pagination calls
// -----------------------------
// since we don't have access to github's
// jQuery object, we'll do a workaround here
$news.on('click', '.js-events-pagination', function() {

    console.info('waiting for a pagination to complete');

    var $button = $(this)
    , $container = $button.parent()
    , id = setInterval(function() {
        if( !$container.hasClass('loading') ) {
            clearInterval(id);
            onPaginationComplete();
            console.info('pagination completed');
        } else {
            console.info('waiting...');
        }
    }, 500);
});<commit_msg>cleanup<commit_after>'use strict';

// cahcing some jQuery references
// ------------------------------
var $news = $('.news')

// hacking into jQuery ajax to be notified
// once the pagination ajax completed
, onPaginationComplete = function() {
    getAvatarsForUsers( function( data ) {
        printImages( data.items );
    });
}

// generate search url for a
// list of github usernames
// ------------------------
, generateUrl = function( array, pagination ) {
    for( var i in array ) {
        array[ i ] = 'user%3A' + array[ i ];
    }
    return '//api.github.com/search/users?q=' + array.join( '+' ) + ( pagination ? '&per_page=' + pagination : '' );
}

// drop duplicated items from an array
// -----------------------------------
, unique = function( array ) {
    var temp = {};
    for( var i in array ) {
        temp[ array[i] ] = {};
    }
    return Object.keys( temp );
}

// get new users
// -------------
, prepareNewUsersOnPage = function() {
    var users = $news.find('.alert').not('.push, .avatar-ready').find('.title a:eq(0)').map(function() {
        var $self = $(this)
        , username = $self.text();

        $self.addClass(username);

        $self.parent().addClass('avatar-container')

        // store username
        $self.closest('.alert')
            .attr('data-username', username);

        return username;
    }).toArray();

    return unique( users );
}

// print all users gravatars into DOM
// ----------------------------------
, printImages = function( items ) {
    for( var item in items ) {
        var $img = $('<img />').addClass('github-avatar').attr( 'src', items[ item ].avatar_url );

        $('.alert:not(.avatar-ready) .' + items[ item ].login ).each(function() {
            var $self = $(this);

            $img.clone().insertBefore( $self );
            $self.closest( '.alert' ).addClass('avatar-ready');
        });
    }
}

, getAvatarsForUsers = function( callback ) {
    $.get( generateUrl( prepareNewUsersOnPage(), 31 ), callback );
}

// tricking first element in feed
// ------------------------------
, $first = $('.news .alert').eq(0)
, $clone;

$first.clone().insertBefore($first);
$clone = $first.prev();
$first.css('border', 'none');
$clone.css({
      height: 0
    , padding: 0
});

// query github API
// ----------------
getAvatarsForUsers( function( data ) {
    printImages( data.items );
});

// hacking into pagination calls
// -----------------------------
// since we don't have access to github's
// jQuery object, we'll do a workaround here
$news.on('click', '.js-events-pagination', function() {

    console.info('waiting for a pagination to complete');

    var $button = $(this)
    , $container = $button.parent()

    , id = setInterval(function() {

        if( !$container.hasClass('loading') ) {
            clearInterval(id);
            onPaginationComplete();
            console.info('pagination completed');
        } else {
            console.info('waiting...');
        }

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