text:
layout: page
title: Rose Ho's 103rd Birthday
date: 2016-05-24
author: Amy Frost
tags: weekly links, java
status: published
summary: In iaculis ultricies molestie. In nulla nisl.
banner: images/banner/leisure-02.jpg
booking:
  startDate: 12/09/2017
  endDate: 12/14/2017
  ctyhocn: DYLPAHX
  groupCode: RH1B
published: true
---
Vestibulum mollis est nec efficitur commodo. Etiam posuere nisl quis lorem varius, sagittis egestas risus dapibus. Quisque faucibus ante lacus, ac tincidunt quam hendrerit vel. Proin enim risus, porttitor ac eleifend sed, venenatis eu justo. In pellentesque magna et felis consequat, ac scelerisque tellus lobortis. Duis nulla orci, placerat quis leo vitae, tincidunt maximus enim. Sed gravida ut nisi pellentesque facilisis. Aliquam laoreet mi purus. Integer pulvinar dui placerat sem feugiat, nec placerat est pulvinar. Proin odio lectus, consectetur vitae eleifend quis, bibendum sit amet diam. Praesent fermentum purus eu ante ullamcorper vulputate.

* Vivamus semper eros et ante venenatis sollicitudin
* Cras imperdiet tortor non leo efficitur commodo
* Suspendisse ut elit sit amet ipsum convallis venenatis
* Integer id velit a nunc dictum eleifend fermentum sit amet urna.

Aenean at sapien a est cursus imperdiet molestie sed sapien. Vivamus ultrices vitae risus non faucibus. Nunc ac tellus porttitor, sagittis massa a, pellentesque orci. Integer vitae scelerisque libero. Duis ut consequat ligula, non dignissim purus. Nam molestie interdum erat et fermentum. Curabitur non eros semper, volutpat nibh in, bibendum purus. Vivamus efficitur luctus magna vel viverra. Sed nulla metus, convallis sit amet nulla in, dignissim vehicula eros. Aliquam nisi sapien, porta in elementum non, tristique nec nunc.


text:
package org.koivusaari.weather.pojo;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;

import org.koivusaari.weather.LocalDateTimeConverter;

@Entity
public class Graph implements Serializable {

	/**
	 *
	 */
	private static final long serialVersionUID = 2880420227975753735L;
	@Id
	private Long graphId;
    private String name;
    private String role;
    @Convert(converter = LocalDateTimeConverter.class)
    private LocalDateTime from;
    @Convert(converter = LocalDateTimeConverter.class)
    private LocalDateTime to;
    private Long dynamic;
    static final public long STATIC_TIME=0;
    static final public long DYNAMIC_TIME=1;
//    @ManyToMany
//    @OrderBy("order_by ASC")
//    @OrderColumn(name="order_by")
//    @JoinTable(name="graph_series",
//    joinColumns=@JoinColumn(name="graph_id"),
//    inverseJoinColumns=@JoinColumn(name="series_id"))
    @OneToMany(mappedBy="graph")
	@OrderBy("orderBy")
    private List<GraphSeries> graphSeries;
//    private List<Series> series;

	public Long getGraphId() {
		return graphId;
	}
	public void setGraphId(Long graphId) {
		this.graphId = graphId;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public LocalDateTime getFrom() {
		return from;
	}
	public void setFrom(LocalDateTime from) {
		this.from = from;
	}
	public LocalDateTime getTo() {
		return to;
	}
	public void setTo(LocalDateTime to) {
		this.to = to;
	}
	public Long getDynamic() {
		return dynamic;
	}
	public void setDynamic(Long dynamic) {
		this.dynamic = dynamic;
	}
	public List<GraphSeries> getGraphSeries() {
		return graphSeries;
	}
	public void setGraphSeries(List<GraphSeries> graphSeries) {
		this.graphSeries = graphSeries;
	}
	@Override
	public String toString() {
		return String.format("Graph [graphId=%s, name=%s, role=%s, from=%s, to=%s, dynamic=%s, graphSeries=%s]",
				graphId, name, role, from, to, dynamic, graphSeries);
	}

}

redpajama_set_name: RedPajamaGithub


text:
from marshmallow import Schema, fields

class EmailSchema(Schema):
    id = fields.UUID(dump_only=True)
    email = fields.Str()
    verified = fields.Bool(default=False)


text:
package org.nisshiee.chatwork_slack_relay

import org.nisshiee.chatwork_slack_relay.domain._

object TransferServiceImpl extends TransferService

trait MixinTransferService extends UsesTransferService {
  override val transferService = TransferServiceImpl
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using gov.va.medora.mdo.dao;
using System.Collections.Concurrent;
using gov.va.medora.mdo.exceptions;
using gov.va.medora.mdo.dao.vista;
using System.Threading;
using System.Threading.Tasks;
using gov.va.medora.utils;

namespace gov.va.medora.mdo.domain.pool.connection
{
    public class ConnectionPool : AbstractResourcePool
    {
        protected byte SHUTDOWN_FLAG = 0;
        private readonly object _locker = new object(); // don't make static because there may be many pools

        IList<ConnectionThread> _startedCxns = new List<ConnectionThread>();
        IList<ConnectionThread> _cxnsToRemove = new List<ConnectionThread>();

        internal BlockingCollection<AbstractConnection> _pooledCxns = new BlockingCollection<AbstractConnection>();
        DateTime _startupTimestamp;

        DateTime _lastSuccessfulCxn = DateTime.Now;
        Int32 _consecutiveCxnErrorCount = 0;

        IList<Task> _cleanupTasks = new List<Task>();

        /// <summary>
        /// This method removes an object from the pool
        /// </summary>
        /// <param name="obj">Not currently used</param>
        /// <returns>AbstractConnection</returns>
        public override AbstractResource checkOut(object obj)
        {
            AbstractConnection cxn = null;
            if (!_pooledCxns.TryTake(out cxn, this.PoolSource.WaitTime))
            {
               // System.Console.WriteLine("Unable to remove connection from pool - were " + _pooledCxns.Count + " cxns available - total resource count: " + this.TotalResources);
                throw new TimeoutException("No connection could be obtained in the configured allotment");
            }
            return cxn;
        }

        /// <summary>
        /// Return an AbstractConnection to the pool
        /// </summary>
        /// <param name="cxn">The connection to return to the pool</param>
        /// <returns></returns>
        public override object checkIn(AbstractResource cxn)
        {
            AbstractConnection theCxn = (AbstractConnection)cxn; // first get a new reference
            if (!theCxn.IsConnected || !theCxn.isAlive()) // don't add disconnected connections to the pool
            {
                //System.Console.WriteLine("Tried checking in invalid connection");
                this.decrementResourceCount();
                //this.TotalResources--;
                return null;
            }
            theCxn.LastUsed = DateTime.Now;

            if (cxn is VistaPoolConnection)
            {
                if (this.PoolSource.Credentials == null) // if not an authenticated connection
                {
                    ((VistaPoolConnection)theCxn).resetRaw(); // reset the symbol table so we're always receiving fresh from pool
                    ((VistaAccount)((VistaConnection)theCxn).Account).setContext(new MenuOption("XUS SIGNON"));
                }
                _pooledCxns.Add(theCxn);
            }
            else if (cxn is VistaConnection)
            {
                if (this.PoolSource.Credentials == null) // if not an authenticated connection
                {
                    ((VistaAccount)((VistaConnection)theCxn).Account).setContext(new MenuOption("XUS SIGNON"));
                }
                _pooledCxns.Add(theCxn);
            }
            else
            {
                _pooledCxns.Add(theCxn);
            }
            //System.Console.WriteLine("A connection was returned to the pool. {0} available", _pooledCxns.Count);
            return null;
        }

        /// <summary>
        /// The job of the run function is simply to make sure we have connections available in the pool. If the # of
        /// connections falls below the threshold, the pool expands (up to the limit). The loop also tries to clean
        /// up any connections that may have failed
        /// </summary>
        internal void run()
        {
            //System.Console.WriteLine("Run called...");
            LogUtils.getInstance().Log("Run called on pool " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
            lock (_locker)
            {
               // System.Console.WriteLine("Run entered...");
                _startupTimestamp = DateTime.Now;

                while (!Convert.ToBoolean(SHUTDOWN_FLAG))
                {
                    System.Threading.Thread.Sleep(500); // this small sleep time prevents the thread from consuming 100% of CPU

                    // this first IF statement checks to see if more connections need to be added to the pool
                    if (_pooledCxns.Count < this.PoolSource.MinPoolSize && _startedCxns.Count == 0) // only grow if we haven't started any connections
                    {
                        if (this.TotalResources < this.PoolSource.MaxPoolSize)
                        {
                            growPool();
                        }
                    }

                    // the second IF checks if this pool has started any connections - most of the time this should be false so we check it before the getEnumerator call
                    if (_startedCxns.Count > 0)
                    {
                        //Console.WriteLine("Found {0} connections that were started", _startedCxns.Count);
                        //LogUtils.getInstance().Log(String.Format("{0} connections were scheduled to be started", _startedCxns.Count));
                        IEnumerator<ConnectionThread> enumerator = _startedCxns.GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            ConnectionThread current = enumerator.Current;
                            Thread t = current.Thread;
                            //if (current.Connection.IsConnected)
                            if (!(t.IsAlive) && current.Connection.IsConnected) // check if started connection is ready for our pool
                            {
                                try { t.Join(0); } catch (Exception) { }
                                //Console.WriteLine("Found successfully started connection");
                                this.incrementResourceCount();
                                _pooledCxns.Add(current.Connection);
                                _cxnsToRemove.Add(current);
                                LogUtils.getInstance().Log(String.Format("Found a successful connection - incremented resource count to {0} and added to pool containing {1} cxns ({2})", this.TotalResources, this._pooledCxns.Count, ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id));
                            }
                            //else if (!current.Connection.IsConnected) // check if started connection thread has completed but for any reason disconnected
                            else if (!(t.IsAlive) && !current.Connection.IsConnected) // check if started connection thread has completed but for any reason disconnected
                            {
                                try { t.Join(0); } catch (Exception) { }
                               // Console.WriteLine("Found apparent failed connection - removing");
                                LogUtils.getInstance().Log("It appears one of the started connections failed to connect... " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
                                _cxnsToRemove.Add(current);
                            }
                            else if (DateTime.Now.Subtract(current.Timestamp).TotalSeconds > this.PoolSource.WaitTime.TotalSeconds) // lastly check for long running connection attempts
                            {
                                LogUtils.getInstance().Log("Found long running connection attempt - scheduling for cleanup: " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
                                _cxnsToRemove.Add(current);

                                try
                                {
                                    // create async task to wait for the thread to stop and disconnect the cxn just to be sure things are cleaned up
                                    Task disconnectTask = new System.Threading.Tasks.Task(() =>
                                    {
                                        t.Join(this.PoolSource.WaitTime); // should be enough - waiting for double pool wait time in total
                                        disconnect(current.Connection);
                                    });
                                    _cleanupTasks.Add(disconnectTask);
                                    disconnectTask.Start();
                                }
                                catch (AggregateException ae) { LogUtils.getInstance().Log(ae.ToString()); }
                                catch (Exception) { /* swallow */ }
                            }

                        }
                    }

                    // per previous IF - can't modify collection while enumerating so the removal of failed connections is a separate step
                    if (_cxnsToRemove.Count > 0)
                    {
                        foreach (ConnectionThread t in _cxnsToRemove)
                        {
                            _startedCxns.Remove(t);
                        }
                        _cxnsToRemove = new List<ConnectionThread>();
                    }

                    try { checkCleanupTasks(); } catch (Exception) { }
                }
            }
            LogUtils.getInstance().Log("Run exited for pool " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
        }

        void checkCleanupTasks()
        {
            bool allCleanupTasksNull = true;
            String poolSiteId = ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id;
            for (int i = 0; i < _cleanupTasks.Count; i++)
            {
                if (_cleanupTasks[i] == null)
                {
                    continue;
                }
                LogUtils.getInstance().Log("Found " + _cleanupTasks.Count + " tasks to clean up: " + poolSiteId);
                if (_cleanupTasks[i].IsFaulted)
                {
                    LogUtils.getInstance().Log("Found a failed cleanup task: " + _cleanupTasks[i].Exception.Message + " - " + poolSiteId);
                    _cleanupTasks[i] = null;
                }
                else if (_cleanupTasks[i].IsCompleted)
                {
                    LogUtils.getInstance().Log("Found a completed cleanup task: " + poolSiteId);
                    _cleanupTasks[i] = null;
                }
                else // if task not
                {
                    LogUtils.getInstance().Log("Cleanup task appears to be still running: " + poolSiteId);
                    allCleanupTasksNull = false;
                }
            }
            // if all cleanup tasks have been addressed then create a new list!
            if (allCleanupTasksNull && _cleanupTasks.Count > 0)
            {
                LogUtils.getInstance().Log("All cleanup tasks finished - " + poolSiteId);
                _cleanupTasks = new List<Task>();
            }
        }

        void growPool()
        {
            if (_consecutiveCxnErrorCount > this.PoolSource.MaxConsecutiveErrors) // we want to recognize when a site might be down, network issues, etc. - wait to retry if we have many connection failures without success
            {
                if (DateTime.Now.Subtract(_lastSuccessfulCxn).CompareTo(this.PoolSource.WaitOnMaxConsecutiveErrors) < 0)
                {
                   // LogUtils.getInstance().Log(String.Format("{0} consecutive failed connection attempts... waiting {1} to start new cxns", _consecutiveCxnErrorCount, this.PoolSource.WaitOnMaxConsecutiveErrors.Subtract(DateTime.Now.Subtract(_lastSuccessfulCxn))));
                    return; // don't start any new cxns if we've seen a lot of errors and haven't waited at least 5 mins (or configurable timespan)
                }
                else // waited configured time, reset error vars so growPool will try creating cxns
                {
                    LogUtils.getInstance().Log("Resetting error related vars so will re-try instantiating cxns.. " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
                    _consecutiveCxnErrorCount = 0;
                    _lastSuccessfulCxn = DateTime.Now;
                }
            }
            if ((_cleanupTasks.Count + this.TotalResources) >= this.PoolSource.MaxPoolSize)
            {
                LogUtils.getInstance().Log("The # of cleanup tasks scheduled + the number of current resources exceeds the max pool size - waiting until cleanup tasks are addressed to grow");
                return; // too many cleanup tasks scheduled! don't grow the pool until the cxns we've attempted to start have been addressed
            }
            // i think there may be a possible race condition here where a cxn may be disconnected during the size
            int growSize = this.PoolSource.PoolExpansionSize;
            if ((this.TotalResources + growSize) > this.PoolSource.MaxPoolSize) // if the growth would expand the pool above the max pool size, only grow by the amount allowed
            {
                growSize = this.PoolSource.MaxPoolSize - this.TotalResources;
            }
            LogUtils.getInstance().Log(String.Format("Connection pool at min size {0}/{1} - growing by {2}. Current total resources: {3} - site: {4}", this.PoolSource.MinPoolSize, this.PoolSource.MaxPoolSize, growSize, this.TotalResources, ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id));
            for (int i = 0; i < growSize; i++)
            {
                ConnectionThread a = new ConnectionThread();
                _startedCxns.Add(a);
                a.Connection = AbstractDaoFactory.getDaoFactory(AbstractDaoFactory.getConstant(((ConnectionPoolSource)this.PoolSource).CxnSource.Protocol))
                    .getConnection(((ConnectionPoolSource)this.PoolSource).CxnSource);
               // Task connectTask = new Task(() => connect(a));
              //  a.Thread = connectTask;
               // connectTask.Start();
                //connect(a);
                Thread t = new Thread(new ParameterizedThreadStart(connect));
                a.Thread = t;
                t.Start(a);
            }
        }

        void connect(object obj)
        {
            ConnectionThread cxn = (ConnectionThread)obj;
            try
            {
                cxn.Connection.connect();
                // Authenticated Vista Connection Handling
                if (this.PoolSource.Credentials != null) // should be an authenticated connection!
                {
                    if (this.PoolSource.Permission == null)
                    {
                        this.PoolSource.Permission = new MenuOption(VistaConstants.CAPRI_CONTEXT);
                    }
                    this.PoolSource.Permission.IsPrimary = true;
                    if (String.IsNullOrEmpty(this.PoolSource.Credentials.AccountName) || String.IsNullOrEmpty(this.PoolSource.Credentials.AccountPassword))
                    {
                        cxn.Connection.Account.AuthenticationMethod = VistaConstants.NON_BSE_CREDENTIALS; // if no A/V codes, visit
                    }
                    else
                    {
                        cxn.Connection.Account.AuthenticationMethod = VistaConstants.LOGIN_CREDENTIALS;
                    }
                    cxn.Connection.Account.authenticateAndAuthorize(this.PoolSource.Credentials, this.PoolSource.Permission);
                }
                // END Authenticated cxn handling
                else if (cxn.Connection is VistaPoolConnection) // else if pool cxn and no creds - get default state
                {
                    ((VistaPoolConnection)cxn.Connection)._rawConnectionSymbolTable = ((VistaPoolConnection)cxn.Connection).getState();
                }
                //this.incrementResourceCount();
                _lastSuccessfulCxn = DateTime.Now;
                _consecutiveCxnErrorCount = 0;
               // System.Console.WriteLine(String.Format("Successfully added a connection - total resources {0}", this.TotalResources));
                //this.TotalResources++;
                cxn.Connection.setTimeout(this.PoolSource.Timeout); // now gracefully timing out connections!
            }
            catch (Exception exc)
            {
                _consecutiveCxnErrorCount++;
                LogUtils.getInstance().Log("There was a problem connecting to " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id + ": " + exc.Message);
                cxn.Connection.IsConnected = false;
                disconnect(cxn.Connection);
            }
        }

        void disconnect(object AbstractConnection)
        {
            try
            {
                ((AbstractConnection)AbstractConnection).disconnect();
            }
            catch (Exception) { }
        }

        /// <summary>
        /// Signal the pool to shutdown. An attempt will be made to wait for as many connections as possible for return to the pool
        /// before disconnecting each of the connections. Sets SHUTDOWN_FLAG so pool no longer tries to continue to run
        /// </summary>
        public override void shutdown()
        {
            if (SHUTDOWN_FLAG == 1)
            {
                return;
            }
            SHUTDOWN_FLAG = 1;

            AbstractConnection current = null;
            while (_pooledCxns.TryTake(out current, 1000))
            {
                current.disconnect();
            }
        }

        /// <summary>
        /// Check the status of the pool. If the pool has been signalled to shutdown, this should return false. If the pool
        /// has no available resources and has been running for more than one minute, assume something went wrong and return false.
        /// Otherwise, this should return true
        /// </summary>
        public bool IsAlive
        {
            get
            {
                if (Convert.ToBoolean(SHUTDOWN_FLAG))
                {
                    return false;
                }
                if ((TotalResources == 0 && (_startedCxns == null || _startedCxns.Count == 0)) && // if no total resources AND no started connections
                    DateTime.Now.Subtract(_startupTimestamp).CompareTo(this.PoolSource.WaitTime) > 0) // if we have no resources, no started resources AND pool started more than 60 seconds ago
                {
                    return false;
                }
                return true;
            }
        }

        /// <summary>
        /// Check out an object from the pool and call isAlive to guarantee state. Decrement resource count
        /// on pool if object is not alive and discard it by removing references
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>AbstractResource</returns>
        public override AbstractResource checkOutAlive(object obj)
        {
            AbstractResource resource = checkOut(obj);
            while (!resource.isAlive())
            {
                LogUtils.getInstance().Log("Found disconnected/timed out connection... Fetching another: " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
                this.decrementResourceCount();
                //this.TotalResources--;
                resource = checkOut(obj);
            }
            if (resource is VistaPoolConnection && this.PoolSource.RecycleCount > 0) // only need to step in here if the recycle count was actually set
            {
                VistaPoolConnection cxn = (VistaPoolConnection)resource;
                if (cxn.QueryCount >= this.PoolSource.RecycleCount) // if we've used cxn more times than specified before recycle, we should disconnect this connection and return another
                {
                    LogUtils.getInstance().Log("Max number of queries exceeded for connection - disconnecting and discarding: " + ((ConnectionPoolSource)this.PoolSource).CxnSource.SiteId.Id);
                    new System.Threading.Tasks.Task(() => cxn.disconnect()).Start();
                    this.decrementResourceCount();
                    //this.TotalResources--;
                    return this.checkOutAlive(obj);
                }
            }
            return resource;
        }
    }
}


text:
/*!
 * jQuery Shuffle Plugin
 * Uses CSS Transforms to filter down a grid of items (degrades to jQuery's animate).
 * Inspired by Isotope http://isotope.metafizzy.co/
 * Use it for whatever you want! Requires jQuery 1.9+
 * @author Glen Cheney (http://glencheney.com)
 * @version 1.6.4
 * @date 04/01/13
 */
(function($, Modernizr, undefined) {
    'use strict';

    // You can return `undefined` from the `by` function to revert to DOM order
    // This plugin does NOT return a jQuery object. It returns a plain array because
    // jQuery sorts everything in DOM order.
    $.fn.sorted = function(options) {
        var opts = $.extend({}, $.fn.sorted.defaults, options),
            arr = this.get(),
            revert = false;

        if ( !arr.length ) {
            return [];
        }

        if ( opts.randomize ) {
            return $.fn.sorted.randomize( arr );
        }

        // Sort the elements by the opts.by function.
        // If we don't have opts.by, default to DOM order
        if (opts.by !== $.noop && opts.by !== null && opts.by !== undefined) {
            arr.sort(function(a, b) {

                // Exit early if we already know we want to revert
                if ( revert ) {
                    return 0;
                }

                var valA = opts.by($(a)),
                    valB = opts.by($(b));

                // If both values are undefined, use the DOM order
                if ( valA === undefined && valB === undefined ) {
                    revert = true;
                    return 0;
                }

                if ( valA === 'sortFirst' || valB === 'sortLast' ) {
                    return -1;
                }

                if ( valA === 'sortLast' || valB === 'sortFirst' ) {
                    return 1;
                }

                return (valA < valB) ? -1 :
                    (valA > valB) ? 1 : 0;
            });
        }

        // Revert to the original array if necessary
        if ( revert ) {
            return this.get();
        }

        if ( opts.reverse ) {
            arr.reverse();
        }

        return arr;

    };

    $.fn.sorted.defaults = {
        reverse: false, // Use array.reverse() to reverse the results
        by: null, // Sorting function
        randomize: false // If true, this will skip the sorting and return a randomized order in the array
    };

    // http://stackoverflow.com/a/962890/373422
    $.fn.sorted.randomize = function( array ) {
        var top = array.length,
            tmp, current;

        if ( !top ) {
            return array;
        }

        while ( --top ) {
            current = Math.floor( Math.random() * (top + 1) );
            tmp = array[ current ];
            array[ current ] = array[ top ];
            array[ top ] = tmp;
        }

        return array;
    };

    var Shuffle = function( $container, options ) {
        var self = this;
        $.extend(self, $.fn.shuffle.options, options, $.fn.shuffle.settings);

        self.$container = $container.addClass('shuffle');
        self.$window = $(window);
        self.unique = 'shuffle_' + $.now();

        self.fire('loading');
        self._init();
        self.fire('done');
    };

    Shuffle.prototype = {

        constructor: Shuffle,

        _init : function() {
            var self = this,
                containerCSS,
                transEndEventNames,
                afterResizeFunc,
                debouncedAfterResize,
                beforeResizeFunc,
                debouncedBeforeResize;

            self.$items = self._getItems().addClass('shuffle-item filtered');
            self.transitionName = self.prefixed('transition'),
            self.transitionDelayName = self.prefixed('transitionDelay');
            self.transitionDuration = self.prefixed('transitionDuration');
            self.transform = self.getPrefixed('transform');

            self.isFluid = self.columnWidth && typeof self.columnWidth === 'function';

            // Get transitionend event name
            transEndEventNames = {
                'WebkitTransition' : 'webkitTransitionEnd',
                'MozTransition'    : 'transitionend',
                'OTransition'      : 'oTransitionEnd',
                'msTransition'     : 'MSTransitionEnd',
                'transition'       : 'transitionend'
            };
            self.transitionend = transEndEventNames[ self.transitionName ];

            // Set up css for transitions
            self.$container[0].style[ self.transitionName ] = 'height ' + self.speed + 'ms ' + self.easing;
            self._initItems( self.showInitialTransition );

            // Bind resize events (http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer)
            // Get debounced versions of our resize methods
            afterResizeFunc = $.proxy( self._afterResize, self );
            debouncedAfterResize = self.throttle ? self.throttle( self.throttleTime, afterResizeFunc ) : afterResizeFunc;
            self.$window.on('resize.' + self.unique, debouncedAfterResize);

            // If we need to hide layouts with a fade instead, we need another event on window resize
            // which is only fired the first time window resize is triggered
            if ( self.hideLayoutWithFade ) {
                beforeResizeFunc = $.proxy( self._beforeResize, self );
                debouncedBeforeResize = self.throttle ? self.throttle( self.throttleTime, true, beforeResizeFunc ) : beforeResizeFunc;
                self.$window.on('resize.shuffle', debouncedBeforeResize);
            }

            // Position cannot be static
            containerCSS = self.$container.css(['paddingLeft', 'paddingRight', 'position', 'width']);
            if ( containerCSS.position === 'static' ) {
                self.$container.css('position', 'relative');
            }

            // Get offset from container
            self.offset = {
                left: parseInt( containerCSS.paddingLeft, 10 ) || 0,
                top: parseInt( containerCSS.paddingTop, 10 ) || 0
            };
            self._resetCols();
            // We already got the container's width above, no need to cause another reflow getting it again...
            self._setColumns( parseInt( containerCSS.width, 10 ) );
            self.shuffle( self.group );

            // If we've hidden the initial layout, we need to now add the transition to the elements
            if ( !self.showInitialTransition && self.supported && self.useTransition ) {
                setTimeout(function() {
                    self._setTransitions();
                }, 0);
            }
        },

        filter : function( category, $collection ) {
            var self = this,
                isPartialSet = $collection !== undefined,
                $items = isPartialSet ? $collection : self.$items,
                $filtered = $();

            category = category || self.lastFilter;

            self.fire('filter');

            // Loop through each item and use provided function to determine
            // whether to hide it or not.
            if ( $.isFunction(category) ) {
                $items.each(function() {
                    var $item = $(this),
                    passes = category.call($item[0], $item, self);

                    if ( passes ) {
                        $filtered = $filtered.add( $item );
                    }
                });
            }

            // Otherwise we've been passed a category to filter by
            else {
                self.group = category;
                if (category !== 'all') {
                    $items.each(function() {
                        var $this = $(this),
                        groups = $this.data('groups'),
                        keys = self.delimeter && !$.isArray( groups ) ? groups.split( self.delimeter ) : groups,
                        passes = $.inArray(category, keys) > -1;

                        if ( passes ) {
                            $filtered = $filtered.add( $this );
                        }
                    });
                }

                // category === 'all', add filtered class to everything
                else {
                    $filtered = $items;
                }
            }

            // Individually add/remove concealed/filtered classes
            var concealed = 'concealed',
                filtered = 'filtered';
            $items.filter( $filtered ).each(function() {
                var $filteredItem = $(this);
                // Remove concealed if it's there
                if ( $filteredItem.hasClass( concealed ) ) {
                    $filteredItem.removeClass( concealed );
                }
                // Add filtered class if it's not there
                if ( !$filteredItem.hasClass( filtered ) ) {
                    $filteredItem.addClass( filtered );
                }
            });
            $items.not( $filtered ).each(function() {
                var $filteredItem = $(this);
                // Add concealed if it's not there
                if ( !$filteredItem.hasClass( concealed ) ) {
                    $filteredItem.addClass( concealed );
                }
                // Remove filtered class if it's there
                if ( $filteredItem.hasClass( filtered ) ) {
                    $filteredItem.removeClass( filtered );
                }
            });

            $items = null;
            $collection = null;

            return $filtered;
        },

        _initItems : function( withTransition, $items ) {
            var self = this;

            // Default to true if unspecified
            withTransition = withTransition === false ? false : true;
            $items = $items || self.$items;

            $items.each(function() {
                $(this).css(self.itemCss);

                // Set CSS transition for transforms and opacity
                if ( self.supported && self.useTransition && withTransition ) {
                    self._setTransition(this);
                }
            });
        },

        _setTransition : function( element ) {
            var self = this;
            element.style[self.transitionName] = self.transform + ' ' + self.speed + 'ms ' + self.easing + ', opacity ' + self.speed + 'ms ' + self.easing;
        },

        _setTransitions : function() {
            var self = this;
            self.$items.each(function() {
                self._setTransition( this );
            });
        },

        _setSequentialDelay : function( $collection ) {
            var self = this;

            if ( !self.supported ) {
                return;
            }

            // $collection can be an array of dom elements or jquery object
            $.each( $collection, function(i) {
                // This works because the transition-property: transform, opacity;
                this.style[ self.transitionDelayName ] = '0ms,' + ((i + 1) * self.sequentialFadeDelay) + 'ms';

                // Set the delay back to zero after one transition
                $(this).one(self.transitionend, function() {
                    this.style[ self.transitionDelayName ] = '0ms';
                });
            });
        },

        _resetDelay : function( $collection ) {
            var self = this;

            if ( !self.supported ) {
                return;
            }

            $.each( $collection, function() {
                $(this).off( self.transitionend );
                this.style[ self.transitionDelayName ] = '0ms';
            });
        },

        _orderItemsByDelay : function( $items ) {
            var self = this,
                $ordered = $(),
                $randomized = $(),
                ordered, randomized, merged,

            by = function( $el ) {
                return $el.data('delayOrder');
            };

            if ( !self.$ordered ) {

                $items.each(function() {
                    var delayOrder = $(this).data('delayOrder');

                    if ( delayOrder ) {
                        $ordered = $ordered.add( this );
                    } else {
                        $randomized = $randomized.add( this );
                    }
                });

                ordered = $ordered.sorted({ by: by });

            } else {
                $ordered = self.$ordered;
                ordered = self.ordered;
                $randomized = $items.not( $ordered );
            }

            // Sort randomly
            randomized = $randomized.sorted({ randomize: true });

            // Merge with the ordered array
            merged = ordered.concat( randomized );

            // Save values
            self.$ordered = $ordered;
            self.ordered = ordered;
            self.itemsOrderedByDelay = merged;
        },

        _getItems : function() {
            return this.$container.children( this.itemSelector );
        },

        // calculates number of columns
        // i.e. this.colWidth = 200
        _setColumns : function( theContainerWidth ) {
            var self = this,
                containerWidth = theContainerWidth || self.$container.width(),
                gutter = typeof self.gutterWidth === 'function' ? self.gutterWidth( containerWidth ) : self.gutterWidth;

            // use fluid columnWidth function if there
            self.colWidth = self.isFluid ? self.columnWidth( containerWidth ) :
                // if not, how about the explicitly set option?
                self.columnWidth ||
                // or use the size of the first item
                self.$items.outerWidth(true) ||
                // if there's no items, use size of container
                containerWidth;

            // Don't let them set a column width of zero.
            self.colWidth = self.colWidth || containerWidth;

            self.colWidth += gutter;

            // Was flooring 4.999999999999999 to 4 :(
            self.cols = Math.floor( ( containerWidth + gutter + 0.000000000001 ) / self.colWidth );
            self.cols = Math.max( self.cols, 1 );

            // This can happen when .shuffle is called on something hidden (e.g. display:none for tabs)
            if ( !self.colWidth || isNaN( self.cols ) || !containerWidth ) {
                self.needsUpdate = true;
            } else {
                self.needsUpdate = false;
            }

            self.containerWidth = containerWidth;
        },

        /**
         * Adjust the height of the grid
         */
        setContainerSize : function() {
            var self = this,
            gridHeight = Math.max.apply( Math, self.colYs );
            self.$container.css( 'height', gridHeight + 'px' );
        },

        /**
         * Fire events with .shuffle namespace
         */
        fire : function( name ) {
            this.$container.trigger(name + '.shuffle', [this]);
        },

        /**
         * Loops through each item that should be shown
         * Calculates the x and y position and then transitions it
         * @param {array} items - array of items that will be shown/layed out in order in their array.
         *     Because jQuery collection are always ordered in DOM order, we can't pass a jq collection
         * @param {function} complete callback function
         * @param {boolean} isOnlyPosition set this to true to only trigger positioning of the items
         */
        _layout: function( items, fn, isOnlyPosition, isHide ) {
            var self = this;

            fn = fn || self.filterEnd;

            self.layoutTransitionEnded = false;
            $.each(items, function(index) {
                var $this = $(items[index]),
                //how many columns does this brick span
                colSpan = Math.ceil( $this.outerWidth(true) / self.colWidth );
                colSpan = Math.min( colSpan, self.cols );

                if ( colSpan === 1 ) {
                    // if brick spans only one column, just like singleMode
                    self._placeItem( $this, self.colYs, fn, isOnlyPosition, isHide );
                } else {
                    // brick spans more than one column
                    // how many different places could this brick fit horizontally
                    var groupCount = self.cols + 1 - colSpan,
                        groupY = [],
                        groupColY,
                        i;

                    // for each group potential horizontal position
                    for ( i = 0; i < groupCount; i++ ) {
                        // make an array of colY values for that one group
                        groupColY = self.colYs.slice( i, i + colSpan );
                        // and get the max value of the array
                        groupY[i] = Math.max.apply( Math, groupColY );
                    }

                    self._placeItem( $this, groupY, fn, isOnlyPosition, isHide );
                }
            });

            // `_layout` always happens after `shrink`, so it's safe to process the style
            // queue here with styles from the shrink method
            self._processStyleQueue();

            // Adjust the height of the container
            self.setContainerSize();
        },

        _resetCols : function() {
            // reset columns
            var i = this.cols;
            this.colYs = [];
            while (i--) {
                this.colYs.push( 0 );
            }
        },

        _reLayout : function( callback, isOnlyPosition ) {
            var self = this;
            callback = callback || self.filterEnd;
            self._resetCols();

            // If we've already sorted the elements, keep them sorted
            if ( self.keepSorted && self.lastSort ) {
                self.sort( self.lastSort, true, isOnlyPosition );
            } else {
                self._layout( self.$items.filter('.filtered').get(), self.filterEnd, isOnlyPosition );
            }
        },

        // worker method that places brick in the columnSet with the the minY
        _placeItem : function( $item, setY, callback, isOnlyPosition, isHide ) {
            // get the minimum Y value from the columns
            var self = this,
                minimumY = Math.min.apply( Math, setY ),
                shortCol = 0;

            // Find index of short column, the first from the left where this item will go
            // if ( setY[i] === minimumY ) requires items' height to be exact every time.
            // The buffer value is very useful when the height is a percentage of the width
            for (var i = 0, len = setY.length; i < len; i++) {
                if ( setY[i] >= minimumY - self.buffer && setY[i] <= minimumY + self.buffer ) {
                    shortCol = i;
                    break;
                }
            }

            // Position the item
            var x = self.colWidth * shortCol,
            y = minimumY;
            x = Math.round( x + self.offset.left );
            y = Math.round( y + self.offset.top );

            // Save data for shrink
            $item.data( {x: x, y: y} );

            // Apply setHeight to necessary columns
            var setHeight = minimumY + $item.outerHeight(true),
            setSpan = self.cols + 1 - len;
            for ( i = 0; i < setSpan; i++ ) {
                self.colYs[ shortCol + i ] = setHeight;
            }

            var transitionObj = {
                from: 'layout',
                $this: $item,
                x: x,
                y: y,
                scale: 1
            };

            if ( !isOnlyPosition ) {
                transitionObj.opacity = 1;
                transitionObj.callback = callback;
            } else {
                transitionObj.skipTransition = true;
            }

            if ( isHide ) {
                transitionObj.opacity = 0;
            }

            self.styleQueue.push( transitionObj );
        },

        /**
         * Hides the elements that don't match our filter
         */
        shrink : function( $collection, fn ) {
            var self = this,
                $concealed = $collection || self.$items.filter('.concealed'),
                transitionObj = {},
                callback = fn || self.shrinkEnd;

            // Abort if no items
            if ($concealed.length === 0) {
                return;
            }

            self.fire('shrink');

            self.shrinkTransitionEnded = false;
            $concealed.each(function() {
                var $this = $(this),
                    data = $this.data(),
                    x = parseInt( data.x, 10 ),
                    y = parseInt( data.y, 10 );

                if (!x) { x = 0; }
                if (!y) { y = 0; }

                transitionObj = {
                    from: 'shrink',
                    $this: $this,
                    x: x,
                    y: y,
                    scale : 0.001,
                    opacity: 0,
                    callback: callback
                };

                self.styleQueue.push( transitionObj );
            });
        },

        _afterResize : function() {
            var self = this,
                containerWidth;

            // If shuffle is disabled, destroyed, don't do anything
            if ( !self.enabled || self.destroyed ) {
                return;
            }

            // Will need to check height in the future if it's layed out horizontaly
            containerWidth = self.$container.width();

            // containerWidth hasn't changed, don't do anything
            if ( containerWidth === self.containerWidth ) {
                return;
            }

            // If we're hiding the layout with a fade,
            if ( self.hideLayoutWithFade && self.supported ) {
                // recaculate column and gutter values
                self._setColumns( containerWidth );
                // Layout the items with only a position
                self._reLayout( false, true );
                // Change the transition-delay value accordingly
                self._setSequentialDelay( self.itemsOrderedByDelay || self.$items.get() );
                self.fire('done');
                self.$items.css('opacity', 1);
            } else {
                self.resized();
            }
        },

        _beforeResize : function() {
            var self = this,
                containerWidth;

            // If shuffle is disabled, destroyed, don't do anything
            if ( !self.hideLayoutWithFade || !self.supported || !self.enabled || self.destroyed ) {
                return;
            }

            // Will need to check height in the future if it's layed out horizontaly
            containerWidth = self.$container.width();

            // containerWidth hasn't changed, don't do anything
            if ( containerWidth === self.containerWidth ) {
                return;
            }

            self.$items.css('opacity', 0);

            self.fire('loading');
            self._resetDelay( self.$items );
            self._orderItemsByDelay( self.$items );
        },

        /**
         * Uses Modernizr's prefixed() to get the correct vendor property name and sets it using jQuery .css()
         *
         * @param {jq} $el the jquery object to set the css on
         * @param {string} prop the property to set (e.g. 'transition')
         * @param {string} value the value of the prop
         */
        setPrefixedCss : function($el, prop, value) {
            $el.css(this.prefixed(prop), value);
        },

        /**
         * Returns things like `-webkit-transition` or `box-sizing` from `transition` or `boxSizing`, respectively
         *
         * @param {string} property to be prefixed.
         * @return {string} the prefixed css property
         */
        getPrefixed : function(prop) {
            var styleName = this.prefixed(prop);
            return styleName ? styleName.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-') : styleName;
        },

        /**
         * Transitions an item in the grid
         *
         * @param {object}  opts options
         * @param {jQuery}  opts.$this jQuery object representing the current item
         * @param {int}     opts.x translate's x
         * @param {int}     opts.y translate's y
         * @param {String}  opts.left left position (used when no transforms available)
         * @param {String}  opts.top top position (used when no transforms available)
         * @param {float}   opts.scale amount to scale the item
         * @param {float}   opts.opacity opacity of the item
         * @param {String}  opts.height the height of the item (used when no transforms available)
         * @param {String}  opts.width the width of the item (used when no transforms available)
         * @param {function} opts.callback complete function for the animation
         */
        transition: function(opts) {
            var self = this,
            transform,
            // Only fire callback once per collection's transition
            complete = function() {
                if (!self.layoutTransitionEnded && opts.from === 'layout') {
                    self.fire('layout');
                    opts.callback.call(self);
                    self.layoutTransitionEnded = true;
                } else if (!self.shrinkTransitionEnded && opts.from === 'shrink') {
                    opts.callback.call(self);
                    self.shrinkTransitionEnded = true;
                }
            };

            opts.callback = opts.callback || $.noop;

            // Use CSS Transforms if we have them
            if ( self.supported ) {

                // Make scale one if it's not preset
                if ( opts.scale === undefined ) {
                    opts.scale = 1;
                }

                if (self.threeD) {
                    transform = 'translate3d(' + opts.x + 'px, ' + opts.y + 'px, 0) scale3d(' + opts.scale + ', ' + opts.scale + ', 1)';
                } else {
                    transform = 'translate(' + opts.x + 'px, ' + opts.y + 'px) scale(' + opts.scale + ', ' + opts.scale + ')';
                }

                if ( opts.x !== undefined ) {
                    self.setPrefixedCss(opts.$this, 'transform', transform);
                }

                if ( opts.opacity !== undefined && self.useTransition ) {
                    // Update css to trigger CSS Animation
                    opts.$this.css('opacity' , opts.opacity);
                }

                if ( self.useTransition ) {
                    opts.$this.one(self.transitionend, complete);
                } else {
                    complete();
                }
            } else {

                var cssObj = {
                    left: opts.x,
                    top: opts.y,
                    opacity: opts.opacity
                };

                if ( self.useTransition ) {
                    // Use jQuery to animate left/top
                    opts.$this.stop(true, true).animate( cssObj, self.speed, 'swing', complete);
                } else {
                    opts.$this.css( cssObj );
                    complete();
                }
            }
        },

        _processStyleQueue : function() {
            var self = this,
                queue = self.styleQueue;

            $.each( queue, function(i, transitionObj) {

                if ( transitionObj.skipTransition ) {
                    self._skipTransition( transitionObj.$this[0], function() {
                        self.transition( transitionObj );
                    });
                } else {
                    self.transition( transitionObj );
                }
            });

            // Remove everything in the style queue
            self.styleQueue.length = 0;
        },

        shrinkEnd: function() {
            this.fire('shrunk');
        },

        filterEnd: function() {
            this.fire('filtered');
        },

        sortEnd: function() {
            this.fire('sorted');
        },

        /**
         * Change a property or execute a function which will not have a transition
         * @param  {Element}         element    DOM element that won't be transitioned
         * @param  {string|function} property   the new style property which will be set or a function which will be called
         * @param  {string}          [value]    the value that `property` should be.
         */
        _skipTransition : function( element, property, value ) {
            var self = this,
                reflow,
                durationName = self.transitionDuration,
                duration = element.style[ durationName ];

            // Set the duration to zero so it happens immediately
            element.style[ durationName ] = '0ms'; // ms needed for firefox!

            if ( $.isFunction( property ) ) {
                property();
            } else {
                element.style[ property ] = value;
            }

            // Force reflow
            reflow = element.offsetWidth;

            // Put the duration back
            element.style[ durationName ] = duration;
        },

        _addItems : function( $newItems, animateIn, isSequential ) {
            var self = this,
                $passed,
                passed;

            if ( !self.supported ) {
                animateIn = false;
            }

            $newItems.addClass('shuffle-item');
            self._initItems( undefined, $newItems );
            self.$items = self._getItems();
            $newItems.not($passed).css('opacity', 0);

            $passed = self.filter( undefined, $newItems );
            passed = $passed.get();

            // How many filtered elements?
            self.visibleItems = self.$items.filter('.filtered').length;

            if ( animateIn ) {
                self._layout( passed, null, true, true );

                if ( isSequential ) {
                    self._setSequentialDelay( $passed );
                }

                self._revealAppended( $passed );
            } else {
                self._layout( passed );
            }
        },

        _revealAppended : function( $newFilteredItems ) {
            var self = this;

            setTimeout(function() {
                $newFilteredItems.each(function(i, el) {
                    self.transition({
                        from: 'reveal',
                        $this: $(el),
                        opacity: 1
                    });
                });
            }, self.revealAppendedDelay);
        },

        /**
         * Public Methods
         */

        /**
         * The magic. This is what makes the plugin 'shuffle'
         * @param  {String|Function} category category to filter by. Can be a function
         */
        shuffle : function( category ) {
            var self = this;

            if ( !self.enabled ) {
                return;
            }

            if ( !category ) {
                category = 'all';
            }

            self.filter( category );
            // Save the last filter in case elements are appended.
            self.lastFilter = category;

            // How many filtered elements?
            self.visibleItems = self.$items.filter('.filtered').length;

            self._resetCols();

            // Shrink each concealed item
            self.shrink();

            // Update transforms on .filtered elements so they will animate to their new positions
            self._reLayout();
        },

        /**
         * Gets the .filtered elements, sorts them, and passes them to layout
         *
         * @param {object} opts the options object for the sorted plugin
         * @param {Boolean} [fromFilter] was called from Shuffle.filter method.
         */
        sort: function( opts, fromFilter, isOnlyPosition ) {
            var self = this,
                items = self.$items.filter('.filtered').sorted(opts);

            if ( !fromFilter ) {
                self._resetCols();
            }

            self._layout(items, function() {
                if (fromFilter) {
                    self.filterEnd();
                }
                self.sortEnd();
            }, isOnlyPosition);

            self.lastSort = opts;
        },

        /**
         * Relayout everything
         */
        resized: function( isOnlyLayout ) {
            if ( this.enabled ) {

                if ( !isOnlyLayout ) {
                    // Get updated colCount
                    this._setColumns();
                }

                // Layout items
                this._reLayout();
            }
        },

        /**
         * Use this instead of `update()` if you don't need the columns and gutters updated
         * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations
         * could be off.
         */
        layout : function() {
            this.update( true );
        },

        update : function( isOnlyLayout ) {
            this.resized( isOnlyLayout );
        },

        /**
         * New items have been appended to shuffle. Fade them in sequentially
         * @param  {jQuery}  $newItems    jQuery collection of new items
         * @param  {Boolean}  [animateIn]    If false, the new items won't animate in
         * @param  {Boolean} [isSequential] If false, new items won't sequentially fade in
         */
        appended : function( $newItems, animateIn, isSequential ) {
            // True if undefined
            animateIn = animateIn === false ? false : true;
            isSequential = isSequential === false ? false : true;

            this._addItems( $newItems, animateIn, isSequential );
        },

        disable : function() {
            this.enabled = false;
        },

        enable : function( isUpdateLayout ) {
            this.enabled = true;
            if ( isUpdateLayout !== false ) {
                this.update();
            }
        },

        remove : function( $collection ) {

            // If this isn't a jquery object, exit
            if ( !$collection.length || !$collection.jquery ) {
                return;
            }

            var self = this,
            remove = function() {
                var shuffle = this;
                $collection.remove();
                $collection = null;
                setTimeout(function() {
                    shuffle.$items = shuffle._getItems();
                    shuffle.layout();
                }, 0);
            };

            self.shrink( $collection, remove );
            self._processStyleQueue();
        },

        destroy: function() {
            var self = this;

            self.$window.off('.' + self.unique);
            self.$container
                .removeClass('shuffle')
                .removeAttr('style')
                .removeData('shuffle');
            self.$items
                .removeAttr('style')
                .removeClass('concealed filtered shuffle-item');
            self.destroyed = true;
        }

    };

    // Plugin definition
    $.fn.shuffle = function(opts, sortObj) {
        var args = Array.prototype.slice.call( arguments, 1 );
        return this.each(function() {
            var $this = $(this),
                shuffle = $this.data('shuffle');

            // If we don't have a stored shuffle, make a new one and save it
            if ( !shuffle ) {
                shuffle = new Shuffle($this, opts);
                $this.data('shuffle', shuffle);
            }

            // If passed a string, lets decide what to do with it. Or they've provided a function to filter by
            if ( $.isFunction(opts) ) {
                shuffle.shuffle( opts );

            // Key should be an object with propreties reversed and by.
            } else if (typeof opts === 'string') {
                switch( opts ) {
                    case 'sort':
                        shuffle.sort(sortObj);
                        break;
                    case 'destroy':
                    case 'update':
                    case 'appended':
                    case 'enable':
                    case 'disable':
                    case 'layout':
                    case 'remove':
                        shuffle[ opts ].apply( shuffle, args );
                        break;
                    default:
                        shuffle.shuffle( opts );
                        break;
                }
            }
        });
    };

    // Overrideable options
    $.fn.shuffle.options = {
        group : 'all', // Filter group
        speed : 400, // Transition/animation speed (milliseconds)
        easing : 'ease-out', // css easing function to use
        itemSelector: '', // e.g. '.gallery-item'
        gutterWidth : 0, // a static number or function that tells the plugin how wide the gutters between columns are (in pixels)
        columnWidth : 0,// a static number or function that returns a number which tells the plugin how wide the columns are (in pixels)
        showInitialTransition : true, // If set to false, the shuffle-items will only have a transition applied to them after the first layout
        delimeter : null, // if your group is not json, and is comma delimeted, you could set delimeter to ','
        buffer: 0, // useful for percentage based heights when they might not always be exactly the same (in pixels)
        throttle: $.debounce || null,
        throttleTime: 300,
        keepSorted : true, // Keep sorted when shuffling/layout
        hideLayoutWithFade: false,
        sequentialFadeDelay: 150,
        useTransition: true // You don't want transitions on shuffle items? Fine, but you're weird
    };

    // Not overrideable
    $.fn.shuffle.settings = {
        itemCss : { // default CSS for each item
            position: 'absolute',
            top: 0,
            left: 0
        },
        revealAppendedDelay: 300,
        enabled: true,
        destroyed: false,
        styleQueue: [],
        supported: Modernizr.csstransforms && Modernizr.csstransitions, // supports transitions and transforms
        prefixed: Modernizr.prefixed,
        threeD: Modernizr.csstransforms3d // supports 3d transforms
    };

})(jQuery, Modernizr);


text:
layout: page
title: Juarez - Newton Wedding
date: 2016-05-24
author: Sarah Chang
tags: weekly links, java
status: published
summary: Curabitur accumsan, ipsum sed hendrerit vestibulum, dui.
banner: images/banner/leisure-03.jpg
booking:
  startDate: 09/05/2017
  endDate: 09/07/2017
  ctyhocn: HLDMIHX
  groupCode: JNW
published: true
---
Praesent ac tortor nec nibh molestie imperdiet. Ut nisl ligula, interdum eget sapien eget, auctor gravida lectus. Etiam tristique porta justo, non feugiat augue dapibus nec. Quisque a bibendum nunc. Proin semper viverra urna vitae pulvinar. Quisque eu pulvinar odio, ut laoreet tortor. In eleifend imperdiet neque, nec posuere urna ultricies in.

* Suspendisse feugiat libero non ante commodo dignissim
* Mauris nec nisi a neque finibus vestibulum
* Fusce dictum lacus et sem venenatis, id tristique urna consequat
* Cras vel felis in risus interdum cursus
* Nulla varius eros et orci ultricies sodales.

Nullam posuere malesuada lobortis. Sed sem orci, dignissim quis leo quis, efficitur tincidunt leo. Integer ac mattis felis. Nullam faucibus lectus auctor, viverra neque in, consequat magna. Quisque tincidunt, est vel tincidunt fermentum, sem tortor venenatis quam, vitae suscipit leo purus vitae sapien. Aenean ullamcorper ultrices fermentum. Etiam tempus dolor vitae tempus imperdiet. Maecenas id sem finibus, tempus neque non, dignissim nibh. Aenean pharetra rhoncus turpis vitae rutrum. Vestibulum quis sollicitudin leo. Etiam eu mollis nisi, vel finibus velit. Fusce finibus, diam eget faucibus placerat, ex nunc vehicula leo, quis ultricies arcu nulla ac ipsum.
Phasellus lobortis suscipit velit, vel accumsan nisi finibus a. Aenean iaculis gravida risus, et consequat sapien. In bibendum cursus euismod. Nulla facilisi. Etiam nisl nisl, imperdiet in fermentum id, aliquam et elit. Sed ultrices purus id mi venenatis consectetur. Integer accumsan arcu in nulla tempor eleifend. Nam ornare rutrum urna nec cursus.


text:
<?php

namespace Programs\Parkcms\Workshop\Models;

use Illuminate\Database\Eloquent\Model as Eloquent;

use Carbon\Carbon;

class Workshop extends Eloquent {
    protected $table = 'workshops';

    public function parts() {
        return $this->hasMany('Programs\Parkcms\Workshop\Models\Part')->orderBy('order');
    }

    public function registrations() {

        $registrations = array();

        foreach($this->parts as $part) {
            foreach($part->registrations as $registration) {
                if(!in_array($registration, $registrations)) {
                    $registrations[] = $registration;
                }
            }
        }

        return $registrations;
    }

    public function occupiedSeats() {

        $registrations = array();

        $occupiedSeats = 0;

        foreach($this->parts()->where('connected_with_seats', true)->get() as $part) {
            foreach($part->registrations()->get() as $registration) {
                if(!in_array($registration->id, $registrations)) {
                    $registrations[] = $registration->id;
                    $occupiedSeats+= $registration->pivot->value;
                }
            }
        }

        return $occupiedSeats;
    }

    public function isFullOrClosed() {
        return $this->isClosed() || $this->isFull();
    }

    public function isFull() {
        if($this->seats < 0) {
            return false;
        }

        if($this->seats == 0) {
            return true;
        }

        return $this->occupiedSeats() >= $this->seats;
    }

    public function isClosed() {
        return $this->date->lt(Carbon::now());
    }

    public function getDates() {
        return array('date', 'created_at', 'updated_at');
    }
}


text:
import Ember from 'ember';

// TODO Move to constants?
const ITEM_HEIGHT = 41;
const MAX_HEIGHT = 5.5 * ITEM_HEIGHT;
const MENU_PADDING = 8;

export default Ember.Component.extend({
  util: Ember.inject.service(),

  tagName: 'ul',
  classNames: ['md-default-theme', 'md-autocomplete-suggestions', 'md-whiteframe-z1'],
  attributeNameBindings: ['role'],
  role: 'presentation',
  stickToElement: null,

  init() {
    this._super(...arguments);
    this._resizeWindowEvent = Ember.run.bind(this, this.resizeWindowEvent);
  },

  mouseEnter() {
    this.sendAction('mouse-enter');
  },

  mouseLeave() {
    this.sendAction('mouse-leave');
  },

  mouseUp() {
    this.sendAction('mouse-up');
  },

  // TODO reafactor into a computed property that binds directly to dropdown's `style`
  positionDropdown() {
    let hrect  = Ember.$(`#${this.get('wrapToElementId')}`)[0].getBoundingClientRect();
    let vrect  = hrect;
    let root   = document.body.getBoundingClientRect();
    let top    = vrect.bottom - root.top;
    let bot    = root.bottom - vrect.top;
    let left   = hrect.left - root.left;
    let { width }  = hrect;
    let styles = {
        left: `${left}px`,
        minWidth: `${width}px`,
        maxWidth: `${Math.max(hrect.right - root.left, root.right - hrect.left) - MENU_PADDING}px`
      };
    let ul = this.$();

    if (top > bot && root.height - hrect.bottom - MENU_PADDING < MAX_HEIGHT) {
      styles.top = 'auto';
      styles.bottom = `${bot}px`;
      styles.maxHeight = `${Math.min(MAX_HEIGHT, hrect.top - root.top - MENU_PADDING)}px`;
    } else {
      styles.top = `${top}px`;
      styles.bottom = 'auto';
      styles.maxHeight = `${Math.min(MAX_HEIGHT, root.bottom - hrect.bottom - MENU_PADDING)}px`;
    }
    ul.css(styles);
    correctHorizontalAlignment();

    /*
     * Makes sure that the menu doesn't go off of the screen on either side.
     */
    function correctHorizontalAlignment() {
      let dropdown = ul[0].getBoundingClientRect();
      let styles = {};
      if (dropdown.right > root.right - MENU_PADDING) {
        styles.left = `${hrect.right - dropdown.width}px`;
      }
      ul.css(styles);
    }
  },

  observeIndex: Ember.observer('selectedIndex', function() {
    let suggestions = this.get('suggestions');
    if (!suggestions || !suggestions.objectAt(this.get('selectedIndex'))) {
      return;
    }

    let ul = this.$();
    let li  = ul.find(`li:eq(${this.get('selectedIndex')})`).get(0);
    let top = li.offsetTop;
    let bot = top + li.offsetHeight;
    let hgt = ul[0].clientHeight;

    if (top < ul[0].scrollTop) {
      ul[0].scrollTop = top;
    } else if (bot > ul[0].scrollTop + hgt) {
      ul[0].scrollTop = bot - hgt;
    }
  }),

  resizeWindowEvent() {
    this.positionDropdown();
  },

  didInsertElement() {
    this._super(...arguments);

    // TODO refactor using ember-wormhole?
    let ul = this.$().detach();
    Ember.$('body').append(ul);
    Ember.$(window).on('resize', this._resizeWindowEvent);
    this.get('util').disableScrollAround(this.$());
    this.positionDropdown();
  },

  willDestroyElement() {
    Ember.$(window).off('resize', this._resizeWindowEvent);
    this.get('util').enableScrolling();
  }

});


text:
/****************************************************************************

  ink_time.h

  Timing routines for libts

 ****************************************************************************/

#pragma once

#include <chrono>

#include "tscore/ink_platform.h"
#include "tscore/ink_defs.h"
#include "tscore/ink_hrtime.h"

/*===========================================================================*

                                 Data Types

 *===========================================================================*/

using ink_time_t  = time_t;
using ts_clock    = std::chrono::system_clock;
using ts_time     = ts_clock::time_point;
using ts_hr_clock = std::chrono::high_resolution_clock;
using ts_hr_time  = ts_hr_clock::time_point;

using ts_seconds      = std::chrono::seconds;
using ts_milliseconds = std::chrono::milliseconds;

/// Equivalent of 0 for @c ts_time. This should be used as the default initializer.
static constexpr ts_time TS_TIME_ZERO;

/*===========================================================================*

                                 Prototypes

 *===========================================================================*/

#define UNDEFINED_TIME ((time_t)0)

double ink_time_wall_seconds();

int cftime_replacement(char *s, int maxsize, const char *format, const time_t *clock);
#define cftime(s, format, clock) cftime_replacement(s, 8192, format, clock)

ink_time_t convert_tm(const struct tm *tp);

inkcoreapi char *ink_ctime_r(const ink_time_t *clock, char *buf);
inkcoreapi struct tm *ink_localtime_r(const ink_time_t *clock, struct tm *res);

/*===========================================================================*
                              Inline Stuffage
 *===========================================================================*/
#if defined(freebsd) || defined(openbsd)

inline int
ink_timezone()
{
  struct timeval tp;
  struct timezone tzp;
  ink_assert(!gettimeofday(&tp, &tzp));
  return tzp.tz_minuteswest * 60;
}

#else // non-freebsd, non-openbsd for the else

inline int
ink_timezone()
{
  return timezone;
}

#endif /* #if defined(freebsd) || defined(openbsd) */


text:
package irc

import (
	"fmt"
	"log"
	"net"
)

type Client struct {
	net.Conn
	serverName string
	server     chan ServerMessage
}

func Connect(serverName, nick, realName string) (*Client, error) {
	conn, err := Dial(serverName)
	if err != nil {
		return conn, err
	}

	conn.Pass("notmeaningfull")
	conn.User(getUname(), getHostname(), getServername(), realName)
	conn.Nick(nick)
	return conn, nil
}

// Listen for messages coming in and return them on the returned channel. Also
// handles low-level information from the server correctly, making information
// available in the Client object as appropriate.
func (c *Client) Listen() <-chan Message {
	ch := make(chan Message)
	handleMessage := func(sm ServerMessage) {
		switch sm.Code {
		case "NOTICE":
			ch <- Message{
				Kind: MSG_NOTICE,
				From: sm.From,
				To:   sm.To,
				Text: sm.Raw[1:],
			}
		case "PRIVMSG":
			ch <- Message{
				Kind: MSG_PRIVMSG,
				From: sm.From,
				To:   sm.To,
				Text: sm.Raw[1:],
			}
		case "PING":
			fmt.Fprintf(c, "PONG :%s\n", sm.To)
		case RPL_MOTD:
		case RPL_MOTDSTART:
		case RPL_ENDOFMOTD:
		case RPL_WELCOME:
		case RPL_YOURHOST:
		case RPL_CREATED:
		case RPL_MYINFO:
		case RPL_BOUNCE:
		case RPL_LUSERCLIENT:
		case RPL_LUSEROP:
		case RPL_LUSERUNKNOWN:
		case RPL_LUSERCHANNELS:
		case RPL_LUSERME:
		case "MODE":
		default:
			log.Printf("Unhandled message %s\t\t%s", sm.Code, sm.Full)
		}
	}
	go func() {
		for {
			var m ServerMessage
			select {
			case m = <-c.server:
				handleMessage(m)
			}
		}
	}()
	return ch
}


text:
// Given a binary tree, determine if it is a valid binary search tree (BST).

// Assume a BST is defined as follows:

// The left subtree of a node contains only nodes with keys less than the node's key.
// The right subtree of a node contains only nodes with keys greater than the node's key.
// Both the left and right subtrees must also be binary search trees.

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public boolean isValidBST(TreeNode root) {
        return helper(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
    }

    public boolean helper(TreeNode node, int min, int max){
    	if(node == null) return true;

    	if(node.val <= min || node.val >= max){
    		return false;
    	}else{
    		return helper(node.left, min, node.val) && helper(node.right, node.val, max);
    	}
    }
}

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    class Data {
        boolean isValid;
        int min;
        int max;
        Data(int min, int max, boolean isValid) {
            this.min = min;
            this.max = max;
            this.isValid = isValid;
        }
    }

    public boolean isValidBST(TreeNode root) {
        Data res = helper(root);
        return res == null || res.isValid;
    }

    public Data helper(TreeNode node) {
        if (node == null) {
            return null;
        }

        Data left = helper(node.left);
        Data right = helper(node.right);
        Data res = new Data(0,0, false);

       // left invalid
        if (left != null && !left.isValid) {
            return res;
        }
        // right invalid
        if (right != null && !right.isValid) {
            return res;
        }

        if (left == null) {
            res.min = node.val;
        } else {
            if (left.max >= node.val || left.min >= node.val) {
                res.isValid = false;
                return res;
            } else {
                res.min = left.min;
            }
        }

        if (right == null) {
            res.max = node.val;
        } else {
            if (right.min <= node.val ) {

                res.isValid = false;
                return res;
            } else {
                res.max = right.max;
            }
        }

        res.isValid = true;

        return res;
    }
}


text:
""" Module handling the snapshots """
import datetime
import yaml
import boto3
from botocore.exceptions import ClientError
from boto.exception import EC2ResponseError
import kayvee
import logging
import os

aws_backup_region = os.environ.get('AWS_BACKUP_REGION')

""" Configure the valid backup intervals """
VALID_INTERVALS = [
    u'hourly',
    u'daily',
    u'weekly',
    u'monthly',
    u'yearly']

def run(connection, backup_client, volume_id, interval='daily', max_snapshots=0, name=''):
    """ Ensure that we have snapshots for a given volume

    :type connection: boto.ec2.connection.EC2Connection
    :param connection: EC2 connection object for primary EBS region
    :type backup_client: boto3.EC2.Client
    :param backup_client: EC2 client for backup region
    :type volume_id: str
    :param volume_id: identifier for boto.ec2.volume.Volume
    :type max_snapshots: int
    :param max_snapshots: number of snapshots to keep (0 means infinite)
    :returns: None
    """
    try:
        volumes = connection.get_all_volumes([volume_id])
    except EC2ResponseError as error:
        logging.error(kayvee.formatLog("ebs-snapshots", "error", "failed to connect to AWS", {
            "msg": error.message,
            "_kvmeta": {
                "team": "eng-infra",
                "kv_version": "2.0.2",
                "kv_language": "python",
                "routes": [ {
                    "type": "notifications",
                    "channel": "#oncall-infra",
                    "icon": ":camera_with_flash:",
                    "user": "ebs-snapshots",
                    "message": "ERROR: " + str(error.message),
                } ]
            }
        }))
        return
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "run", {"volume": volume_id, "count": len(volumes)}))
    for volume in volumes:
        _ensure_snapshot(connection, backup_client, volume, interval, name)
        _remove_old_snapshots(connection, volume, max_snapshots)
        _remove_old_snapshot_backups(backup_client, volume.id, max_snapshots)

def _create_snapshot(connection, volume, name=''):
    """ Create a new snapshot

    :type volume: boto.ec2.volume.Volume
    :param volume: Volume to snapshot
    :returns: boto.ec2.snapshot.Snapshot -- The new snapshot
    """
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "creating new snapshot", {"volume": volume.id}))
    snapshot = volume.create_snapshot(
        description="automatic snapshot by ebs-snapshots")
    if not name:
        name = '{}-snapshot'.format(volume.id)
    connection.create_tags(
        [snapshot.id], dict(Name=name, creator='ebs-snapshots'))
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "created snapshot successfully", {
        "name": name,
        "volume": volume.id,
        "snapshot": snapshot.id
    }))
    return snapshot

def _availability_zone_to_region_name(zone):
    """Get the region_name from an availability zone by removing last letter

    :type zone: str
    :param zone: name of availability zone
    :returns  str -- the name of the region
    """
    return zone[:-1]

def _copy_snapshot(backup_client, volume, snapshot_id, name):
    """ Copy a snapshot to another region

    :type backup_client: boto3.EC2.Client
    :param backup_client: EC2 client for backup region
    :type volume: boto.ec2.volume.Volume
    :param volume: Volume that snapshot is of
    :type snapshot_id: str
    :param snapshot_id: identifier for boto.ec2.snapshot.Snapshot (the snapshot to copy)
    :returns: str -- the id of the copy
    """
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "copying snapshot", {"volume": volume.id, "source_snapshot": snapshot_id}))
    region = _availability_zone_to_region_name(volume.zone)

    try:
        response = backup_client.copy_snapshot(
            SourceRegion=region,
            SourceSnapshotId=snapshot_id,
            Encrypted=True,
            Description='copy of {}'.format(snapshot_id))

    except ClientError as error:
        if error.response["Error"]["Code"] == "ResourceLimitExceeded":
            logging.info(kayvee.formatLog("ebs-snapshots", "info", "copying snapshot", {
                "volume": volume.id,
                "source_snapshot": snapshot_id,
                "name": name
            }))
        else:
            logging.error(kayvee.formatLog("ebs-snapshots", "error", "snapshot copy error", {
                "name": name,
                "volume": volume.id,
                "source_snapshot": snapshot_id,
                "error": error.response["Error"]["Code"]
            }))
        return None

    try:
        backup_client.create_tags(
            Resources=[response["SnapshotId"]],
            Tags=[
                {"Key":"Name", "Value":name},
                {"Key":"creator", "Value":"ebs-snapshots"},
                {"Key":"source_snapshot", "Value":snapshot_id},
                {"Key":"volume-id", "Value":volume.id}
            ]
        )
    except ClientError as error:
        logging.error(kayvee.formatLog("ebs-snapshots", "error", "unable to tag snapshot copy (error)", {
            "name": name,
            "volume": volume.id,
            "source_snapshot": snapshot_id,
            "error": error.response["Error"]["Code"]
        }))
        return response["SnapshotId"]

    logging.info(kayvee.formatLog("ebs-snapshots", "info", "copied snapshot successfully", {
        "name": name,
        "volume": volume.id,
        "source_snapshot": snapshot_id,
        "snapshot_copy": response["SnapshotId"]
    }))

    return response["SnapshotId"]

def _ensure_snapshot(connection, backup_client, volume, interval, name):
    """ Ensure that a given volume has appropriate snapshot(s) and backup snapshot(s)

    :type connection: boto.ec2.connection.EC2Connection
    :param connection: EC2 connection object
    :type backup_client: boto3.EC2.Client
    :param backup_client: EC2 client for backup region
    :type volume: boto.ec2.volume.Volume
    :param volume: Volume to check
    :type name: str
    :param name: a name to tag the snapshot(s) with
    :returns: None
    """
    if interval not in VALID_INTERVALS:
        logging.warning(kayvee.formatLog("ebs-snapshots", "warning", "invalid snapshotting interval", {
            "volume": volume.id,
            "interval": interval
        }))
        return

    snapshots = connection.get_all_snapshots(filters={'volume-id': volume.id})

    # Create a snapshot if we don't have any
    if not snapshots:
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "no snapshots found - creating snapshot", {"volume": volume.id}))
        _create_snapshot(connection, volume, name)
        return

    latest_snapshot_id = None
    min_delta = 3600 * 24 * 365 * 10  # 10 years :)

    latest_complete_snapshot_id = None
    min_complete_snapshot_delta = 3600 * 24 * 365 * 10

    for snapshot in snapshots:
        # Determine time since latest snapshot.
        timestamp = datetime.datetime.strptime(
            snapshot.start_time,
            '%Y-%m-%dT%H:%M:%S.%fZ')
        delta_seconds = int(
            (datetime.datetime.utcnow() - timestamp).total_seconds())

        if delta_seconds < min_delta:
            latest_snapshot_id = snapshot.id
            min_delta = delta_seconds

        # Determine latest completed snapshot's id.
        if snapshot.status == "completed" and delta_seconds < min_complete_snapshot_delta:
            latest_complete_snapshot_id = snapshot.id
            min_complete_snapshot_delta = delta_seconds

    logging.info(kayvee.formatLog("ebs-snapshots", "info", 'The newest snapshot for {} is {} seconds old (snapshot {})'.format(volume.id, min_delta, latest_snapshot_id), data={"volume":volume.id}))
    logging.info(kayvee.formatLog("ebs-snapshots", "info", 'The newest completed snapshot for {} is {} seconds old (snapshot {})'.format(volume.id, min_complete_snapshot_delta, latest_complete_snapshot_id), data={"volume":volume.id}))

    # Create snapshot if latest is older than interval.
    intervalToSeconds = {
        u'hourly': 3600,
        u'daily': 3600*24,
        u'weekly': 3600*24*7,
        u'monthly': 3600*24*30,
        u'yearly': 3600*24*365,
    }
    if min_delta > intervalToSeconds[interval]:
        _create_snapshot(connection, volume, name)
        # copy the last one we created to backup region
        if latest_complete_snapshot_id is None:
            logging.info(kayvee.formatLog("ebs-snapshots", "info", "waiting to create backup snapshot until snapshot is complete", {"volume": volume.id}))
        else:
            _copy_snapshot(backup_client, volume, latest_complete_snapshot_id, name)
    else:
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "no snapshot needed", {"volume": volume.id, "lastest_snapshot_id": latest_snapshot_id}))

def _remove_old_snapshot_backups(client, volume_id, max_snapshots):
    """ Remove old snapshot backups

    :type client: boto3.EC2.Client
    :param client: EC2 client object
    :type volume_id: str
    :param volume_id: ID of volume to check
    :returns: None
    """
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "removing old backup snapshots", data={"volume":volume_id}))

    retention = max_snapshots
    if not type(retention) is int and retention >= 0:
        logging.warning(kayvee.formatLog("ebs-snapshots", "warning", "invalid max_snapshots value", {
            "volume": volume_id,
            "max_snapshots": retention
        }))
        return

    response = client.describe_snapshots(
        Filters=[{ "Name": "tag:volume-id", "Values":[volume_id] }]
    )
    snapshots = response["Snapshots"]

    # Sort the list based on the start time
    snapshots.sort(key=lambda x: x["StartTime"])

    # Remove snapshots we want to keep
    snapshots = snapshots[:-int(retention)]

    if not snapshots:
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "no old backup snapshots to remove", data={"volume":volume_id}))
        return

    ec2 = boto3.resource('ec2', region_name=aws_backup_region)
    for snapshotInfo in snapshots:
        snapshot = ec2.Snapshot(snapshotInfo["SnapshotId"])
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "deleting backup snapshot", {"snapshot": snapshot.id}))
        try:
            snapshot.delete()
        except Exception as e:  # @TODO: how to get exceptions for boto3 resource?
            logging.error(kayvee.formatLog("ebs-snapshots", "error", "could not remove backup snapshot (error)", {
                "snapshot": snapshot.id,
                "error": str(e)
            }))

    logging.info(kayvee.formatLog("ebs-snapshots", "info", "done deleting snapshot backups", data={"volume":volume_id}))

def _remove_old_snapshots(connection, volume, max_snapshots):
    """ Remove old snapshots

    :type connection: boto.ec2.connection.EC2Connection
    :param connection: EC2 connection object
    :type volume: boto.ec2.volume.Volume
    :param volume: Volume to check
    :returns: None
    """
    logging.info(kayvee.formatLog("ebs-snapshots", "info", "removing old snapshots", data={"volume":volume.id}))

    retention = max_snapshots
    if not type(retention) is int and retention >= 0:
        logging.warning(kayvee.formatLog("ebs-snapshots", "warning", "invalid max_snapshots value", {
            "volume": volume.id,
            "max_snapshots": retention
        }))
        return
    snapshots = connection.get_all_snapshots(filters={'volume-id': volume.id})

    # Sort the list based on the start time
    snapshots.sort(key=lambda x: x.start_time)

    # Remove snapshots we want to keep
    snapshots = snapshots[:-int(retention)]

    if not snapshots:
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "no old snapshots to remove", data={"volume":volume.id}))
        return

    for snapshot in snapshots:
        logging.info(kayvee.formatLog("ebs-snapshots", "info", "deleting snapshot", {"snapshot": snapshot.id}))
        try:
            snapshot.delete()
        except EC2ResponseError as error:
            logging.warning(kayvee.formatLog("ebs-snapshots", "warning", "could not remove snapshot", {
                "snapshot": snapshot.id,
                "msg": error.message
            }))

    logging.info(kayvee.formatLog("ebs-snapshots", "info", "done deleting snapshots", data={"volume":volume.id}))


text:
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Alachisoft.NosDB.Common.Serialization;

using Newtonsoft.Json;

namespace Alachisoft.NosDB.Common.Server.Engine
{
    public class DocumentKey : ICompactSerializable, IComparable,ICloneable
    {
        private object _value;
        private Type _valueType;

        public DocumentKey() { }

        public DocumentKey(object key)
        {
            if (!IsKeyValid(key))
                throw new ArgumentException("Key is not a valid JSON value");
            _value = key;
            if(key != null)
                _valueType = key.GetType();
        }

        [JsonProperty(PropertyName = "Value")]
        public object Value
        {
            get { return _value; }
            set
            {
                _value = value;
                _valueType =  value.GetType();
            }
        }

        public override string ToString()
        {
            return _value != null? _value.ToString(): null;
        }

        public ExtendedJSONDataTypes GetJSONType()
        {
            if (_value == null)
            {
                return ExtendedJSONDataTypes.Null;
            }

            //this check will be removed after validation
            if(_value is DocumentKey)
                return ((DocumentKey)_value).GetJSONType();

            Type valueType = _value.GetType();
            TypeCode typeCode = Type.GetTypeCode(valueType);
            switch (typeCode)
            {
                case TypeCode.Boolean:
                    return ExtendedJSONDataTypes.Boolean;
                case TypeCode.Byte:
                case TypeCode.Decimal:
                case TypeCode.Double:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.Single:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    return ExtendedJSONDataTypes.Number;
                case TypeCode.Char:
                case TypeCode.String:
                    return ExtendedJSONDataTypes.String;
                case TypeCode.DateTime:
                    return ExtendedJSONDataTypes.DateTime;
            }
            if (valueType.IsArray)
                return ExtendedJSONDataTypes.Array;
            return ExtendedJSONDataTypes.Object;
        }

        public bool IsKeyValid( object value)
        {
            if (value == null || value is string)
                return true;
            return false;

        }

        public override int GetHashCode()
        {
            return _value.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            DocumentKey key = obj as DocumentKey;
            if (key == null)
                return false;

            return key._value.Equals(this._value);
        }

        public static DocumentKey FromJson(string p)
        {
            return JsonConvert.DeserializeObject<DocumentKey>(p);
        }

        public string ToJson()
        {
            //To:DO
            return JsonConvert.SerializeObject(this);
        }

        #region ICompactSerializable Methods
        public void Deserialize(Common.Serialization.IO.CompactReader reader)
        {
            //_value = reader.Read() as string
            _value = reader.ReadObject();
            _valueType = _value.GetType();
        }

        public void Serialize(Common.Serialization.IO.CompactWriter writer)
        {
            //TODO:
           // writer.Write(JsonConvert.SerializeObject(_value));
            writer.WriteObject(_value);
        }
        #endregion

        #region IComparable Methods
        public int CompareTo(object docKey)
        {
            DocumentKey doc = docKey as DocumentKey;
            object obj = doc.Value;

            if (_value == null && obj == null)
                return 0;

            if (_value == null)
                return -1;

            if (obj == null)
                return 1;

            Type valueType = obj.GetType();
            if (!valueType.Equals(_valueType))
            {
                throw new Exception("In DocumentKey: Invalid Type for DocumentKey Comparison");
            }
            switch (Type.GetTypeCode(valueType))
            {
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    long field1 = long.Parse(_value.ToString());
                    long field2 = long.Parse(obj.ToString());
                    return field1.CompareTo(field2);
                case TypeCode.Decimal:
                case TypeCode.Single:
                case TypeCode.Double:
                    double dField1 = double.Parse(_value.ToString());
                    double dField2 = double.Parse(obj.ToString());
                    return dField1.CompareTo(dField2);
                case TypeCode.Char:
                case TypeCode.String:
                    string sField1 = _value.ToString();
                    string sField2 = obj.ToString();
                    return sField1.CompareTo(sField2);
                case TypeCode.DateTime:
                    DateTime dtField1 = DateTime.Parse(_value.ToString());
                    DateTime dtField2 = DateTime.Parse(obj.ToString());
                    return dtField1.CompareTo(dtField2);
                default:
                    throw new Exception("In DocumentKey: Invalid Type for DocumentKey Comparison");
            }
        }
        #endregion

        //public static DocumentKey FromJson(string p)
        //{
        //    return JsonConvert.DeserializeObject<DocumentKey>(p);
        //}

        //public string ToJson()
        //{
        //    return JsonConvert.SerializeObject(this);
        //}

        public object Clone()
        {
            DocumentKey clone = new DocumentKey();
            clone._value = _value;
            clone._valueType = _valueType;

            return clone;
        }
    }
}