/// <summary>
        /// Parses and verifies the card count of the deck filename.  The filename must match
        /// those found in /DeckFiles/
        /// </summary>
        /// <param name="deckFileName">The filename of the deck to verify</param>
        /// <param name="scratchDirectory">The directory to create the deck file in</param>
        /// <param name="game">The Game that should be chosen in the Wizard</param>
        public static void VerifyDeckFile(
            string deckFileName, 
            IEnumerable<ExpectedDeckSection> expectedSectionsStats,
            string scratchDirectory, 
            Octgn.DataNew.Entities.Game game)
        {
            Assert.IsTrue(DeckFileResourceHelpers.CopyDeckFileResourceToDirectory(
                scratchDirectory,
                deckFileName));

            ConverterDeck converterDeck = ConvertDeckFileUsingWizard(Path.Combine(scratchDirectory, deckFileName), game);

            foreach (ConverterSection converterSection in converterDeck.ConverterSections)
            {
                ExpectedDeckSection expectedSectionStats = 
                    expectedSectionsStats.First(eds => eds.SectionName == converterSection.SectionName);

                Assert.AreEqual(expectedSectionStats.TotalCardCount, converterSection.SectionCount);
                Assert.AreEqual(expectedSectionStats.UniqueCardCount, converterSection.SectionMappings.Count(sm => sm.PotentialOCTGNCards.Count > 0));

                foreach (ConverterMapping converterMapping in converterSection.SectionMappings)
                {
                    // At least one potential match should have been found
                    Assert.IsTrue(converterMapping.PotentialOCTGNCards.Count() > 0);
                }
            }
        }
示例#2
0
 public void installSet(Windows.UpdateChecker wnd, Octgn.Data.Game game)
 {
     wnd.UpdateStatus("Retrieving xml...");
     XmlSetParser xmls = xml_set;
     wnd.UpdateStatus("Parsing retrieved xml...");
     xmls.check();
     bool is_spoiler_installed = true;
     Data.Set set = null;
     string path = Path.Combine(Prefs.DataDirectory, "Games", game.Id.ToString(), "Sets");
     string downloadto = Path.Combine(path) + xmls.name() + ".o8s";
     var cli = new WebClient();
     wnd.UpdateStatus("Downloading new definition...");
     if (xmls.user() != null && xmls.user() != "")
         cli.Credentials = new System.Net.NetworkCredential(xmls.user(), xmls.password());
     cli.DownloadFile(xmls.link(), downloadto);
     wnd.UpdateStatus( "Checking for existence of old definition...");
     try
     {
         set = game.Sets.First<Data.Set>(_set => _set.Id.ToString() == xmls.uuid());
     }
     catch
     {
         is_spoiler_installed = false;
     }
     if (is_spoiler_installed)
     {
         wnd.UpdateStatus("Removing old definition...");
         game.DeleteSet(set);
     }
     wnd.UpdateStatus("Installing new definition...");
     game.InstallSet(downloadto);
     wnd.UpdateStatus("Set installed correctly");
 }
        /// <summary>
        /// The database of all OCTGN card Name, Guid, Set, and MultiverseID info needs to be read in.
        /// It only needs to be done once, which is why this is a Singleton.  
        /// When Initialize is called, the database is read from the Controller on a worker thread so 
        /// the user can immediately begin entering their deck info.
        /// </summary>
        /// <param name="mtgGame">The OCTGN Game to be used to build cards from.  It must be MTG.</param>
        public void Initialize(Octgn.DataNew.Entities.Game mtgGame)
        {
            if (mtgGame == null)
            {
                throw new ArgumentNullException();
            }

            this.GameDefinition = mtgGame;

            if (this.GameDefinition != null)
            {
                this._BuildCardDatabaseTask = new Task(() =>
                {
                    this.Sets = ConverterDatabase.BuildCardDatabase(this.GameDefinition);
                    this.IsInitialized = true;
                });

                // Continue with this if building the database threw an unexpected exception
                this._BuildCardDatabaseTask.ContinueWith
                (
                    (t) =>
                    {
                        this.BuildCardDatabaseExceptions = t.Exception;
                    },
                    System.Threading.Tasks.TaskContinuationOptions.OnlyOnFaulted
                );

                this._BuildCardDatabaseTask.Start();
            }
        }
 /// <summary>
 /// Initializes a new instance of the ConverterSet class.
 /// It represents a Set from Octgn, and provides a list of ConverterCards which are
 /// found in the Set.
 /// </summary>
 /// <param name="octgnSet">The Octgn Set</param>
 public ConverterSet(Octgn.DataNew.Entities.Set octgnSet)
 {
     if (octgnSet == null) 
     {
         throw new ArgumentNullException(); 
     }
     this.OctgnSet = octgnSet;
     this.IncludeInSearches = true;
 }
示例#5
0
 public void CheckXml(Octgn.Data.Game game)
 {
     XmlSetParser xmls = xml_set;
     if (game.Id.ToString() != xmls.game())
     {
         throw new Exception("Error! Wrong game specified in xml");
     }
     xmls.check();
 }
        /// <summary>
        /// Gets the ConverterGame corresponding to the specified OCTGN Game.  It will be created if it doesn't exist
        /// </summary>
        /// <param name="octgnGame">The corresponding OCTGN game to get the ConverterGame for</param>
        /// <returns>The corresponding ConverterGame</returns>
        public ConverterGame GetConverterGame(Octgn.DataNew.Entities.Game octgnGame)
        {
            if (this._ConverterGameDictionary[octgnGame] == null)
            {
                this._ConverterGameDictionary[octgnGame] = new ConverterGame(octgnGame);
            }

            return this._ConverterGameDictionary[octgnGame];
        }
        /// <summary>
        /// Initializes a new instance of the ConverterGame class.
        /// </summary>
        /// <param name="game">The OCTGN game definition to use for conversion</param>
        public ConverterGame(Octgn.DataNew.Entities.Game game)
        {
            if (game == null)
            {
                throw new ArgumentNullException("game");
            }

            this.Game = game;
            this.Initialize();
        }
示例#8
0
 public void CheckXml(Windows.ChangeSetsProgressDialog wnd, int max, Octgn.Data.Game game)
 {
     XmlSetParser xmls = xml_set;
     if (game.Id.ToString() != xmls.game())
     {
         wnd.UpdateProgress(max, max, string.Format("Error! Wrong game specified in xml"), false);
         return;
     }
     xmls.check();
 }
示例#9
0
 public void CheckVerboseXml(Windows.ChangeSetsProgressDialog wnd, int max, Octgn.Data.Game game)
 {
     XmlSetParser xmls = xml_set;
     wnd.UpdateProgress(1, max, "Parsing retrieved xml...", false);
     xmls.check();
     if (game.Id.ToString() != xmls.game())
     {
         wnd.UpdateProgress(10, 10, string.Format("Error! Wrong game specified in xml"), false);
         return;
     }
     wnd.UpdateProgress(2, max, "Name: " + xmls.name(), false);
     wnd.UpdateProgress(3, max, "Game: " + xmls.game(), false);
     wnd.UpdateProgress(4, max, "UUID: " + xmls.uuid(), false);
     wnd.UpdateProgress(5, max, "Version: " + xmls.version(), false);
     wnd.UpdateProgress(6, max, "Date: " + xmls.date(), false);
     wnd.UpdateProgress(7, max, "Link: " + xmls.link(), false);
     wnd.UpdateProgress(8, max, "Login: "******"Password: "******"Xml seems ok"), false);
 }
示例#10
0
 private void ChangeGamePath(Octgn.Data.Game game, String path)
 {
     String opath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Octgn");
     String masterDbPath = Path.Combine(opath, "master.vdb3"); ;
     using(var dda = VistaDBEngine.Connections.OpenDDA())
     using(var masterDb = dda.OpenDatabase(masterDbPath, VistaDBDatabaseOpenMode.NonexclusiveReadWrite, null))
     using(var gamesTable = masterDb.OpenTable("Game", false, false))
     {
         masterDb.BeginTransaction();
         bool previousCompatibleVersion = false;
         try
         {
             if(gamesTable.Find("id:'" + game.Id.ToString() + "'", "GamePK", false, false))
                 gamesTable.PutString("filename", path);
             gamesTable.Post();
             masterDb.CommitTransaction();
         }
         catch
         {
             masterDb.RollbackTransaction();
             throw;
         }
     }
 }
示例#11
0
文件: Client.cs 项目: TriAdX/OCTGN
 /// <summary>
 /// The begin host game.
 /// </summary>
 /// <param name="game">
 /// The game.
 /// </param>
 /// <param name="gamename">
 /// The gamename.
 /// </param>
 public void BeginHostGame(Octgn.DataNew.Entities.Game game, string gamename)
 {
     string data = string.Format("{0},:,{1},:,{2}", game.Id.ToString(), game.Version, gamename);
     Log.InfoFormat("BeginHostGame {0}",data);
     var m = new Message(new Jid("gameserv@" + Host), this.Me.JidUser, MessageType.normal, data, "hostgame");
     m.GenerateId();
     this.xmpp.Send(m);
     //m = new Message(new Jid("gameserv2@" + Host), this.Me.JidUser, MessageType.normal, data, "hostgame");
     //m.GenerateId();
     //this.xmpp.Send(m);
 }
示例#12
0
 public SetList(Octgn.Data.Game selectedGame)
 {
     InitializeComponent();
     SelectedGame = selectedGame;
 }
示例#13
0
 /// <summary>
 /// Start hosting a game.
 /// </summary>
 /// <param name="callback">Callback for when the server talks back</param>
 /// <param name="game">Game</param>
 /// <param name="gamename">Name of the game</param>
 /// <param name="password">Password</param>
 public void BeginHostGame(SocketMessageResult callback, Octgn.Data.Game game, string gamename, string password)
 {
     Callbacks.Clear();
     Callbacks.Add("hostgameresponse",callback);
     SocketMessage sm = new SocketMessage("hostgame");
     sm.AddData("game",game.Id);
     sm.AddData("version",game.Version);
     sm.AddData("name",gamename);
     sm.AddData("pass",password);
     WriteMessage(sm);
 }
        /// <summary>
        /// Returns an Image of the Octgn Card with corresponding Guid.  If there is an error (including if the Card Guid is not found)
        /// then the default back of the card is returned.
        /// </summary>
        /// <param name="cardID">The Guid of the Card to get a Bitmap picture of</param>
        /// <param name="game">The OCTGN game to find the Card from</param>
        /// <returns>The BitmapImage of the Octgn Card with corresponding Guid</returns>
        public static BitmapImage GetCardBitmapImage(Guid cardID, Octgn.DataNew.Entities.Game game)
        {
            var bim = new BitmapImage();
            bim.BeginInit();
            bim.CacheOption = BitmapCacheOption.OnLoad;

            try
            {
                Octgn.DataNew.Entities.Card octgnCard = game.AllCards().First(c => c.Id == cardID);
                bim.UriSource = new Uri(octgnCard.GetPicture());
                bim.EndInit();
            }
            catch (Exception)
            {
                bim = new BitmapImage();
                bim.CacheOption = BitmapCacheOption.OnLoad;
                bim.BeginInit();
                bim.UriSource = new Uri(game.CardFront);
                bim.EndInit();
            }

            return bim;
        }
示例#15
0
 public HostGameSettings(Octgn.Data.Game game)
 {
     InitializeComponent();
     Game = game;
 }
示例#16
0
        void SaveSettingsTask(
            ref string dataDirectory,
            bool useLightChat,
            bool useHardwareRendering,
            bool useTransparentWindows,
            bool ignoreSSLCertificates,
            int maxChatHistory,
            bool enableChatImages,
            bool enableWhisperSound,
            bool enableNameSound,
            string windowSkin,
            bool tileWindowSkin,
            bool useWindowsForChat,
            int chatFontSize,
            bool useInstantSearch,
            bool enableGameSounds,
            Octgn.Prefs.ZoomType zoomOption)
        {
            this.ValidateFields(
                ref dataDirectory,
                useLightChat,
                useHardwareRendering,
                useTransparentWindows,
                ignoreSSLCertificates,
                maxChatHistory,
                enableChatImages,
                enableWhisperSound,
                enableNameSound,
                windowSkin,
                tileWindowSkin,
                useWindowsForChat,
                chatFontSize,
                useInstantSearch,
                enableGameSounds
                );

            Prefs.DataDirectory = dataDirectory;
            Prefs.UseLightChat = useLightChat;
            Prefs.UseHardwareRendering = useHardwareRendering;
            Prefs.UseWindowTransparency = useTransparentWindows;
            Prefs.IgnoreSSLCertificates = ignoreSSLCertificates;
            Prefs.MaxChatHistory = maxChatHistory;
            Prefs.EnableChatImages = enableChatImages;
            Prefs.EnableWhisperSound = enableWhisperSound;
            Prefs.EnableNameSound = enableNameSound;
            Prefs.WindowSkin = windowSkin;
            Prefs.TileWindowSkin = tileWindowSkin;
            Prefs.UseWindowsForChat = useWindowsForChat;
            Prefs.ChatFontSize = chatFontSize;
            Prefs.InstantSearch = useInstantSearch;
            Prefs.EnableGameSound = enableGameSounds;
            Prefs.ZoomOption = zoomOption;
            //Prefs.EnableChatGifs = enableChatGifs;
        }
示例#17
0
 /// <summary>
 /// The begin host game.
 /// </summary>
 /// <param name="game">
 /// The game.
 /// </param>
 /// <param name="gamename">
 /// The gamename.
 /// </param>
 public void BeginHostGame(Octgn.DataNew.Entities.Game game, string gamename,
     string password, string actualgamename, string gameIconUrl, Version sasVersion, bool specators)
 {
     var hgr = new HostGameRequest(game.Id, game.Version, gamename, actualgamename, gameIconUrl, password ?? "", sasVersion, specators);
     //string data = string.Format("{0},:,{1},:,{2},:,{3},:,{4}", game.Id.ToString(), game.Version, gamename, password ?? "",actualgamename);
     Log.InfoFormat("BeginHostGame {0}", hgr);
     var m = new Message(this.Config.GameBotUser.JidUser, this.Me.JidUser, MessageType.normal, "", "hostgame");
     m.GenerateId();
     m.AddChild(hgr);
     this.xmpp.Send(m);
 }
示例#18
0
文件: Client.cs 项目: haslo/OCTGN
 /// <summary>
 /// The begin host game.
 /// </summary>
 /// <param name="game">
 /// The game.
 /// </param>
 /// <param name="gamename">
 /// The gamename.
 /// </param>
 public void BeginHostGame(Octgn.DataNew.Entities.Game game, string gamename, string password)
 {
     string data = string.Format("{0},:,{1},:,{2},:,{3}", game.Id.ToString(), game.Version, gamename, password ?? "");
     Log.InfoFormat("BeginHostGame {0}", data);
     var m = new Message(this.Config.GameBotUser.JidUser, this.Me.JidUser, MessageType.normal, data, "hostgame");
     m.GenerateId();
     this.xmpp.Send(m);
 }
示例#19
0
        void LClient_eLobbyChat(Octgn.Networking.LobbyClient.LobbyChatTypes type,string user, string chat)
        {
            System.Threading.Thread thread = new System.Threading.Thread
            (
                new System.Threading.ThreadStart
                (
                    delegate()
                    {
                        rtbChat.Dispatcher.Invoke
                        (
                            System.Windows.Threading.DispatcherPriority.Normal,
                            new Action
                            (
                                delegate()
                                {
                                    if (rtbChat == null)
                                        return;
                                    switch (type)
                                    {
                                        case Networking.LobbyClient.LobbyChatTypes.Global:
                                            rtbChat.AppendText("[" + user + "]: " + chat + "\n");
                                        break;
                                        case Networking.LobbyClient.LobbyChatTypes.System:
                                            rtbChat.AppendText("#" + user + ": " + chat + "\n");
                                        break;
                                        case Networking.LobbyClient.LobbyChatTypes.Whisper:
                                            String[] w = user.Split(new char[1] { ':' });
                                            rtbChat.AppendText("<" + w[0] + ">" +  w[1] + ": " + chat + "\n");
                                        break;
                                        case Networking.LobbyClient.LobbyChatTypes.Error:
                                            rtbChat.AppendText("!" + user + ": " + chat + "\n");
                                        break;
                                    }
                                    UpdateColors();
                                }
                            )
                        );
                    }
                )
            );

            thread.Start();
        }
示例#20
0
        private void DeleteGame(Octgn.Data.Game game)
        {
            String opath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Octgn");
            String masterDbPath = Path.Combine(opath, "master.vdb3"); ;
            using(var dda = VistaDBEngine.Connections.OpenDDA())
            using(var masterDb = dda.OpenDatabase(masterDbPath, VistaDBDatabaseOpenMode.NonexclusiveReadWrite, null))
            using(var gamesTable = masterDb.OpenTable("Game", false, false))
            {
                masterDb.BeginTransaction();
                try
                {
                    if(gamesTable.Find("id:'" + game.Id.ToString() + "'", "GamePK", false, false))
                    {
                        gamesTable.Unlock(gamesTable.CurrentRow.RowId);
                        gamesTable.Delete();

                        foreach(Set s in game.Sets)
                        {
                            game.DeleteSet(s);
                        }
                    }
                }
                catch(VistaDBException e)
                {
                    String s = e.StackTrace;
                    MessageBox.Show(s);
                    masterDb.RollbackTransaction();
                }
            }
        }
        /// <summary>
        /// Converts a URL into a ConverterDeck, then returns it
        /// </summary>
        /// <param name="deckURL">The URL of the deck to get</param>
        /// <param name="game">The Game that should be chosen in the Wizard</param>
        /// <returns>a ConverterDeck containing cards parsed from the deck file</returns>
        public static OCTGNDeckConverter.Model.ConverterDeck ConvertURLUsingWizard(
            string deckURL,
            Octgn.DataNew.Entities.Game game)
        {
            ImportDeckWizardVM idwvm = new ImportDeckWizardVM();

            // If more than one Game is installed, the ChooseGame page will be active.  Select the game
            if (idwvm.CurrentWizardPageVM is WizardPage_ChooseGame)
            {
                (idwvm.CurrentWizardPageVM as WizardPage_ChooseGame).ChooseGameCommand.Execute(game);
            }

            Assert.IsTrue(idwvm.CurrentWizardPageVM is WizardPage_ChooseDeckSourceType);
            (idwvm.CurrentWizardPageVM as WizardPage_ChooseDeckSourceType).ChooseDeckSourceTypeCommand.Execute(DeckSourceTypes.Webpage);

            Assert.IsTrue(idwvm.CurrentWizardPageVM is WizardPage_EnterWebpage);
            idwvm.Converter.DeckURL = deckURL;
            idwvm.MoveToNextStep();

            // It might take some time for the conversion, (or for the database to load) so wait for it
            DateTime waitForConversionUntil = DateTime.Now.Add(TimeSpan.FromSeconds(300));
            while (!(idwvm.CurrentWizardPageVM is WizardPage_CompareCards) && DateTime.Now < waitForConversionUntil)
            {
                System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(100));
            }

            Assert.IsTrue(idwvm.CurrentWizardPageVM is WizardPage_CompareCards);

            return idwvm.Converter.ConverterDeck;
        }
        /// <summary>
        /// Returns a Dictionary who's keys are Guids which represent Octgn Sets, and who's values are corresponding
        /// ConverterSet objects.  
        /// </summary>
        /// <param name="game">The Octgn.DataNew.Entities.Game object to use to read sets from</param>
        /// <returns>A Dictionary of Octgn Set Guids and corresponding ConverterSet objects</returns>
        private static Dictionary<Guid, ConverterSet> BuildCardDatabase(Octgn.DataNew.Entities.Game game)
        {
            if (game == null)
            {
                throw new ArgumentNullException();
            }

            // MTG has a property "MultiVerseId" which should be grabbed if it exists
            Octgn.DataNew.Entities.PropertyDef multiverseIdPropertyDef =
                game.CustomProperties.FirstOrDefault(p => p.Name.Equals("MultiVerseId", StringComparison.InvariantCultureIgnoreCase));

            Dictionary<Guid, ConverterSet> sets = new Dictionary<Guid, ConverterSet>();

            foreach (Octgn.DataNew.Entities.Set octgnSet in game.Sets())
            {
                sets[octgnSet.Id] = new ConverterSet(octgnSet);
                foreach (Octgn.DataNew.Entities.Card card in octgnSet.Cards)
                {
                    // Try to dig the MultiverseID property out of the Octgn.DataNew.Entities.Card
                    // During testing, all properties seemed nested under the first KeyValuePair in card.Properties
                    int multiverseID = 0;
                    if (multiverseIdPropertyDef != null)
                    {
                        if (card.Properties.Count > 0)
                        {
                            KeyValuePair<string, Octgn.DataNew.Entities.CardPropertySet> firstCardPropertyKVP = card.Properties.First();
                            object multiverseIdString = null;
                            if (firstCardPropertyKVP.Value.Properties.TryGetValue(multiverseIdPropertyDef, out multiverseIdString))
                            {
                                int.TryParse(multiverseIdString.ToString(), out multiverseID);
                            }
                        }
                    }

                    sets[octgnSet.Id].AddNewConverterCard
                    (
                        card.Id,
                        card.Name,
                        multiverseID
                    );
                }
            }

            foreach (KeyValuePair<Guid, ConverterSet> kvp in sets)
            {
                kvp.Value.SortConverterCards();

                if (SettingsManager.SingletonInstance.SetsExcludedFromSearches.Contains(kvp.Key))
                {
                    kvp.Value.IncludeInSearches = false;
                }
            }

            return sets;
        }
        /// <summary>
        /// Returns a Dictionary who's keys are Guids which represent Octgn Sets, and who's values are corresponding
        /// ConverterSet objects.  
        /// </summary>
        /// <param name="game">The Octgn.DataNew.Entities.Game object to use to read sets from</param>
        /// <returns>A Dictionary of Octgn Set Guids and corresponding ConverterSet objects</returns>
        private static Dictionary<Guid, ConverterSet> BuildCardDatabase(Octgn.DataNew.Entities.Game game)
        {
            if (game == null)
            {
                throw new ArgumentNullException();
            }

            // MTG has a property "MultiVerseId" which should be grabbed if it exists
            Octgn.DataNew.Entities.PropertyDef multiverseIdPropertyDef =
                game.CustomProperties.FirstOrDefault(p => p.Name.Equals("MultiVerseId", StringComparison.InvariantCultureIgnoreCase));

            Dictionary<Guid, ConverterSet> sets = new Dictionary<Guid, ConverterSet>();

            foreach (Octgn.DataNew.Entities.Set octgnSet in game.Sets())
            {
                sets[octgnSet.Id] = new ConverterSet(octgnSet);
                foreach (Octgn.DataNew.Entities.Card card in octgnSet.Cards)
                {
                    // Try to dig the MultiverseID property out of the Octgn.DataNew.Entities.Card
                    // During testing, all properties seemed nested under the first KeyValuePair in card.Properties
                    int multiverseID = 0;
                    if (multiverseIdPropertyDef != null)
                    {
                        if (card.Properties.Count > 0)
                        {
                            KeyValuePair<string, Octgn.DataNew.Entities.CardPropertySet> firstCardPropertyKVP = card.Properties.First();
                            object multiverseIdString = null;
                            if (firstCardPropertyKVP.Value.Properties.TryGetValue(multiverseIdPropertyDef, out multiverseIdString))
                            {
                                int.TryParse(multiverseIdString.ToString(), out multiverseID);
                            }
                        }
                    }

                    string name = card.Name;

                    // CoC uses special characters at the beginning of the card name to represent properties such as Unique and Steadfast.
                    // These characters should not be included as part of the name for comparison.
                    if (game.Id == ConvertEngine.Game.CoC.GameGuidStatic)
                    {
                        name = name.Trim(new Char[] { '{', '}', '[', ']', '<', '>', '_', '^', '*', ' ' });
                    }

                    sets[octgnSet.Id].AddNewConverterCard
                    (
                        card.Id,
                        name,
                        multiverseID
                    );
                }
            }

            foreach (KeyValuePair<Guid, ConverterSet> kvp in sets)
            {
                kvp.Value.SortConverterCards();

                if (SettingsManager.SingletonInstance.SetsExcludedFromSearches.Contains(kvp.Key))
                {
                    kvp.Value.IncludeInSearches = false;
                }
            }

            return sets;
        }
示例#24
0
        private void InstallSet(string fname, Octgn.Data.Game SelectedGame)
        {
            string shortName = Path.GetFileName(fname);
            UpdateStatus("Installing Set " + shortName);
            string path = Path.Combine(Prefs.DataDirectory, "Games", SelectedGame.Id.ToString(), "Sets");
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            try
            {
                if (shortName != null)
                {
                    string copyto = Path.Combine(path, shortName);
                    if (fname.ToLower() != copyto.ToLower())
                        File.Copy(fname, copyto, true);
                    SelectedGame.InstallSet(copyto);
                }
                UpdateStatus(string.Format("Set '{0}' installed.", shortName));
            }
            catch (Exception ex)
            {
                UpdateStatus(string.Format("'{0}' an error occured during installation:",shortName));
                UpdateStatus(ex.Message);
            }
        }
        /// <summary>
        /// Parses and verifies the card count of the deck URL.
        /// </summary>
        /// <param name="deckURL">The URL of the deck to verify</param>
        /// <param name="scratchDirectory">The directory to create the deck file in</param>
        /// <param name="game">The Game that should be chosen in the Wizard</param>
        public static void VerifyURL(
            string deckURL,
            IEnumerable<ExpectedDeckSection> expectedSectionsStats,
            Octgn.DataNew.Entities.Game game)
        {
            ConverterDeck converterDeck = ConvertURLUsingWizard(deckURL, game);

            foreach (ConverterSection converterSection in converterDeck.ConverterSections)
            {
                ExpectedDeckSection expectedSectionStats =
                    expectedSectionsStats.First(eds => eds.SectionName == converterSection.SectionName);

                Assert.AreEqual(expectedSectionStats.TotalCardCount, converterSection.SectionCount);
                Assert.AreEqual(expectedSectionStats.UniqueCardCount, converterSection.SectionMappings.Count(sm => sm.PotentialOCTGNCards.Count > 0));

                foreach (ConverterMapping converterMapping in converterSection.SectionMappings)
                {
                    // At least one potential match should have been found
                    Assert.IsTrue(converterMapping.PotentialOCTGNCards.Count() > 0);
                }
            }
        }