public static IEnumerable <TeamSnapApi.Event> UnpackEvents(this ReadDocument doc)
    {
        return(doc.Collection.Items.Select(x =>
        {
            TeamSnapApi.Event r = new TeamSnapApi.Event
            {
                Id = long.Parse(x.Data.GetDataByName("id").Value.ToString()),

                TeamId = long.Parse(x.Data.GetDataByName("team_id").Value.ToString()),

                Name = x.Data.GetDataByName("name").Value.ToString(),

                IsTimeTBD = bool.Parse(x.Data.GetDataByName("is_tbd").Value.ToString()),

                StartDate = x.Data.GetDataByName("start_date").Value.ToObject <DateTime>(),

                IsCancelled = bool.Parse(x.Data.GetDataByName("is_canceled").Value.ToString()),

                IsGame = bool.Parse(x.Data.GetDataByName("is_game").Value.ToString()),

                LocationName = x.Data.GetDataByName("location_name").Value.ToString(),

                OpponentName = x.Data.GetDataByName("opponent_name").Value.ToString(),

                Notes = x.Data.GetDataByName("notes").Value.ToString()
            };

            int.TryParse(x.Data.GetDataByName("duration_in_minutes").Value.ToString(), out int duration);

            r.DurationMinutes = duration;


            int.TryParse(x.Data.GetDataByName("minutes_to_arrive_early").Value.ToString(), out int arriveEarlyMin);

            r.ArriveEarlyMinutes = arriveEarlyMin;

            return r;
        }));
    }
    public static IEnumerable <CompareResult> Compare(IEnumerable <TeamSnapApi.Event> tsEvents, IEnumerable <TwinRinksEvent> trEvents, HashSet <DateTime> exlusions = null)
    {
        List <CompareResult> res = new List <CompareResult>();

        HashSet <long> seenTsEvents = new HashSet <long>();

        foreach (TwinRinksEvent trEvent in trEvents)
        {
            if (exlusions != null && exlusions.Contains(trEvent.EventDate))
            {
                continue;
            }

            IEnumerable <TeamSnapApi.Event> tsEventsOnDay = tsEvents.Where(x => ToCSTTime(x.StartDate).Date == trEvent.EventDate.Date && x.IsCancelled == false).ToArray();

            seenTsEvents = new HashSet <long>(tsEventsOnDay.Select(e => e.Id));

            if (tsEventsOnDay.Any())
            {
                TeamSnapApi.Event foundTsEventByExactTime = tsEventsOnDay.Where(x => ToCSTTime(x.StartDate).TimeOfDay == trEvent.EventStart).FirstOrDefault();

                if (foundTsEventByExactTime != null)
                {
                    if (foundTsEventByExactTime.LocationName.Equals(trEvent.Location, StringComparison.InvariantCultureIgnoreCase) && foundTsEventByExactTime.IsGame == (trEvent.EventType == TwinRinksEventType.Game))
                    {
                        //matched location and event type
                    }
                    else
                    {
                        res.Add(new CompareResult()
                        {
                            Type = DifferenceType.WrongLocOrEvtType, TR_EventTime = (trEvent.EventDate + trEvent.EventStart), TR_EventType = trEvent.EventType, TR_Location = trEvent.Location, TS_Location = foundTsEventByExactTime.LocationName, TS_EventType = foundTsEventByExactTime.IsGame ? TwinRinksEventType.Game : TwinRinksEventType.Practice, TS_NumEvents = tsEventsOnDay.Count()
                        });

                        //not matched on location or event type
                    }
                }
                else
                {
                    TeamSnapApi.Event foundTsEventByEventTypeAndLocation = tsEventsOnDay.Where(x => x.LocationName.Equals(trEvent.Location, StringComparison.InvariantCultureIgnoreCase) && x.IsGame == (trEvent.EventType == TwinRinksEventType.Game)).FirstOrDefault();

                    if (foundTsEventByEventTypeAndLocation != null)
                    {
                        //time not matched
                        res.Add(new CompareResult()
                        {
                            Type = DifferenceType.WrongTimeInTeamSnap, TR_EventTime = (trEvent.EventDate + trEvent.EventStart), TR_EventType = trEvent.EventType, TR_Location = trEvent.Location, TS_EventTime = ToCSTTime(foundTsEventByEventTypeAndLocation.StartDate), TS_NumEvents = tsEventsOnDay.Count(), TS_EventID = foundTsEventByEventTypeAndLocation.Id
                        });
                    }
                    else
                    {
                        //nothing matching
                        res.Add(new CompareResult()
                        {
                            Type = DifferenceType.NotInTeamSnap, TR_EventTime = (trEvent.EventDate + trEvent.EventStart), TR_EventType = trEvent.EventType, TR_Location = trEvent.Location, TS_NumEvents = tsEventsOnDay.Count()
                        });
                    }
                }
            }
            else
            {
                //nothing on this date

                res.Add(new CompareResult()
                {
                    Type = DifferenceType.NotInTeamSnap, TR_EventTime = (trEvent.EventDate + trEvent.EventStart), TR_EventType = trEvent.EventType, TR_Location = trEvent.Location
                });
            }
        }

        foreach (TeamSnapApi.Event tsEvent in tsEvents.Where(x => !x.IsCancelled && ToCSTTime(x.StartDate) > ToCSTTime(DateTime.Now.Date)))
        {
            if (exlusions != null && exlusions.Contains(ToCSTTime(tsEvent.StartDate).Date))
            {
                continue;
            }

            if (!seenTsEvents.Contains(tsEvent.Id))
            {
                TwinRinksEvent trEvent = trEvents.Where(x => ToCSTTime(tsEvent.StartDate).Date == x.EventDate.Date).Where(x => ToCSTTime(tsEvent.StartDate).TimeOfDay == x.EventStart).FirstOrDefault();

                int cnt = trEvents.Where(x => ToCSTTime(tsEvent.StartDate).Date == x.EventDate.Date).Count();

                if (trEvent == null)
                {
                    res.Add(new CompareResult()
                    {
                        Type = DifferenceType.NotOnTwinRinksWebSite, TS_EventTime = ToCSTTime(tsEvent.StartDate), TS_Location = tsEvent.LocationName, TS_EventType = tsEvent.IsGame ? TwinRinksEventType.Game : TwinRinksEventType.Practice, TR_NumEvents = cnt, TS_EventID = tsEvent.Id
                    });
                }
            }
        }



        return(res);
    }