/// <summary>
        ///     Handles the Click event of the btnSearch control.
        ///     Implements the searching algorithm by accumulating the criteria and filtering the available players based on those criteria.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">
        ///     The <see cref="RoutedEventArgs" /> instance containing the event data.
        /// </param>
        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            dgvPlayerStats.ItemsSource = null;
            Dictionary<int, PlayerStats> pst = MainWindow.PST;
            IEnumerable<KeyValuePair<int, PlayerStats>> filteredPST = pst.AsEnumerable();

            if (!String.IsNullOrWhiteSpace(txtLastName.Text))
            {
                filteredPST = cmbLastNameSetting.SelectedItem.ToString() == "Contains"
                                  ? filteredPST.Where(pair => pair.Value.LastName.Contains(txtLastName.Text))
                                  : filteredPST.Where(pair => pair.Value.LastName == txtLastName.Text);
            }

            if (!String.IsNullOrWhiteSpace(txtFirstName.Text))
            {
                filteredPST = cmbFirstNameSetting.SelectedItem.ToString() == "Contains"
                                  ? filteredPST.Where(pair => pair.Value.FirstName.Contains(txtFirstName.Text))
                                  : filteredPST.Where(pair => pair.Value.FirstName == txtFirstName.Text);
            }

            if (cmbPosition1.SelectedIndex != -1 && cmbPosition1.SelectedItem.ToString() != "Any")
            {
                filteredPST = filteredPST.Where(pair => pair.Value.Position1.ToString() == cmbPosition1.SelectedItem.ToString());
            }

            if (cmbPosition2.SelectedIndex != -1 && cmbPosition2.SelectedItem.ToString() != "Any")
            {
                filteredPST = filteredPST.Where(pair => pair.Value.Position2.ToString() == cmbPosition2.SelectedItem.ToString());
            }

            if (cmbContractOpt.SelectedIndex != -1 && cmbContractOpt.SelectedItem.ToString() != "Any")
            {
                filteredPST = filteredPST.Where(pair => pair.Value.Contract.Option.ToString() == cmbContractOpt.SelectedItem.ToString());
            }

            if (chkIsActive.IsChecked.GetValueOrDefault())
            {
                filteredPST = filteredPST.Where(pair => pair.Value.IsActive);
            }
            else if (chkIsActive.IsChecked != null)
            {
                filteredPST = filteredPST.Where(pair => !pair.Value.IsActive);
            }

            if (chkIsInjured.IsChecked.GetValueOrDefault())
            {
                filteredPST = filteredPST.Where(pair => pair.Value.Injury.IsInjured);
            }
            else if (chkIsInjured.IsChecked != null)
            {
                filteredPST = filteredPST.Where(pair => !pair.Value.Injury.IsInjured);
            }

            if (chkIsAllStar.IsChecked.GetValueOrDefault())
            {
                filteredPST = filteredPST.Where(pair => pair.Value.IsAllStar);
            }
            else if (chkIsAllStar.IsChecked != null)
            {
                filteredPST = filteredPST.Where(pair => !pair.Value.IsAllStar);
            }

            if (chkIsChampion.IsChecked.GetValueOrDefault())
            {
                filteredPST = filteredPST.Where(pair => pair.Value.IsNBAChampion);
            }
            else if (chkIsChampion.IsChecked != null)
            {
                filteredPST = filteredPST.Where(pair => !pair.Value.IsNBAChampion);
            }

            if (cmbTeam.SelectedItem != null && !String.IsNullOrEmpty(cmbTeam.SelectedItem.ToString()) &&
                chkIsActive.IsChecked.GetValueOrDefault() && cmbTeam.SelectedItem.ToString() != "- Any -")
            {
                filteredPST = filteredPST.Where(pair => pair.Value.TeamF == GetTeamIDFromDisplayName(cmbTeam.SelectedItem.ToString()));
            }

            Dictionary<int, PlayerStats> pstDict = filteredPST.ToDictionary(ps => ps.Value.ID, ps => ps.Value);
            List<PlayerStatsRow> psrListSea = pstDict.Values.AsParallel().Select(ps => new PlayerStatsRow(ps)).ToList();
            List<PlayerStatsRow> psrListPl = pstDict.Values.AsParallel().Select(ps => new PlayerStatsRow(ps)).ToList();
            List<TeamStatsRow> tsrListSea = MainWindow.TST.Values.Select(ts => new TeamStatsRow(ts)).ToList();
            List<TeamStatsRow> tsrListPl = MainWindow.TST.Values.Select(ts => new TeamStatsRow(ts, true)).ToList();
            List<TeamStatsRow> tsrOppListSea = MainWindow.TSTOpp.Values.Select(ts => new TeamStatsRow(ts)).ToList();
            List<TeamStatsRow> tsrOppListPl = MainWindow.TSTOpp.Values.Select(ts => new TeamStatsRow(ts, true)).ToList();

            #region Custom Expressions parsing

            dgvPlayerStats.Columns.SkipWhile(col => col.Header.ToString() != "Custom")
                          .Skip(1)
                          .ToList()
                          .ForEach(col => dgvPlayerStats.Columns.Remove(col));

            dgvPlayoffStats.Columns.SkipWhile(col => col.Header.ToString() != "Custom")
                           .Skip(1)
                           .ToList()
                           .ForEach(col => dgvPlayoffStats.Columns.Remove(col));

            List<int> includedIDs = pstDict.Keys.ToList();
            var context = new ExpressionContext();
            int j = 0;
            string message = "";
            foreach (string itemS in _customExpressions)
            {
                Dictionary<int, string> expByPlayer = includedIDs.ToDictionary(id => id, id => "");
                Dictionary<int, string> plExpByPlayer = includedIDs.ToDictionary(id => id, id => "");
                string[] itemSParts = itemS.Split(new[] {": "}, StringSplitOptions.None);
                string name = itemSParts[0];
                string item = itemSParts[1];
                string decimalPoints = itemSParts[3];
                string[] parts = item.Split(_splitOn.ToArray(), StringSplitOptions.RemoveEmptyEntries);
                int k = 0;
                PlayerStatsRow curPSR;
                PlayerStatsRow curPSRPl;

                var ignoredIDs = new List<int>();
                var ignoredPlIDs = new List<int>();
                for (int i = 0; i < item.Length; i++)
                {
                    char c1 = item[i];
                    char c2;
                    if (_numericOperators.Contains(c1.ToString()))
                    {
                        foreach (int id in includedIDs)
                        {
                            if (!ignoredIDs.Contains(id))
                            {
                                expByPlayer[id] += c1;
                            }
                            if (!ignoredPlIDs.Contains(id))
                            {
                                plExpByPlayer[id] += c1;
                            }
                        }
                    }
                    else if (c1 == '$')
                    {
                        try
                        {
                            try
                            {
                                c2 = item[i + 1];
                            }
                            catch (IndexOutOfRangeException)
                            {
                                MessageBox.Show("Encountered '$' at end of custom expression.");
                                return;
                            }
                            bool isPlayer;
                            bool? isOwnTeam = null;
                            string part;
                            if (c2 != '$')
                            {
                                part = parts[k++].Substring(1);
                                isPlayer = true;
                            }
                            else
                            {
                                part = parts[k++].Substring(3);
                                isPlayer = false;
                                if (item[i + 2] == 't')
                                {
                                    isOwnTeam = true;
                                }
                                else if (item[i + 2] == 'o')
                                {
                                    isOwnTeam = false;
                                }
                                else
                                {
                                    MessageBox.Show("Encountered unknown/malformed parameter: " + parts[k - 1]);
                                    return;
                                }
                            }
                            part = part.Replace("3P", "TP");
                            part = part.Replace("TO", "TOS");
                            part = part.Replace("%", "p");
                            foreach (int id in includedIDs)
                            {
                                if (!ignoredIDs.Contains(id))
                                {
                                    string val;
                                    curPSR = psrListSea.Single(psr => psr.ID == id);
                                    if (isPlayer)
                                    {
                                        val =
                                            Convert.ToDouble(typeof (PlayerStatsRow).GetProperty(part).GetValue(curPSR, null))
                                                   .ToString(".0###############");
                                    }
                                    else
                                    {
                                        if (curPSR.TeamF == -1)
                                        {
                                            val = "NaN";
                                        }
                                        else
                                        {
                                            TeamStatsRow curTSR = isOwnTeam == true
                                                                      ? tsrListSea.Single(tsr => tsr.ID == curPSR.TeamF)
                                                                      : tsrOppListSea.Single(tsr => tsr.ID == curPSR.TeamF);
                                            val =
                                                Convert.ToDouble(typeof (TeamStatsRow).GetProperty(part).GetValue(curTSR, null))
                                                       .ToString(".0###############");
                                        }
                                    }
                                    if (val != "NaN")
                                    {
                                        expByPlayer[id] += val;
                                    }
                                    else
                                    {
                                        ignoredIDs.Add(id);
                                        expByPlayer[id] = "$$INVALID";
                                    }
                                }
                                if (!ignoredPlIDs.Contains(id))
                                {
                                    string plVal;
                                    curPSRPl = psrListPl.Single(psr => psr.ID == id);
                                    if (isPlayer)
                                    {
                                        plVal =
                                            Convert.ToDouble(typeof (PlayerStatsRow).GetProperty(part).GetValue(curPSRPl, null))
                                                   .ToString(".0###############");
                                    }
                                    else
                                    {
                                        if (curPSRPl.TeamF == -1)
                                        {
                                            plVal = "NaN";
                                        }
                                        else
                                        {
                                            TeamStatsRow curTSRPl = isOwnTeam == true
                                                                        ? tsrListPl.Single(tsr => tsr.ID == curPSRPl.TeamF)
                                                                        : tsrOppListPl.Single(tsr => tsr.ID == curPSRPl.TeamF);
                                            plVal =
                                                Convert.ToDouble(typeof (TeamStatsRow).GetProperty(part).GetValue(curTSRPl, null))
                                                       .ToString(".0###############");
                                        }
                                    }
                                    if (plVal != "NaN")
                                    {
                                        plExpByPlayer[id] += plVal;
                                    }
                                    else
                                    {
                                        ignoredPlIDs.Add(id);
                                        plExpByPlayer[id] = "$$INVALID";
                                    }
                                }
                            }
                            if (isPlayer)
                            {
                                i += part.Length; // should be Length-1 but we're using Substring(1) in part's initialization
                            }
                            else
                            {
                                i += part.Length + 2; // we're using Substring(3)
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("Error encountered while trying to evaluate custom expression parameter.\n\n" + ex.Message);
                            return;
                        }
                    }
                    else if (Tools.IsNumeric(parts[k]))
                    {
                        string part = parts[k++];
                        foreach (int id in includedIDs)
                        {
                            if (!ignoredIDs.Contains(id))
                            {
                                expByPlayer[id] += part;
                            }
                            if (!ignoredPlIDs.Contains(id))
                            {
                                plExpByPlayer[id] += part;
                            }
                        }
                        i += part.Length - 1;
                    }
                }
                foreach (int id in includedIDs)
                {
                    curPSR = psrListSea.Single(psr => psr.ID == id);
                    curPSRPl = psrListPl.Single(psr => psr.ID == id);
                    if (!ignoredIDs.Contains(id))
                    {
                        try
                        {
                            IGenericExpression<double> compiled = context.CompileGeneric<double>(expByPlayer[id]);
                            curPSR.Custom.Add(compiled.Evaluate());
                        }
                        catch (Exception ex)
                        {
                            message = string.Format("Expression {0}:\n{1}\nevaluated to\n{2}\n\nError: {3}", (j + 1), item,
                                                    expByPlayer[id], ex.Message);
                            curPSR.Custom.Add(double.NaN);
                        }
                    }
                    else
                    {
                        curPSR.Custom.Add(double.NaN);
                    }
                    if (!ignoredPlIDs.Contains(id))
                    {
                        try
                        {
                            IGenericExpression<double> compiled = context.CompileGeneric<double>(plExpByPlayer[id]);
                            curPSRPl.Custom.Add(compiled.Evaluate());
                        }
                        catch (Exception ex)
                        {
                            message = string.Format("Expression {0}:\n{1}\nevaluated to\n{2}\n\nError: {3}", (j + 1), item,
                                                    plExpByPlayer[id], ex.Message);
                            curPSRPl.Custom.Add(double.NaN);
                        }
                    }
                    else
                    {
                        curPSRPl.Custom.Add(double.NaN);
                    }
                }
                dgvPlayerStats.Columns.Add(new DataGridTextColumn
                    {
                        Header = name,
                        Binding =
                            new Binding
                                {
                                    Path = new PropertyPath(string.Format("Custom[{0}]", j)),
                                    Mode = BindingMode.OneWay,
                                    StringFormat = "{0:F" + decimalPoints + "}"
                                }
                    });
                dgvPlayoffStats.Columns.Add(new DataGridTextColumn
                    {
                        Header = name,
                        Binding =
                            new Binding
                                {
                                    Path = new PropertyPath(string.Format("Custom[{0}]", j)),
                                    Mode = BindingMode.OneWay,
                                    StringFormat = "{0:F" + decimalPoints + "}"
                                }
                    });
                j++;
            }

            #endregion Custom Expressions parsing

            ICollectionView psrView = CollectionViewSource.GetDefaultView(psrListSea);
            psrView.Filter = filter;

            ICollectionView plPSRView = CollectionViewSource.GetDefaultView(psrListPl);
            plPSRView.Filter = filter;

            dgvPlayerStats.ItemsSource = psrView;
            dgvPlayoffStats.ItemsSource = plPSRView;

            string sortColumn;
            foreach (string item in lstMetrics.Items.Cast<string>())
            {
                sortColumn = item.Split(' ')[0];
                sortColumn = sortColumn.Replace("%", "p");
                psrView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
                plPSRView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
            }
            foreach (string item in lstAvg.Items.Cast<string>())
            {
                sortColumn = item.Split(' ')[0];
                sortColumn = sortColumn.Replace("3P", "TP");
                sortColumn = sortColumn.Replace("%", "p");
                psrView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
                plPSRView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
            }
            foreach (string item in lstTotals.Items.Cast<string>())
            {
                sortColumn = item.Split(' ')[0];
                sortColumn = sortColumn.Replace("3P", "TP");
                sortColumn = sortColumn.Replace("TO", "TOS");
                psrView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
                plPSRView.SortDescriptions.Add(new SortDescription(sortColumn, ListSortDirection.Descending));
            }

            if (psrView.SortDescriptions.Count == 0)
            {
                dgvPlayerStats.Columns.Single(col => col.Header.ToString() == "GmSc").SortDirection = ListSortDirection.Descending;
                dgvPlayoffStats.Columns.Single(col => col.Header.ToString() == "GmSc").SortDirection = ListSortDirection.Descending;
                psrView.SortDescriptions.Add(new SortDescription("GmSc", ListSortDirection.Descending));
                plPSRView.SortDescriptions.Add(new SortDescription("GmSc", ListSortDirection.Descending));
            }

            tbcPlayerSearch.SelectedItem = tabResults;

            if (!String.IsNullOrWhiteSpace(message))
            {
                const string warning = "An error occurred while trying to evaluate one or more of the custom column expressions:\n\n";
                const string contact =
                    "\n\nIf you believe your expression is correct and that you shouldn't be getting this error, contact the developer " +
                    "and give them this information.";
                var cmw = new CopyableMessageWindow(warning + message + contact, "Error while evaluating expression", beep: true);
                cmw.ShowDialog();
            }
        }
 private void OnChangelogDownloadCompleted(object sender, AsyncCompletedEventArgs asyncCompletedEventArgs)
 {
     List<string> lines = File.ReadAllLines(App.AppTempPath + "changelog.txt").ToList();
     lines.Add("");
     var cmw = new CopyableMessageWindow(lines.Aggregate((l1, l2) => l1 + "\n" + l2), "NBA Stats Tracker - What's New",
                                         TextAlignment.Left);
     cmw.ShowDialog();
 }
        /// <summary>
        ///     Imports all team (and optionally) player stats from an REDitor-exported set of CSV files.
        /// </summary>
        /// <param name="tst">The team stats dictionary.</param>
        /// <param name="tstOpp">The opposing team stats dictionary.</param>
        /// <param name="pst">The player stats dictionary.</param>
        /// <param name="folder">The folder containing the exported CSV files.</param>
        /// <param name="teamsOnly">
        ///     if set to <c>true</c>, only team stats will be imported.
        /// </param>
        /// <returns></returns>
        public static int ImportAll(ref Dictionary<int, TeamStats> tst, ref Dictionary<int, TeamStats> tstOpp,
                                    ref Dictionary<int, PlayerStats> pst, string folder, bool teamsOnly = false)
        {
            List<Dictionary<string, string>> teams;
            List<Dictionary<string, string>> players;
            List<Dictionary<string, string>> teamStats;
            List<Dictionary<string, string>> playerStats;

            if (populateREDitorDictionaryLists(folder, out teams, out players, out teamStats, out playerStats) == -1)
            {
                return -1;
            }

            var importMessages = new List<string>();
            var tradesList = new List<string>();
            var faSigningsList = new List<string>();
            var reSigningsList = new List<string>();
            var waiversList = new List<string>();
            var injuredList = new List<string>();
            var reInjuredList = new List<string>();
            var recoveredList = new List<string>();

            #region Import Teams & Team Stats

            var legalTTypes = new List<string> {"0", "4"};

            List<Dictionary<string, string>> validTeams = teams.FindAll(delegate(Dictionary<string, string> team)
                {
                    if (legalTTypes.IndexOf(team["TType"]) != -1)
                    {
                        return true;
                    }
                    return false;
                });

            List<Dictionary<string, string>> activeTeams = validTeams.FindAll(delegate(Dictionary<string, string> team)
                {
                    if (team["StatCurS"] != "-1")
                    {
                        return true;
                    }
                    return false;
                });
            if (activeTeams.Count < 30)
            {
                var dlw = new DualListWindow(validTeams, activeTeams);
                if (dlw.ShowDialog() == false)
                {
                    return -1;
                }

                activeTeams = new List<Dictionary<string, string>>(MainWindow.SelectedTeams);

                if (MainWindow.SelectedTeamsChanged)
                {
                    CreateSettingsFile(activeTeams, folder);
                }
            }

            bool madeNew = false;

            if (tst.Count != activeTeams.Count)
            {
                tst = new Dictionary<int, TeamStats>();
                tstOpp = new Dictionary<int, TeamStats>();
                madeNew = true;
            }

            Dictionary<int, TeamStats> oldTST = tst.ToDictionary(ts => ts.Key, ts => ts.Value.Clone());
            Dictionary<int, TeamStats> oldtstOpp = tstOpp.ToDictionary(ts => ts.Key, ts => ts.Value.Clone());
            Dictionary<int, PlayerStats> oldPST = pst.ToDictionary(ps => ps.Key, ps => ps.Value.Clone());

            CreateDivisions();

            var activeTeamsIDs = new List<int>();
            var rosters = new Dictionary<int, List<int>>();
            activeTeams.Sort((p1, p2) => Convert.ToInt32(p1["ID"]).CompareTo(Convert.ToInt32(p2["ID"])));
            foreach (var team in activeTeams)
            {
                string name = team["Name"];
                int redID = Convert.ToInt32(team["ID"]);
                if (tst.Values.All(ts => ts.Name != name))
                {
                    if (tst.Keys.Contains(redID))
                    {
                        string oldName = tst[redID].Name;
                        tst[redID].Name = name;
                        tstOpp[redID].Name = name;
                        if (oldName == tst[redID].DisplayName)
                        {
                            tst[redID].DisplayName = name;
                            tstOpp[redID].DisplayName = name;
                        }
                    }
                }
                int id = tst.Values.Single(ts => ts.Name == name).ID;
                activeTeamsIDs.Add(Convert.ToInt32(team["ID"]));

                if (madeNew)
                {
                    tst[id] = new TeamStats(id, name);
                    tstOpp[id] = new TeamStats(id, name);
                }

                int sStatsID = Convert.ToInt32(team["StatCurS"]);
                int pStatsID = Convert.ToInt32(team["StatCurP"]);

                Dictionary<string, string> sStats = teamStats.Find(delegate(Dictionary<string, string> s)
                    {
                        if (s["ID"] == sStatsID.ToString())
                        {
                            return true;
                        }
                        return false;
                    });

                tst[id].ID = id;
                tstOpp[id].ID = id;
                tst[id].Division = Convert.ToInt32(team["Division"]);
                tstOpp[id].Division = Convert.ToInt32(team["Division"]);

                if (sStats != null)
                {
                    tst[id].Record[0] = Convert.ToByte(sStats["Wins"]);
                    tst[id].Record[1] = Convert.ToByte(sStats["Losses"]);
                    tst[id].Totals[TAbbr.MINS] = Convert.ToUInt16(sStats["Mins"]);
                    tst[id].Totals[TAbbr.PF] = Convert.ToUInt16(sStats["PtsFor"]);
                    tst[id].Totals[TAbbr.PA] = Convert.ToUInt16(sStats["PtsAg"]);
                    tst[id].Totals[TAbbr.FGM] = Convert.ToUInt16(sStats["FGMade"]);
                    tst[id].Totals[TAbbr.FGA] = Convert.ToUInt16(sStats["FGAtt"]);
                    tst[id].Totals[TAbbr.TPM] = Convert.ToUInt16(sStats["3PTMade"]);
                    tst[id].Totals[TAbbr.TPA] = Convert.ToUInt16(sStats["3PTAtt"]);
                    tst[id].Totals[TAbbr.FTM] = Convert.ToUInt16(sStats["FTMade"]);
                    tst[id].Totals[TAbbr.FTA] = Convert.ToUInt16(sStats["FTAtt"]);
                    tst[id].Totals[TAbbr.DREB] = Convert.ToUInt16(sStats["DRebs"]);
                    tst[id].Totals[TAbbr.OREB] = Convert.ToUInt16(sStats["ORebs"]);
                    tst[id].Totals[TAbbr.STL] = Convert.ToUInt16(sStats["Steals"]);
                    tst[id].Totals[TAbbr.BLK] = Convert.ToUInt16(sStats["Blocks"]);
                    tst[id].Totals[TAbbr.AST] = Convert.ToUInt16(sStats["Assists"]);
                    tst[id].Totals[TAbbr.FOUL] = Convert.ToUInt16(sStats["Fouls"]);
                    tst[id].Totals[TAbbr.TOS] = Convert.ToUInt16(sStats["TOs"]);

                    if (pStatsID != -1)
                    {
                        Dictionary<string, string> pStats = teamStats.Find(delegate(Dictionary<string, string> s)
                            {
                                if (s["ID"] == pStatsID.ToString())
                                {
                                    return true;
                                }
                                return false;
                            });
                        tst[id].PlRecord[0] = Convert.ToByte(pStats["Wins"]);
                        tst[id].PlRecord[1] = Convert.ToByte(pStats["Losses"]);
                        tst[id].PlTotals[TAbbr.MINS] = Convert.ToUInt16(pStats["Mins"]);
                        tst[id].PlTotals[TAbbr.PF] = Convert.ToUInt16(pStats["PtsFor"]);
                        tst[id].PlTotals[TAbbr.PA] = Convert.ToUInt16(pStats["PtsAg"]);
                        tst[id].PlTotals[TAbbr.FGM] = Convert.ToUInt16(pStats["FGMade"]);
                        tst[id].PlTotals[TAbbr.FGA] = Convert.ToUInt16(pStats["FGAtt"]);
                        tst[id].PlTotals[TAbbr.TPM] = Convert.ToUInt16(pStats["3PTMade"]);
                        tst[id].PlTotals[TAbbr.TPA] = Convert.ToUInt16(pStats["3PTAtt"]);
                        tst[id].PlTotals[TAbbr.FTM] = Convert.ToUInt16(pStats["FTMade"]);
                        tst[id].PlTotals[TAbbr.FTA] = Convert.ToUInt16(pStats["FTAtt"]);
                        tst[id].PlTotals[TAbbr.DREB] = Convert.ToUInt16(pStats["DRebs"]);
                        tst[id].PlTotals[TAbbr.OREB] = Convert.ToUInt16(pStats["ORebs"]);
                        tst[id].PlTotals[TAbbr.STL] = Convert.ToUInt16(pStats["Steals"]);
                        tst[id].PlTotals[TAbbr.BLK] = Convert.ToUInt16(pStats["Blocks"]);
                        tst[id].PlTotals[TAbbr.AST] = Convert.ToUInt16(pStats["Assists"]);
                        tst[id].PlTotals[TAbbr.FOUL] = Convert.ToUInt16(pStats["Fouls"]);
                        tst[id].PlTotals[TAbbr.TOS] = Convert.ToUInt16(pStats["TOs"]);
                    }
                }

                tst[id].CalcAvg();

                rosters[id] = new List<int>
                    {
                        Convert.ToInt32(team["Ros_PG"]),
                        Convert.ToInt32(team["Ros_SG"]),
                        Convert.ToInt32(team["Ros_SF"]),
                        Convert.ToInt32(team["Ros_PF"]),
                        Convert.ToInt32(team["Ros_C"])
                    };
                for (int i = 6; i <= 12; i++)
                {
                    int cur = Convert.ToInt32(team["Ros_S" + i.ToString()]);
                    if (cur != -1)
                    {
                        rosters[id].Add(cur);
                    }
                    else
                    {
                        break;
                    }
                }
                for (int i = 13; i <= 20; i++)
                {
                    int cur = Convert.ToInt32(team["Ros_R" + i.ToString()]);
                    if (cur != -1)
                    {
                        rosters[id].Add(cur);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            #endregion

            #region Import Players & Player Stats

            var duplicatePlayers = new List<string>();
            if (!teamsOnly)
            {
                List<Dictionary<string, string>> validPlayers = players.FindAll(delegate(Dictionary<string, string> player)
                    {
                        if (player["PlType"] == "4" || player["PlType"] == "5" || player["PlType"] == "6")
                        {
                            if ((player["IsFA"] == "0" && player["TeamID1"] != "-1") || (player["IsFA"] == "1"))
                            {
                                return true;
                            }
                        }
                        return false;
                    });

                foreach (var player in validPlayers)
                {
                    int playerID = Convert.ToInt32(player["ID"]);

                    string lastName = player["Last_Name"];
                    string firstName = player["First_Name"];

            #if DEBUG
                    //if (LastName == "Felton") System.Diagnostics.Debugger.Break();
            #endif

                    int pTeam;
                    var curTeam = new TeamStats();
                    try
                    {
                        pTeam = rosters.Single(r => r.Value.Contains(playerID)).Key;
                        curTeam = tst[pTeam];
                    }
                    catch (InvalidOperationException)
                    {
                        pTeam = -1;
                    }

                    if (pTeam == -1 && player["IsFA"] != "1")
                    {
                        if (pst.ContainsKey(playerID) && pst[playerID].LastName == lastName && pst[playerID].FirstName == firstName)
                        {
                            pst[playerID].IsActive = false;
                            pst[playerID].TeamF = -1;
                            pst[playerID].IsHidden = true;
                        }
                        continue;
                    }

                    int playerStatsID = Convert.ToInt32(player["StatY0"]);

                    Dictionary<string, string> plStats = playerStats.Find(delegate(Dictionary<string, string> s)
                        {
                            if (s["ID"] == playerStatsID.ToString())
                            {
                                return true;
                            }
                            return false;
                        });

                    if (pst.ContainsKey(playerID) && (pst[playerID].LastName != lastName || pst[playerID].FirstName != firstName))
                    {
                        List<KeyValuePair<int, PlayerStats>> candidates =
                            pst.Where(
                                pair =>
                                pair.Value.LastName == lastName && pair.Value.FirstName == firstName && pair.Value.IsHidden == false)
                               .ToList();
                        if (candidates.Count > 0)
                        {
                            bool found = false;
                            Dictionary<int, TeamStats> temptst = tst;
                            List<KeyValuePair<int, PlayerStats>> c2 =
                                candidates.Where(pair => temptst.ContainsKey(pair.Value.TeamF)).ToList();
                            if (c2.Count() == 1)
                            {
                                playerID = c2.First().Value.ID;
                                found = true;
                            }
                            else
                            {
                                List<KeyValuePair<int, PlayerStats>> c4 =
                                    candidates.Where(pair => pair.Value.YearOfBirth.ToString() == player["BirthYear"]).ToList();
                                if (c4.Count == 1)
                                {
                                    playerID = c4.First().Value.ID;
                                    found = true;
                                }
                                else
                                {
                                    if (pTeam != -1)
                                    {
                                        List<KeyValuePair<int, PlayerStats>> c3 =
                                            candidates.Where(pair => pair.Value.TeamF == curTeam.ID).ToList();
                                        if (c3.Count == 1)
                                        {
                                            playerID = c3.First().Value.ID;
                                            found = true;
                                        }
                                    }
                                }
                            }
                            if (!found)
                            {
                                var choices = new List<string>();
                                foreach (var pair in candidates)
                                {
                                    string choice = String.Format("{0}: {1} {2} (Born {3}", pair.Value.ID, pair.Value.FirstName,
                                                                  pair.Value.LastName, pair.Value.YearOfBirth);
                                    if (pair.Value.IsActive)
                                    {
                                        choice += String.Format(", plays in {0}", tst[pair.Value.TeamF].DisplayName);
                                    }
                                    else
                                    {
                                        choice += ", free agent";
                                    }
                                    choice += ")";
                                    choices.Add(choice);
                                }
                                string message = String.Format("{0}: {1} {2} (Born {3}", player["ID"], player["First_Name"],
                                                               player["Last_Name"], player["BirthYear"]);
                                if (pTeam != -1)
                                {
                                    message += String.Format(", plays in {0}", curTeam.DisplayName);
                                }
                                else
                                {
                                    message += ", free agent";
                                }
                                message += ")";
                                var ccw = new ComboChoiceWindow(message, choices);
                                if (ccw.ShowDialog() != true)
                                {
                                    duplicatePlayers.Add(firstName + " " + lastName);
                                    continue;
                                }
                                else
                                {
                                    playerID = Convert.ToInt32(ComboChoiceWindow.UserChoice.Split(':')[0]);
                                }
                            }
                        }
                        else
                        {
                            playerID = createNewPlayer(ref pst, player);
                        }
                    }
                    else if (!pst.ContainsKey(playerID))
                    {
                        playerID = createNewPlayer(ref pst, player, playerID);
                    }
                    PlayerStats curPlayer = pst[playerID];
                    PlayerStats oldPlayer = curPlayer.Clone();

                    curPlayer.Position1 = (Position) Enum.Parse(typeof (Position), player["Pos"]);
                    curPlayer.Position2 = (Position) Enum.Parse(typeof (Position), player["SecondPos"]);
                    curPlayer.IsHidden = false;
                    curPlayer.YearsPro = Convert.ToInt32(player["YearsPro"]);
                    curPlayer.YearOfBirth = Convert.ToInt32(player["BirthYear"]);
                    curPlayer.Contract.Option = (PlayerContractOption) Enum.Parse(typeof (PlayerContractOption), player["COption"]);
                    curPlayer.Contract.ContractSalaryPerYear.Clear();
                    for (int i = 1; i < 7; i++)
                    {
                        int salary = Convert.ToInt32(player["CYear" + i]);
                        if (salary == 0)
                        {
                            break;
                        }

                        curPlayer.Contract.ContractSalaryPerYear.Add(salary);
                    }
                    curPlayer.Height = Convert.ToDouble(player["Height"]);
                    curPlayer.Weight = Convert.ToDouble(player["Weight"]);
                    curPlayer.Injury = new PlayerInjury(Convert.ToInt32(player["InjType"]), Convert.ToInt32(player["InjDaysLeft"]));

                    if (plStats != null)
                    {
                        string teamReal = pTeam.ToString();
                        string team1 = plStats["TeamID2"];
                        string team2 = plStats["TeamID1"];
                        bool hasBeenTraded = (team1 != "-1");

                        if (teamReal != "-1" && player["IsFA"] != "1")
                        {
                            TeamStats ts = tst[pTeam];
                        }
                        if (hasBeenTraded)
                        {
                            Dictionary<string, string> teamS = teams.Find(delegate(Dictionary<string, string> s)
                                {
                                    if (s["ID"] == team2)
                                    {
                                        return true;
                                    }
                                    return false;
                                });
                        }

                        PlayerStats ps = curPlayer;
                        ps.TeamF = pTeam;
                        ps.TeamS = Convert.ToInt32(team2);

                        ps.IsActive = (player["IsFA"] != "1" && teamReal != "-1");

                        ps.Totals[PAbbr.GP] = Convert.ToUInt16(plStats["GamesP"]);
                        ps.Totals[PAbbr.GS] = Convert.ToUInt16(plStats["GamesS"]);
                        ps.Totals[PAbbr.MINS] = Convert.ToUInt16(plStats["Minutes"]);
                        ps.Totals[PAbbr.PTS] = Convert.ToUInt16(plStats["Points"]);
                        ps.Totals[PAbbr.DREB] = Convert.ToUInt16(plStats["DRebs"]);
                        ps.Totals[PAbbr.OREB] = Convert.ToUInt16(plStats["ORebs"]);
                        ps.Totals[PAbbr.AST] = Convert.ToUInt16(plStats["Assists"]);
                        ps.Totals[PAbbr.STL] = Convert.ToUInt16(plStats["Steals"]);
                        ps.Totals[PAbbr.BLK] = Convert.ToUInt16(plStats["Blocks"]);
                        ps.Totals[PAbbr.TOS] = Convert.ToUInt16(plStats["TOs"]);
                        ps.Totals[PAbbr.FOUL] = Convert.ToUInt16(plStats["Fouls"]);
                        ps.Totals[PAbbr.FGM] = Convert.ToUInt16(plStats["FGMade"]);
                        ps.Totals[PAbbr.FGA] = Convert.ToUInt16(plStats["FGAtt"]);
                        ps.Totals[PAbbr.TPM] = Convert.ToUInt16(plStats["3PTMade"]);
                        ps.Totals[PAbbr.TPA] = Convert.ToUInt16(plStats["3PTAtt"]);
                        ps.Totals[PAbbr.FTM] = Convert.ToUInt16(plStats["FTMade"]);
                        ps.Totals[PAbbr.FTA] = Convert.ToUInt16(plStats["FTAtt"]);

                        ps.IsAllStar = Convert.ToBoolean(Convert.ToInt32(plStats["IsAStar"]));
                        ps.IsNBAChampion = Convert.ToBoolean(Convert.ToInt32(plStats["IsChamp"]));

                        ps.Injury = new PlayerInjury(Convert.ToInt32(player["InjType"]), Convert.ToInt32(player["InjDaysLeft"]));

                        ps.CalcAvg();

                        pst[playerID] = ps;
                    }
                    else
                    {
                        PlayerStats ps = curPlayer;

                        ps.TeamF = pTeam;

                        ps.IsActive = player["IsFA"] != "1";
                        ps.Injury = new PlayerInjury(Convert.ToInt32(player["InjType"]), Convert.ToInt32(player["InjDaysLeft"]));

                        ps.CalcAvg();

                        pst[playerID] = ps;
                    }

                    #region Import Messsages

                    string name = String.Format("{0} {1}", curPlayer.FirstName, curPlayer.LastName);
                    if (oldPlayer.TeamF != curPlayer.TeamF)
                    {
                        string msg;
                        if (curPlayer.IsActive && oldPlayer.IsActive)
                        {
                            msg = String.Format("{0} was traded from the {1} to the {2}.", name, tst[oldPlayer.TeamF].DisplayName,
                                                tst[curPlayer.TeamF].DisplayName);
                            tradesList.Add(msg);
                        }
                        else if (oldPlayer.IsActive)
                        {
                            msg = String.Format("{0} was released from the {1}.", name, tst[oldPlayer.TeamF].DisplayName);
                            waiversList.Add(msg);
                        }
                    }

                    if (oldPlayer.Contract.GetYears() < curPlayer.Contract.GetYears() && curPlayer.IsActive)
                    {
                        string msg = name;
                        bool reSigned;
                        if (!oldPlayer.IsActive && curPlayer.IsActive)
                        {
                            reSigned = false;
                            msg += " signed ";
                        }
                        else
                        {
                            reSigned = true;
                            msg += " re-signed ";
                        }
                        msg += String.Format("with the {0} on a {1}/{2:C0} ({3:C0} per year) contract.",
                                             tst[curPlayer.TeamF].DisplayName, curPlayer.Contract.GetYearsDesc(),
                                             curPlayer.Contract.GetTotal(), curPlayer.Contract.GetAverage());
                        if (reSigned)
                        {
                            reSigningsList.Add(msg);
                        }
                        else
                        {
                            faSigningsList.Add(msg);
                        }
                    }

                    if (oldPlayer.Injury.InjuryName != curPlayer.Injury.InjuryName)
                    {
                        if (!oldPlayer.Injury.IsInjured)
                        {
                            injuredList.Add(name + " got injured. Status: " + curPlayer.Injury.Status);
                        }
                        else if (!curPlayer.Injury.IsInjured)
                        {
                            recoveredList.Add(name + " is no longer injured.");
                        }
                        else
                        {
                            reInjuredList.Add(name + " was injured with " + oldPlayer.Injury.InjuryName +
                                              ", is now injured again. Status: " + curPlayer.Injury.Status);
                        }
                    }

                    #endregion
                }
            }

            if (duplicatePlayers.Count > 0)
            {
                string msg =
                    "The following names belong to two or more players in the database and the tool couldn't determine who to import to:\n\n";
                duplicatePlayers.ForEach(item => msg += item + ", ");
                msg = msg.TrimEnd(new[] {' ', ','});
                msg += "\n\nImport will continue, but there will be some stats missing." + "\n\nTo avoid this problem, either\n" +
                       "1) disable the duplicate occurences via (Miscellaneous > Enable/Disable Players For This Season...), or\n" +
                       "2) transfer the correct instance of the player to their current team.";
                MessageBox.Show(msg);
            }

            #endregion

            #region Check for box-scores we can calculate

            if (oldTST.Count == 30)
            {
                TeamsThatPlayedAGame = new List<int>();
                foreach (var team in tst)
                {
                    TeamStats newTeam = team.Value;
                    int teamID = team.Key;
                    TeamStats oldTeam = oldTST[teamID];

                    if (oldTeam.GetGames() + 1 == newTeam.GetGames() || oldTeam.GetPlayoffGames() + 1 == newTeam.GetPlayoffGames())
                    {
                        TeamsThatPlayedAGame.Add(team.Key);
                    }
                }

                if (TeamsThatPlayedAGame.Count >= 2)
                {
                    PickedTeams = new List<int>();
                    var dlw = new PickGamesWindow(TeamsThatPlayedAGame);

                    if (dlw.ShowDialog() == true)
                    {
                        for (int i = 0; i <= PickedTeams.Count - 2; i += 2)
                        {
                            int t1 = PickedTeams[i];
                            int t2 = PickedTeams[i + 1];

                            BoxScoreEntry bse = prepareBoxScore(tst, oldTST, pst, oldPST, t1, t2);

                            TeamBoxScore teamBoxScore = bse.BS;
                            BoxScoreWindow.CalculateTeamsFromPlayers(ref teamBoxScore,
                                                                     bse.PBSList.Where(pbs => pbs.TeamID == bse.BS.Team1ID),
                                                                     bse.PBSList.Where(pbs => pbs.TeamID == bse.BS.Team2ID));

                            if (teamBoxScore.PTS1 != getDiff(tst, oldTST, t1, TAbbr.PF, teamBoxScore.IsPlayoff) ||
                                teamBoxScore.PTS2 != getDiff(tst, oldTST, t2, TAbbr.PF, teamBoxScore.IsPlayoff))
                            {
                                MessageBox.Show(
                                    String.Format(
                                        "{0} @ {1} won't have its box-score imported because it couldn't be properly calculated. A possible reason for this is that one or more players participating in that game has been since traded away from the teams.",
                                        tst[t1].DisplayName, tst[t2].DisplayName), "NBA Stats Tracker", MessageBoxButton.OK,
                                    MessageBoxImage.Exclamation);
                                continue;
                            }

                            bse.BS.GameDate = SelectedDate;
                            bse.Date = bse.BS.GameDate;
                            TeamStats.AddTeamStatsFromBoxScore(bse.BS, ref oldTST, ref oldtstOpp, t1, t2);
                            MainWindow.BSHist.Add(bse);
                            tst[t1] = oldTST[t1].Clone();
                            tst[t2] = oldTST[t2].Clone();
                            tstOpp[t1] = oldtstOpp[t1].Clone();
                            tstOpp[t2] = oldtstOpp[t2].Clone();
                        }
                    }
                }
            }

            #endregion

            if (tradesList.Count + faSigningsList.Count + reSigningsList.Count + waiversList.Count > 0)
            {
                importMessages.Add("League Transactions");
                importMessages.Add("========================================");
                importMessages.Add("");
                if (tradesList.Count > 0)
                {
                    importMessages.Add("Players traded");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(tradesList);
                    importMessages.Add("");
                }
                if (faSigningsList.Count > 0)
                {
                    importMessages.Add("Players signed from free-agency");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(faSigningsList);
                    importMessages.Add("");
                }
                if (reSigningsList.Count > 0)
                {
                    importMessages.Add("Players that signed an extension");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(reSigningsList);
                    importMessages.Add("");
                }
                if (waiversList.Count > 0)
                {
                    importMessages.Add("Players waived");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(waiversList);
                    importMessages.Add("");
                }
                importMessages.Add("");
                importMessages.Add("");
            }
            if (injuredList.Count + reInjuredList.Count + recoveredList.Count > 0)
            {
                importMessages.Add("Injury Updates");
                importMessages.Add("========================================");
                importMessages.Add("");
                if (injuredList.Count > 0)
                {
                    importMessages.Add("Players injured");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(injuredList);
                    importMessages.Add("");
                }
                if (reInjuredList.Count > 0)
                {
                    importMessages.Add("Players that got injured again after recovery");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(reInjuredList);
                    importMessages.Add("");
                }
                if (recoveredList.Count > 0)
                {
                    importMessages.Add("Players recovered");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(recoveredList);
                    importMessages.Add("");
                }
            }

            if (importMessages.Count > 0)
            {
                importMessages.Add("");
                var cmw = new CopyableMessageWindow(importMessages.Aggregate((m1, m2) => m1 + "\n" + m2), "League News",
                                                    TextAlignment.Left);
                cmw.ShowDialog();
            }

            return 0;
        }
 private void OnChangelogDownloadCompleted(object sender, AsyncCompletedEventArgs asyncCompletedEventArgs)
 {
     var lines = File.ReadAllLines(App.AppTempPath + "changelog.txt").ToList();
     lines.Add("");
     var result = "";
     lines.ForEach(line => result += line.Replace("\t", "  ") + "\n");
     var cmw = new CopyableMessageWindow(result, "NBA Stats Tracker - What's New");
     cmw.ShowDialog();
 }
Beispiel #5
0
        /// <summary>Imports all team (and optionally) player stats from an REDitor-exported set of CSV files.</summary>
        /// <param name="tst">The team stats dictionary.</param>
        /// <param name="tstOpp">The opposing team stats dictionary.</param>
        /// <param name="pst">The player stats dictionary.</param>
        /// <param name="folder">The folder containing the exported CSV files.</param>
        /// <param name="teamsOnly">
        ///     if set to <c>true</c>, only team stats will be imported.
        /// </param>
        /// <returns></returns>
        public static int ImportCurrentYear(
            ref Dictionary<int, TeamStats> tst,
            ref Dictionary<int, TeamStats> tstOpp,
            ref Dictionary<int, PlayerStats> pst,
            string folder,
            bool teamsOnly = false)
        {
            List<Dictionary<string, string>> teams;
            List<Dictionary<string, string>> players;
            List<Dictionary<string, string>> teamStats;
            List<Dictionary<string, string>> playerStats;

            NBA2KVersion nba2KVersion;
            if (populateREDitorDictionaryLists(folder, out teams, out players, out teamStats, out playerStats, out nba2KVersion) == -1)
            {
                return -1;
            }

            initializeLegalTeamTypes(nba2KVersion);

            var importMessages = new List<string>();
            var tradesList = new List<string>();
            var faSigningsList = new List<string>();
            var reSigningsList = new List<string>();
            var waiversList = new List<string>();
            var injuredList = new List<string>();
            var reInjuredList = new List<string>();
            var recoveredList = new List<string>();
            var newRecordsList = new List<string>();

            #region Import Teams & Team Stats

            var validTeams = teams.FindAll(
                delegate(Dictionary<string, string> team)
                    {
                        if (legalTTypes.IndexOf(team["TType"]) != -1)
                        {
                            return true;
                        }
                        return false;
                    });

            var activeTeams = validTeams.FindAll(
                delegate(Dictionary<string, string> team)
                    {
                        if (team["StatCurS"] != "-1")
                        {
                            return true;
                        }
                        return false;
                    }).ToList();
            if (activeTeams.Count < 30)
            {
                bool? dialogResult = null;
                Tools.AppInvoke(
                    () =>
                        {
                            var dlw = new DualListWindow(validTeams, activeTeams);
                            dialogResult = dlw.ShowDialog();
                        });
                if (dialogResult != true)
                {
                    return -1;
                }
                activeTeams = new List<Dictionary<string, string>>(MainWindow.SelectedTeams);

                if (MainWindow.SelectedTeamsChanged)
                {
                    createSettingsFile(activeTeams, folder);
                }
            }

            var madeNew = false;

            if (tst.Count != activeTeams.Count)
            {
                tst = new Dictionary<int, TeamStats>();
                tstOpp = new Dictionary<int, TeamStats>();
                madeNew = true;
            }

            var oldTST = tst.ToDictionary(ts => ts.Key, ts => ts.Value.BinarySerializationClone());
            var oldtstOpp = tstOpp.ToDictionary(ts => ts.Key, ts => ts.Value.BinarySerializationClone());
            var oldPST = pst.ToDictionary(ps => ps.Key, ps => ps.Value.BinarySerializationClone());

            CreateDivisions();

            var activeTeamsIDs = new List<int>();
            var rosters = new Dictionary<int, List<int>>();
            activeTeams.Sort((p1, p2) => Convert.ToInt32(p1["ID"]).CompareTo(Convert.ToInt32(p2["ID"])));
            foreach (var team in activeTeams)
            {
                var name = team["Name"];
                if (nba2KVersion != NBA2KVersion.NBA2K12)
                {
                    name += (team["Year"] == "0" ? "" : team["Year"].PadLeft(2, '0'));
                }
                var redID = Convert.ToInt32(team["ID"]);
                if (tst.Values.All(ts => ts.Name != name))
                {
                    if (tst.Keys.Contains(redID))
                    {
                        var oldName = tst[redID].Name;
                        tst[redID].Name = name;
                        tstOpp[redID].Name = name;
                        if (oldName == tst[redID].DisplayName)
                        {
                            tst[redID].DisplayName = name;
                            tstOpp[redID].DisplayName = name;
                        }
                    }
                    else
                    {
                        tst.Add(redID, new TeamStats(redID, name));
                        tstOpp.Add(redID, new TeamStats(redID, name));
                    }
                }
                var id = tst.Values.Single(ts => ts.Name == name).ID;
                activeTeamsIDs.Add(Convert.ToInt32(team["ID"]));

                if (madeNew)
                {
                    tst[id] = new TeamStats(id, name);
                    tstOpp[id] = new TeamStats(id, name);
                }

                var sStatsID = Convert.ToInt32(team["StatCurS"]);
                var pStatsID = Convert.ToInt32(team["StatCurP"]);

                var sStats = teamStats.Find(
                    delegate(Dictionary<string, string> s)
                        {
                            if (s["ID"] == sStatsID.ToString())
                            {
                                return true;
                            }
                            return false;
                        });

                tst[id].ID = id;
                tstOpp[id].ID = id;
                tst[id].Division = Convert.ToInt32(team["Division"]);
                tstOpp[id].Division = Convert.ToInt32(team["Division"]);

                if (sStats != null)
                {
                    tst[id].Record[0] = Convert.ToByte(sStats["Wins"]);
                    tst[id].Record[1] = Convert.ToByte(sStats["Losses"]);
                    tst[id].Totals[TAbbrT.MINS] = Convert.ToUInt16(sStats["Mins"]);
                    tst[id].Totals[TAbbrT.PF] = Convert.ToUInt16(sStats["PtsFor"]);
                    tst[id].Totals[TAbbrT.PA] = Convert.ToUInt16(sStats["PtsAg"]);
                    tst[id].Totals[TAbbrT.FGM] = Convert.ToUInt16(sStats["FGMade"]);
                    tst[id].Totals[TAbbrT.FGA] = Convert.ToUInt16(sStats["FGAtt"]);
                    try
                    {
                        tst[id].Totals[TAbbrT.TPM] = Convert.ToUInt16(sStats["3PTMade"]);
                        tst[id].Totals[TAbbrT.TPA] = Convert.ToUInt16(sStats["3PTAtt"]);
                    }
                    catch (KeyNotFoundException)
                    {
                        tst[id].Totals[TAbbrT.TPM] = Convert.ToUInt16(sStats["TPTMade"]);
                        tst[id].Totals[TAbbrT.TPA] = Convert.ToUInt16(sStats["TPTAtt"]);
                    }
                    tst[id].Totals[TAbbrT.FTM] = Convert.ToUInt16(sStats["FTMade"]);
                    tst[id].Totals[TAbbrT.FTA] = Convert.ToUInt16(sStats["FTAtt"]);
                    tst[id].Totals[TAbbrT.DREB] = Convert.ToUInt16(sStats["DRebs"]);
                    tst[id].Totals[TAbbrT.OREB] = Convert.ToUInt16(sStats["ORebs"]);
                    tst[id].Totals[TAbbrT.STL] = Convert.ToUInt16(sStats["Steals"]);
                    tst[id].Totals[TAbbrT.BLK] = Convert.ToUInt16(sStats["Blocks"]);
                    tst[id].Totals[TAbbrT.AST] = Convert.ToUInt16(sStats["Assists"]);
                    tst[id].Totals[TAbbrT.FOUL] = Convert.ToUInt16(sStats["Fouls"]);
                    tst[id].Totals[TAbbrT.TOS] = Convert.ToUInt16(sStats["TOs"]);

                    if (pStatsID != -1)
                    {
                        var pStats = teamStats.Single(s => s["ID"] == pStatsID.ToString());
                        tst[id].PlRecord[0] = Convert.ToByte(pStats["Wins"]);
                        tst[id].PlRecord[1] = Convert.ToByte(pStats["Losses"]);
                        tst[id].PlTotals[TAbbrT.MINS] = Convert.ToUInt16(pStats["Mins"]);
                        tst[id].PlTotals[TAbbrT.PF] = Convert.ToUInt16(pStats["PtsFor"]);
                        tst[id].PlTotals[TAbbrT.PA] = Convert.ToUInt16(pStats["PtsAg"]);
                        tst[id].PlTotals[TAbbrT.FGM] = Convert.ToUInt16(pStats["FGMade"]);
                        tst[id].PlTotals[TAbbrT.FGA] = Convert.ToUInt16(pStats["FGAtt"]);
                        try
                        {
                            tst[id].PlTotals[TAbbrT.TPM] = Convert.ToUInt16(sStats["3PTMade"]);
                            tst[id].PlTotals[TAbbrT.TPA] = Convert.ToUInt16(sStats["3PTAtt"]);
                        }
                        catch (KeyNotFoundException)
                        {
                            tst[id].PlTotals[TAbbrT.TPM] = Convert.ToUInt16(sStats["TPTMade"]);
                            tst[id].PlTotals[TAbbrT.TPA] = Convert.ToUInt16(sStats["TPTAtt"]);
                        }
                        tst[id].PlTotals[TAbbrT.FTM] = Convert.ToUInt16(pStats["FTMade"]);
                        tst[id].PlTotals[TAbbrT.FTA] = Convert.ToUInt16(pStats["FTAtt"]);
                        tst[id].PlTotals[TAbbrT.DREB] = Convert.ToUInt16(pStats["DRebs"]);
                        tst[id].PlTotals[TAbbrT.OREB] = Convert.ToUInt16(pStats["ORebs"]);
                        tst[id].PlTotals[TAbbrT.STL] = Convert.ToUInt16(pStats["Steals"]);
                        tst[id].PlTotals[TAbbrT.BLK] = Convert.ToUInt16(pStats["Blocks"]);
                        tst[id].PlTotals[TAbbrT.AST] = Convert.ToUInt16(pStats["Assists"]);
                        tst[id].PlTotals[TAbbrT.FOUL] = Convert.ToUInt16(pStats["Fouls"]);
                        tst[id].PlTotals[TAbbrT.TOS] = Convert.ToUInt16(pStats["TOs"]);
                    }
                }

                tst[id].CalcAvg();

                rosters[id] = new List<int>
                    {
                        Convert.ToInt32(team["Ros_PG"]),
                        Convert.ToInt32(team["Ros_SG"]),
                        Convert.ToInt32(team["Ros_SF"]),
                        Convert.ToInt32(team["Ros_PF"]),
                        Convert.ToInt32(team["Ros_C"])
                    };
                for (var i = 6; i <= 12; i++)
                {
                    var cur = Convert.ToInt32(team["Ros_S" + i.ToString()]);
                    if (cur != -1)
                    {
                        rosters[id].Add(cur);
                    }
                    else
                    {
                        break;
                    }
                }
                for (var i = 13; i <= 20; i++)
                {
                    var cur = Convert.ToInt32(team["Ros_R" + i.ToString()]);
                    if (cur != -1)
                    {
                        rosters[id].Add(cur);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            #endregion

            #region Import Players & Player Stats

            var duplicatePlayers = new List<string>();
            if (!teamsOnly)
            {
                var validPlayers = players.FindAll(player => isValidPlayer(player, nba2KVersion));

                foreach (var player in validPlayers)
                {
                    var playerID = Convert.ToInt32(player["ID"]);

                    var lastName = player["Last_Name"];
                    var firstName = player["First_Name"];

                    int pTeam;
                    var curTeam = new TeamStats();
                    try
                    {
                        pTeam = rosters.Single(r => r.Value.Contains(playerID)).Key;
                        curTeam = tst[pTeam];
                    }
                    catch (InvalidOperationException)
                    {
                        pTeam = -1;
                    }

                    if (pTeam == -1 && player["IsFA"] != "1")
                    {
                        if (pst.ContainsKey(playerID) && pst[playerID].LastName == lastName && pst[playerID].FirstName == firstName)
                        {
                            pst[playerID].IsSigned = false;
                            pst[playerID].TeamF = -1;
                            pst[playerID].IsHidden = true;
                        }
                        continue;
                    }

                    var playerStatsID = Convert.ToInt32(player["StatY0"]);

                    Dictionary<string, string> playerSeasonStats;
                    try
                    {
                        playerSeasonStats = playerStats.Single(s => s["ID"] == playerStatsID.ToString());
                    }
                    catch
                    {
                        playerSeasonStats = null;
                    }

                    Dictionary<string, string> playerPlayoffStats = null;
                    if (nba2KVersion >= NBA2KVersion.NBA2K13)
                    {
                        var playerPlayoffStatsID = player["StatPOs"];
                        try
                        {
                            playerPlayoffStats = playerStats.Find(s => s["ID"] == playerPlayoffStatsID);
                        }
                        catch
                        {
                            playerPlayoffStats = null;
                        }
                    }

                    #region Match Player

                    if (pst.ContainsKey(playerID) && (pst[playerID].LastName != lastName || pst[playerID].FirstName != firstName))
                    {
                        var candidates =
                            pst.Where(
                                pair =>
                                pair.Value.LastName == lastName && pair.Value.FirstName == firstName && pair.Value.IsHidden == false)
                               .ToList();
                        if (candidates.Count > 0)
                        {
                            var found = false;
                            var temptst = tst;
                            var c2 = candidates.Where(pair => temptst.ContainsKey(pair.Value.TeamF)).ToList();
                            if (c2.Count() == 1)
                            {
                                playerID = c2.First().Value.ID;
                                found = true;
                            }
                            else
                            {
                                var c4 = candidates.Where(pair => pair.Value.YearOfBirth.ToString() == player["BirthYear"]).ToList();
                                if (c4.Count == 1)
                                {
                                    playerID = c4.First().Value.ID;
                                    found = true;
                                }
                                else
                                {
                                    if (pTeam != -1)
                                    {
                                        var c3 = candidates.Where(pair => pair.Value.TeamF == curTeam.ID).ToList();
                                        if (c3.Count == 1)
                                        {
                                            playerID = c3.First().Value.ID;
                                            found = true;
                                        }
                                    }
                                }
                            }
                            if (!found)
                            {
                                var choices = new List<string>();
                                foreach (var pair in candidates)
                                {
                                    var choice = String.Format(
                                        "{0}: {1} {2} (Born {3}",
                                        pair.Value.ID,
                                        pair.Value.FirstName,
                                        pair.Value.LastName,
                                        pair.Value.YearOfBirth);
                                    if (pair.Value.IsSigned)
                                    {
                                        choice += String.Format(", plays in {0}", tst[pair.Value.TeamF].DisplayName);
                                    }
                                    else
                                    {
                                        choice += ", free agent";
                                    }
                                    choice += ")";
                                    choices.Add(choice);
                                }
                                var message = String.Format(
                                    "{0}: {1} {2} (Born {3}",
                                    player["ID"],
                                    player["First_Name"],
                                    player["Last_Name"],
                                    player["BirthYear"]);
                                if (pTeam != -1)
                                {
                                    message += String.Format(", plays in {0}", curTeam.DisplayName);
                                }
                                else
                                {
                                    message += ", free agent";
                                }
                                message += ")";
                                var ccw = new ComboChoiceWindow(message, choices);
                                if (ccw.ShowDialog() != true)
                                {
                                    duplicatePlayers.Add(firstName + " " + lastName);
                                    continue;
                                }
                                else
                                {
                                    playerID = Convert.ToInt32(ComboChoiceWindow.UserChoice.Split(':')[0]);
                                }
                            }
                        }
                        else
                        {
                            playerID = createNewPlayer(ref pst, player);
                        }
                    }
                    else if (!pst.ContainsKey(playerID))
                    {
                        playerID = createNewPlayer(ref pst, player, playerID);
                    }

                    #endregion Match Player

                    var curPlayer = pst[playerID];
                    var oldPlayer = curPlayer.BinarySerializationClone();

                    curPlayer.Position1 = (Position) Enum.Parse(typeof(Position), player["Pos"]);
                    curPlayer.Position2 = (Position) Enum.Parse(typeof(Position), player["SecondPos"]);
                    curPlayer.IsHidden = false;
                    curPlayer.YearsPro = Convert.ToInt32(player["YearsPro"]);
                    curPlayer.YearOfBirth = Convert.ToInt32(player["BirthYear"]);
                    curPlayer.Contract.Option = (PlayerContractOption) Enum.Parse(typeof(PlayerContractOption), player["COption"]);
                    curPlayer.Contract.ContractSalaryPerYear.Clear();
                    for (var i = 1; i < 7; i++)
                    {
                        var salary = Convert.ToInt32(player["CYear" + i]);
                        if (salary == 0)
                        {
                            break;
                        }

                        curPlayer.Contract.ContractSalaryPerYear.Add(salary);
                    }
                    curPlayer.Height = Convert.ToDouble(player["Height"]);
                    curPlayer.Weight = Convert.ToDouble(player["Weight"]);
                    curPlayer.Injury = new PlayerInjury(Convert.ToInt32(player["InjType"]), Convert.ToInt32(player["InjDaysLeft"]));

                    if (playerSeasonStats != null)
                    {
                        var teamReal = pTeam.ToString();
                        var team2 = playerSeasonStats["TeamID1"];
                        //bool hasBeenTraded = (team1 != "-1");

                        curPlayer.TeamF = pTeam;
                        curPlayer.TeamS = Convert.ToInt32(team2);

                        curPlayer.IsSigned = (player["IsFA"] != "1" && teamReal != "-1");

                        importPlayerStats(curPlayer, playerSeasonStats, nba2KVersion, false);

                        curPlayer.CalcAvg();

                        pst[playerID] = curPlayer;
                    }
                    else
                    {
                        curPlayer.TeamF = pTeam;

                        curPlayer.IsSigned = player["IsFA"] != "1";

                        curPlayer.CalcAvg();
                    }

                    if (playerPlayoffStats != null)
                    {
                        importPlayerStats(curPlayer, playerPlayoffStats, nba2KVersion, true);

                        curPlayer.CalcAvg();
                    }

                    if (nba2KVersion >= NBA2KVersion.NBA2K13)
                    {
                        importPlayerCareerHighs(curPlayer, player);
                    }

                    #region Import Messsages

                    var name = String.Format("{0} {1}", curPlayer.FirstName, curPlayer.LastName);
                    if (oldPlayer.TeamF != curPlayer.TeamF)
                    {
                        string msg;
                        if (curPlayer.IsSigned && oldPlayer.IsSigned)
                        {
                            msg = String.Format(
                                "{0} was traded from the {1} to the {2}.",
                                name,
                                tst[oldPlayer.TeamF].DisplayName,
                                tst[curPlayer.TeamF].DisplayName);
                            tradesList.Add(msg);
                        }
                        else if (oldPlayer.IsSigned)
                        {
                            msg = String.Format("{0} was released from the {1}.", name, tst[oldPlayer.TeamF].DisplayName);
                            waiversList.Add(msg);
                        }
                    }

                    if (oldPlayer.Contract.GetYears() < curPlayer.Contract.GetYears() && curPlayer.IsSigned)
                    {
                        var msg = name;
                        bool reSigned;
                        if (!oldPlayer.IsSigned && curPlayer.IsSigned)
                        {
                            reSigned = false;
                            msg += " signed ";
                        }
                        else
                        {
                            reSigned = true;
                            msg += " re-signed ";
                        }
                        msg += String.Format(
                            "with the {0} on a {1}/{2:C0} ({3:C0} per year) contract.",
                            tst[curPlayer.TeamF].DisplayName,
                            curPlayer.Contract.GetYearsDesc(),
                            curPlayer.Contract.GetTotal(),
                            curPlayer.Contract.GetAverage());
                        if (reSigned)
                        {
                            reSigningsList.Add(msg);
                        }
                        else
                        {
                            faSigningsList.Add(msg);
                        }
                    }

                    if (oldPlayer.Injury.InjuryName != curPlayer.Injury.InjuryName)
                    {
                        if (!oldPlayer.Injury.IsInjured)
                        {
                            injuredList.Add(
                                string.Format(
                                    "{0} ({1}) got injured. Status: {2}",
                                    name,
                                    curPlayer.TeamF != -1 ? tst[curPlayer.TeamF].DisplayName : "Free Agent",
                                    curPlayer.Injury.Status));
                        }
                        else if (!curPlayer.Injury.IsInjured)
                        {
                            recoveredList.Add(
                                string.Format(
                                    "{1} ({0}) is no longer injured.",
                                    curPlayer.TeamF != -1 ? tst[curPlayer.TeamF].DisplayName : "Free Agent",
                                    name));
                        }
                        else
                        {
                            reInjuredList.Add(
                                string.Format(
                                    "{0} ({3}) was being reported as having {1}, is now reported as: {2}",
                                    name,
                                    oldPlayer.Injury.InjuryName,
                                    curPlayer.Injury.Status,
                                    curPlayer.TeamF != -1 ? tst[curPlayer.TeamF].DisplayName : "Free Agent"));
                        }
                    }

                    var count = 0;
                    var recMsg = "";
                    for (var i = 0; i < curPlayer.CareerHighs.Count(); i++)
                    {
                        if (i == PAbbrT.MINS || i == PAbbrT.TOS || i == PAbbrT.FOUL)
                        {
                            continue;
                        }
                        if (oldPlayer.CareerHighs[i] != 0 && oldPlayer.CareerHighs[i] < curPlayer.CareerHighs[i])
                        {
                            if (count == 0)
                            {
                                recMsg = string.Format(
                                    "{0} has a new career-high in {1} ({2})",
                                    curPlayer.FullInfo(tst, true, false),
                                    PlayerStatsHelper.CHTotals[i],
                                    curPlayer.CareerHighs[i]);
                            }
                            else
                            {
                                recMsg += string.Format(", {0} ({1})", PlayerStatsHelper.CHTotals[i], curPlayer.CareerHighs[i]);
                            }
                            count++;
                        }
                    }
                    recMsg += ".";
                    if (count > 0)
                    {
                        newRecordsList.Add(recMsg);
                    }

                    #endregion
                }
            }

            if (duplicatePlayers.Count > 0)
            {
                var msg =
                    "The following names belong to two or more players in the database and the tool couldn't determine who to import to:\n\n";
                duplicatePlayers.ForEach(item => msg += item + ", ");
                msg = msg.TrimEnd(new[] { ' ', ',' });
                msg += "\n\nImport will continue, but there will be some stats missing." + "\n\nTo avoid this problem, either\n"
                       + "1) disable the duplicate occurences via (Miscellaneous > Enable/Disable Players For This Season...), or\n"
                       + "2) transfer the correct instance of the player to their current team.";
                Tools.AppInvoke(() => MessageBox.Show(msg));
            }

            #endregion

            #region Check for box-scores we can calculate

            if (oldTST.Count == 30)
            {
                TeamsThatPlayedAGame = new List<int>();
                foreach (var team in tst)
                {
                    var newTeam = team.Value;
                    var teamID = team.Key;
                    var oldTeam = oldTST[teamID];

                    if (oldTeam.GetGames() + 1 == newTeam.GetGames() || oldTeam.GetPlayoffGames() + 1 == newTeam.GetPlayoffGames())
                    {
                        TeamsThatPlayedAGame.Add(team.Key);
                    }
                }

                if (TeamsThatPlayedAGame.Count >= 2)
                {
                    bool? result = null;

                    PickedTeams = new List<int>();
                    Tools.AppInvoke(
                        () =>
                            {
                                var dlw = new PickGamesWindow(TeamsThatPlayedAGame);
                                result = dlw.ShowDialog();
                            });

                    if (result == true)
                    {
                        for (var i = 0; i <= PickedTeams.Count - 2; i += 2)
                        {
                            var t1 = PickedTeams[i];
                            var t2 = PickedTeams[i + 1];

                            var bse = prepareBoxScore(tst, oldTST, pst, oldPST, t1, t2);

                            var teamBoxScore = bse.BS;
                            BoxScoreWindow.CalculateTeamsFromPlayers(
                                ref teamBoxScore,
                                bse.PBSList.Where(pbs => pbs.TeamID == bse.BS.Team1ID),
                                bse.PBSList.Where(pbs => pbs.TeamID == bse.BS.Team2ID));

                            if (teamBoxScore.PTS1 != getDiff(tst, oldTST, t1, TAbbrT.PF, teamBoxScore.IsPlayoff)
                                || teamBoxScore.PTS2 != getDiff(tst, oldTST, t2, TAbbrT.PF, teamBoxScore.IsPlayoff))
                            {
                                var localtst = tst;
                                Tools.AppInvoke(
                                    () =>
                                    MessageBox.Show(
                                        String.Format(
                                            "{0} @ {1} won't have its box-score imported because it couldn't be properly calculated. A possible reason for this is that one or more players participating in that game has been since traded away from the teams.",
                                            localtst[t1].DisplayName,
                                            localtst[t2].DisplayName),
                                        "NBA Stats Tracker",
                                        MessageBoxButton.OK,
                                        MessageBoxImage.Exclamation));
                                continue;
                            }

                            bse.BS.GameDate = SelectedDate;
                            TeamStats.AddTeamStatsFromBoxScore(bse.BS, ref oldTST, ref oldtstOpp, t1, t2);
                            MainWindow.BSHist.Add(bse);
                            tst[t1] = oldTST[t1].BinarySerializationClone();
                            tst[t2] = oldTST[t2].BinarySerializationClone();
                            tstOpp[t1] = oldtstOpp[t1].BinarySerializationClone();
                            tstOpp[t2] = oldtstOpp[t2].BinarySerializationClone();
                        }
                    }
                }
            }

            #endregion

            if (tradesList.Count + faSigningsList.Count + reSigningsList.Count + waiversList.Count > 0)
            {
                importMessages.Add("League Transactions");
                importMessages.Add("========================================");
                importMessages.Add("");
                if (tradesList.Count > 0)
                {
                    importMessages.Add("Players traded");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(tradesList);
                    importMessages.Add("");
                }
                if (faSigningsList.Count > 0)
                {
                    importMessages.Add("Players signed from free-agency");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(faSigningsList);
                    importMessages.Add("");
                }
                if (reSigningsList.Count > 0)
                {
                    importMessages.Add("Players that signed an extension");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(reSigningsList);
                    importMessages.Add("");
                }
                if (waiversList.Count > 0)
                {
                    importMessages.Add("Players waived");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(waiversList);
                    importMessages.Add("");
                }
                importMessages.Add("");
                importMessages.Add("");
            }
            if (injuredList.Count + reInjuredList.Count + recoveredList.Count > 0)
            {
                importMessages.Add("Injury Updates");
                importMessages.Add("========================================");
                importMessages.Add("");
                if (injuredList.Count > 0)
                {
                    importMessages.Add("Players injured");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(injuredList);
                    importMessages.Add("");
                }
                if (reInjuredList.Count > 0)
                {
                    importMessages.Add("Players whose injury status changed");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(reInjuredList);
                    importMessages.Add("");
                }
                if (recoveredList.Count > 0)
                {
                    importMessages.Add("Players recovered");
                    importMessages.Add("=========================");
                    importMessages.Add("");
                    importMessages.AddRange(recoveredList);
                    importMessages.Add("");
                }
                importMessages.Add("");
                importMessages.Add("");
            }
            if (newRecordsList.Count > 0)
            {
                importMessages.Add("New Career Highs");
                importMessages.Add("========================================");
                importMessages.Add("");
                importMessages.AddRange(newRecordsList);
                importMessages.Add("");
            }

            if (importMessages.Count > 0)
            {
                importMessages.Add("");
                Tools.AppInvoke(
                    () =>
                        {
                            var cmw = new CopyableMessageWindow(importMessages.Aggregate((m1, m2) => m1 + "\n" + m2), "League News");
                            cmw.ShowDialog();
                        });
            }

            return 0;
        }