Exemplo n.º 1
0
        /* - Dont do this as it will remove valid duplicate cards. Rely on the regular Sync instead,
         *
         * public void removeDupeCards()
         * {
         *  //loop through each pack. Pack filter should be up-to date even if this is called from the startup-checks.
         *  foreach (cardcast_pack pack in packs)
         *  {
         *      //add each card to one of these lists depending on whether it has been seen or not. Remove the removal ones afterwards.
         *      List<mod_xyzzy_card> validQCards = new List<mod_xyzzy_card>();
         *      List<mod_xyzzy_card> removeQCards = new List<mod_xyzzy_card>();
         *      foreach (mod_xyzzy_card c in questions.Where(y => y.category == pack.name) )
         *      {
         *          //is there a matching card already?
         *          List<mod_xyzzy_card> matchList = validQCards.Where(x => (x.category == pack.name && Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(c.text))).ToList();
         *          if (matchList.Count() > 1)
         *          {
         *              removeQCards.Add(c);
         *              //updating any references in active games.
         *              replaceCardReferences(c, matchList[0], "Q");
         *          }
         *          else
         *          {
         *              validQCards.Add(c);
         *          }
         *      }
         *      //remove any flagged cards
         *      foreach (mod_xyzzy_card c in removeQCards) { questions.Remove(c); }
         *
         *      //Repeat for answers
         *      List<mod_xyzzy_card> validACards = new List<mod_xyzzy_card>();
         *      List<mod_xyzzy_card> removeACards = new List<mod_xyzzy_card>();
         *      foreach (mod_xyzzy_card c in answers.Where(y => y.category == pack.name))
         *      {
         *          //is there a matching card already?
         *          List<mod_xyzzy_card> matchList = validACards.Where(x => (x.category == pack.name && Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(c.text))).ToList();
         *          if (matchList.Count() > 1)
         *          {
         *              removeACards.Add(c);
         *              //updating any references in active games.
         *              replaceCardReferences(c, matchList[0], "A");
         *          }
         *          else
         *          {
         *              validACards.Add(c);
         *          }
         *      }
         *      //remove any flagged cards
         *      int total = removeQCards.Count() + removeACards.Count();
         *      foreach (mod_xyzzy_card c in removeACards) { answers.Remove(c); }
         *      log("Removed " + removeQCards.Count() + " / " + removeACards.Count()
         + " duplicate q/a from " + pack.name
         + " new totals are " + questions.Where(y => y.category == pack.name).Count()
         + " / " + answers.Where(y => y.category == pack.name).Count() + " q/a."
         +          , total > 0? logging.loglevel.warn:logging.loglevel.verbose);
         +
         +
         +  }
         + }*/

        private void replaceCardReferences(mod_xyzzy_card old, mod_xyzzy_card newcard, string cardType)
        {
            foreach (chat c in Roboto.Settings.chatData)
            {
                mod_xyzzy_chatdata chatdata = (mod_xyzzy_chatdata)c.getPluginData(typeof(mod_xyzzy_chatdata));
                if (chatdata != null)
                {
                    chatdata.replaceCard(old, newcard, cardType);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Remove an answer card.
        /// </summary>
        /// <param name="cardToRemove"></param>
        /// <param name="replacementGuid"></param>
        /// <returns>Returns a list of chats that were potentially broken by the removal. </returns>
        private List <mod_xyzzy_chatdata> removeACard(mod_xyzzy_card cardToRemove, string replacementGuid)
        {
            List <mod_xyzzy_chatdata> result = new List <mod_xyzzy_chatdata>();

            //remove from the master list
            bool success = answers.Remove(cardToRemove);

            log("Answer " + cardToRemove.text + (success ? "successfully": "FAILED") + " to remove from master list", success ? logging.loglevel.normal:logging.loglevel.critical);

            //remove any cached answers / cards in hand
            foreach (chat c in Roboto.Settings.chatData)
            {
                mod_xyzzy_chatdata chatData = (mod_xyzzy_chatdata)c.getPluginData(typeof(mod_xyzzy_chatdata));
                if (chatData != null)
                {
                    //remove any cached answers
                    chatData.remainingAnswers.RemoveAll(x => x == cardToRemove.uniqueID);

                    //remove answers from player hands.
                    foreach (mod_xyzzy_player p in chatData.players)
                    {
                        int i = p.cardsInHand.RemoveAll(x => x == cardToRemove.uniqueID);
                        if (i > 0)
                        {
                            log("Removed " + i + " copies of card " + cardToRemove.text + " from player " + p.name + "'s hand", logging.loglevel.high);
                            if (replacementGuid != null)
                            {
                                p.cardsInHand.Add(replacementGuid);
                                log("Added " + replacementGuid + " to replace removed card", logging.loglevel.high);
                            }
                        }

                        //check if they have played the card.
                        i = p.selectedCards.RemoveAll(x => x == cardToRemove.uniqueID);
                        if (i > 0)
                        {
                            log("Removed " + i + " copies of card " + cardToRemove.text + " from player " + p.name + "'s selected cards", logging.loglevel.high);
                            if (replacementGuid != null)
                            {
                                p.selectedCards.Add(replacementGuid);
                                log("Added " + replacementGuid + " to replace removed selected card", logging.loglevel.high);
                            }
                            else
                            {
                                //removed a played card without a replacement guid - likely to all end in failure.
                                result.Add(chatData);
                            }
                        }
                    }
                }
            }
            return(result);
        }
Exemplo n.º 3
0
        private List <mod_xyzzy_chatdata> removeQCard(mod_xyzzy_card cardToRemove, string replacementGuid)
        {
            List <mod_xyzzy_chatdata> result = new List <mod_xyzzy_chatdata>();

            //remove from the master list
            bool success = questions.Remove(cardToRemove);

            log("Question " + cardToRemove.text + (success ? "successfully" : "FAILED") + " to remove from master list", success ? logging.loglevel.normal : logging.loglevel.critical);


            //remove any cached questions
            foreach (chat c in Roboto.Settings.chatData)
            {
                mod_xyzzy_chatdata chatData = (mod_xyzzy_chatdata)c.getPluginData(typeof(mod_xyzzy_chatdata));
                if (chatData != null)
                {
                    int recsRemoved = chatData.remainingQuestions.RemoveAll(x => x == cardToRemove.uniqueID);
                    if (recsRemoved > 0)
                    {
                        log("Removed question card from remaining question " + recsRemoved + " times from " + c.ToString(), logging.loglevel.warn);
                    }
                    //if we remove the current question, invalidate the chat. Will reask a question once the rest of the import is done.
                    if (chatData.currentQuestion == cardToRemove.uniqueID)
                    {
                        result.Add(chatData);
                        if (replacementGuid != null)
                        {
                            chatData.currentQuestion = replacementGuid;
                            log("The current question " + chatData.currentQuestion + " guid for chat " + c.ToString() + " has been replaced.", logging.loglevel.high);
                        }
                        else
                        {
                            log("The current question " + chatData.currentQuestion + " for " + chatData.status + " chat " + c.ToString() + " has been removed!", chatData.status == xyzzy_Statuses.Stopped? logging.loglevel.normal: logging.loglevel.high);
                        }
                    }
                }
            }
            return(result);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Import / Sync a cardcast pack into the xyzzy localdata
        /// </summary>
        /// <param name="packCode"></param>
        /// <param name="pack"></param>
        /// <param name="response"> String containing details of the pack and cards added.String will be empty if import failed.</param>
        /// <returns>success/fil</returns>
        public bool importCardCastPack(string packCode, out Helpers.cardcast_pack pack, out string response)
        {
            response = "";
            pack     = new Helpers.cardcast_pack();
            bool success = false;
            int  nr_qs   = 0;
            int  nr_as   = 0;
            int  nr_rep  = 0;
            List <Helpers.cardcast_question_card> import_questions = new List <Helpers.cardcast_question_card>();
            List <Helpers.cardcast_answer_card>   import_answers   = new List <Helpers.cardcast_answer_card>();
            List <mod_xyzzy_chatdata>             brokenChats      = new List <mod_xyzzy_chatdata>();

            logging.longOp lo_sync = new logging.longOp("XYZZY - Packsync", 5);

            try
            {
                log("Attempting to sync/import " + packCode);
                //Call the cardcast API. We should get an array of cards back (but in the wrong format)
                //note that this directly updates the pack object we are going to return - so need to shuffle around later if we sync a pack
                success = Helpers.cardCast.getPackCards(ref packCode, out pack, ref import_questions, ref import_answers);

                lo_sync.addone();

                if (!success)
                {
                    response = "Failed to import pack from cardcast. Check that the code is valid";
                }
                else
                {
                    //lets just check if the pack already exists?
                    log("Retrieved " + import_questions.Count() + " questions and " + import_answers.Count() + " answers from Cardcast");
                    Guid l_packID = pack.packID;
                    List <cardcast_pack> matchingPacks = getPackFilterList().Where(x => x.packCode == packCode).ToList();



                    if (matchingPacks.Count > 1)  // .Contains(pack.name))
                    {
                        log("Multiple packs found for " + l_packID + " - aborting!", logging.loglevel.critical);
                        response += "/n/r" + "Aborting sync!";
                    }
                    else if (matchingPacks.Count == 1)
                    {
                        cardcast_pack updatePack = matchingPacks[0];

                        //sync the pack.
                        response = "Pack " + pack.name + " (" + packCode + ") exists, syncing cards";
                        log("Pack " + pack.name + "(" + packCode + ") exists, syncing cards", logging.loglevel.normal);

                        //===================
                        //QUESTIONS
                        //===================

                        //NB: Used to do a first pass to remove any matching cards from the import list. This WONT work as it will remove the ability
                        //to find out how many copies of a card we should have! Instead, take a backup copy, remove items from that, and then delete
                        //anything that is remaining at the end.
                        List <mod_xyzzy_card> questionCache = questions.Where(x => (x.packID == updatePack.packID)).ToList();
                        log("=============================", logging.loglevel.high);
                        log("Procesing " + questionCache.Count() + " QUESTION cards", logging.loglevel.high);
                        log("=============================", logging.loglevel.high);
                        logging.longOp lo_q = new logging.longOp("Questions", questionCache.Count());

                        //Loop through everything that is in the import list, removing items as we go.
                        while (import_questions.Count() > 0)
                        {
                            lo_q.updateLongOp(questionCache.Count()); //go backwards. This is just the remaining nr cards.
                            cardcast_question_card currentCard = import_questions[0];
                            //find how many other matches in the import list we have.
                            List <cardcast_question_card> matchingImportCards = import_questions.Where(x => Helpers.common.cleanseText(x.question) == Helpers.common.cleanseText(currentCard.question)).ToList();
                            if (matchingImportCards.Count() == 0)
                            {
                                log("Error! No matches found for card '" + currentCard.question + "' - expect at least 1", logging.loglevel.critical);
                            }
                            else
                            {
                                log("Processing " + matchingImportCards.Count() + " cards matching " + currentCard.question, logging.loglevel.verbose);
                                List <mod_xyzzy_card> matchingLocalCards = questions.Where(x => (x.packID == updatePack.packID) && (Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(currentCard.question))).ToList();
                                log("Found " + matchingLocalCards.Count() + " local cards", logging.loglevel.verbose);

                                //assume the first cards should match the cards coming from CardCast. Update so we have exact text
                                int j = 0;
                                while (j < matchingLocalCards.Count() && j < matchingImportCards.Count())
                                {
                                    if (matchingLocalCards[j].text != matchingImportCards[j].question || matchingLocalCards[j].nrAnswers != matchingImportCards[j].nrAnswers)
                                    {
                                        try
                                        {
                                            log("Local question card updated from " + matchingLocalCards[j].text + "(" + matchingLocalCards[j].nrAnswers + ") to " + matchingImportCards[j].question + " (" + matchingImportCards[j].nrAnswers + ")", logging.loglevel.high);
                                            matchingLocalCards[j].text      = matchingImportCards[j].question;
                                            matchingLocalCards[j].nrAnswers = matchingImportCards[j].nrAnswers;
                                            nr_rep++;
                                        }
                                        catch (Exception e)
                                        {
                                            log("Error updating question text on qcard - " + e.Message, logging.loglevel.critical);
                                        }
                                    }
                                    j++;
                                }

                                //for the remainder, decide how to progress:
                                if (matchingLocalCards.Count() == matchingImportCards.Count())
                                {
                                    //log("Count matches, nothing more to do!", logging.loglevel.verbose);
                                }
                                //Need to add some new cards
                                else if (matchingLocalCards.Count() < matchingImportCards.Count())
                                {
                                    log("Not enough local cards, adding " + (matchingLocalCards.Count() - matchingImportCards.Count()) + " extra", logging.loglevel.verbose);
                                    for (int i = matchingLocalCards.Count(); i < matchingImportCards.Count(); i++)
                                    {
                                        log("Adding card " + i + " " + matchingImportCards[0].question, logging.loglevel.verbose);
                                        mod_xyzzy_card x_question = new mod_xyzzy_card(matchingImportCards[0].question, pack.packID, matchingImportCards[0].nrAnswers);
                                        questions.Add(x_question);
                                    }
                                }
                                //need to remove some existing cards. Retire cards by merging data into the first card
                                else
                                {
                                    for (int i = matchingImportCards.Count(); i < matchingLocalCards.Count(); i++)
                                    {
                                        //merge the card from the master list, and flag any chats as broken
                                        List <mod_xyzzy_chatdata> newBrokenChats = removeQCard(matchingLocalCards[i], matchingLocalCards[0].uniqueID);
                                        if (newBrokenChats.Count() > 0)
                                        {
                                            log("Marking " + newBrokenChats.Count() + " chats as requiring checking", logging.loglevel.high);
                                        }
                                        brokenChats.AddRange(newBrokenChats);
                                    }
                                }
                            }
                            //now remove all the processed import cards from our import list, and our cache
                            foreach (cardcast_question_card c in matchingImportCards)
                            {
                                import_questions.Remove(c);
                                log("Removed card from import list: " + c.question, logging.loglevel.verbose);
                            }
                            int matches = questionCache.RemoveAll(x => Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(currentCard.question));
                            log("Removed " + matches + " from temporary local cache", logging.loglevel.verbose);
                        }

                        //now remove anything left in the cache from the master question list.
                        lo_sync.addone();
                        foreach (mod_xyzzy_card c in questionCache)
                        {
                            log("Card wasnt processed - disposing of " + c.text, logging.loglevel.warn);
                            //remove the card
                            List <mod_xyzzy_chatdata> addnBrokenChats = removeQCard(c, null);
                            brokenChats.AddRange(addnBrokenChats);
                        }
                        lo_q.complete();
                        lo_sync.addone();
                        //===================
                        //ANSWERS
                        //===================

                        //NB: Used to do a first pass to remove any matching cards from the import list. This WONT work as it will remove the ability
                        //to find out how many copies of a card we should have! Instead, take a backup copy, remove items from that, and then delete
                        //anything that is remaining at the end.

                        List <mod_xyzzy_card> answerCache = answers.Where(x => (x.packID == updatePack.packID)).ToList();
                        log("=============================", logging.loglevel.high);
                        log("Procesing " + answerCache.Count() + " ANSWER cards", logging.loglevel.high);
                        log("=============================", logging.loglevel.high);
                        logging.longOp lo_a = new logging.longOp("Answers", answerCache.Count());



                        //Loop through everything that is in the import list, removing items as we go.
                        while (import_answers.Count() > 0)
                        {
                            lo_a.updateLongOp(answerCache.Count());

                            cardcast_answer_card currentCard = import_answers[0];
                            //find how many other matches in the import list we have.
                            List <cardcast_answer_card> matchingImportCards = import_answers.Where(x => Helpers.common.cleanseText(x.answer) == Helpers.common.cleanseText(currentCard.answer)).ToList();
                            if (matchingImportCards.Count() == 0)
                            {
                                log("Error! No matches found for card '" + currentCard.answer + "' - expect at least 1", logging.loglevel.critical);
                            }
                            else
                            {
                                log("Processing " + matchingImportCards.Count() + " cards matching " + currentCard.answer, logging.loglevel.verbose);
                                List <mod_xyzzy_card> matchingLocalCards = answers.Where(x => (x.packID == updatePack.packID) && (Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(currentCard.answer))).ToList();
                                log("Found " + matchingLocalCards.Count() + " local cards", logging.loglevel.verbose);

                                //assume the first cards should match the cards coming from CardCast. Update so we have exact text
                                int j = 0;
                                while (j < matchingLocalCards.Count() && j < matchingImportCards.Count())
                                {
                                    if (matchingLocalCards[j].text != matchingImportCards[j].answer)
                                    {
                                        try
                                        {
                                            log("Local answer card updated from " + matchingLocalCards[j].text + " to " + matchingImportCards[j].answer, logging.loglevel.high);
                                            matchingLocalCards[j].text = matchingImportCards[j].answer;
                                            // matchingLocalCards[j].nrAnswers = matchingImportCards[j].nrAnswers; <- automatically set to -1 for an answer card.
                                            nr_rep++;
                                        }
                                        catch (Exception e)
                                        {
                                            log("Error updating answer text on acard - " + e.Message, logging.loglevel.critical);
                                        }
                                    }
                                    j++;
                                }

                                //for the remainder, decide how to progress:
                                if (matchingLocalCards.Count() == matchingImportCards.Count())
                                {
                                    //log("Count matches, nothing more to do!", logging.loglevel.verbose);
                                }
                                //Need to add some new cards (either doesnt exist locally - new card - or they have added another copy remotely)
                                else if (matchingLocalCards.Count() < matchingImportCards.Count())
                                {
                                    log("Not enough local cards, adding " + (matchingImportCards.Count() - matchingLocalCards.Count()) + " extra", logging.loglevel.verbose);
                                    for (int i = matchingLocalCards.Count(); i < matchingImportCards.Count(); i++)
                                    {
                                        log("Adding card " + i + " - " + matchingImportCards[0].answer, logging.loglevel.verbose);
                                        mod_xyzzy_card x_answer = new mod_xyzzy_card(matchingImportCards[0].answer, pack.packID, matchingImportCards[0].nrAnswers);
                                        answers.Add(x_answer);
                                    }
                                }
                                //need to remove some existing cards. Retire cards by merging data into the first card
                                else
                                {
                                    for (int i = matchingImportCards.Count(); i < matchingLocalCards.Count(); i++)
                                    {
                                        List <mod_xyzzy_chatdata> newBrokenChats = removeACard(matchingLocalCards[i], matchingLocalCards[0].uniqueID);
                                        if (newBrokenChats.Count() > 0)
                                        {
                                            log("Marking " + newBrokenChats.Count() + " chats as requiring checking", logging.loglevel.high);
                                        }
                                        brokenChats.AddRange(newBrokenChats);
                                    }
                                }
                            }
                            //now remove all the processed import cards from our import list, and our cache
                            lo_sync.addone();
                            foreach (cardcast_answer_card c in matchingImportCards)
                            {
                                import_answers.Remove(c);
                                log("Removed card from import list: " + c.answer, logging.loglevel.verbose);
                            }
                            int matches = answerCache.RemoveAll(x => Helpers.common.cleanseText(x.text) == Helpers.common.cleanseText(currentCard.answer));
                            log("Removed " + matches + " from temporary local cache", logging.loglevel.verbose);
                        }

                        //now remove anything left in the cache from the master answer list.
                        foreach (mod_xyzzy_card c in answerCache)
                        {
                            log("Card wasnt processed - suggests it was removed from the cardcast pack. Disposing of " + c.text, logging.loglevel.warn);
                            List <mod_xyzzy_chatdata> addnBrokenChats = removeQCard(c, null);
                            brokenChats.AddRange(addnBrokenChats);
                        }
                        lo_a.complete();
                        lo_sync.addone();


                        //Update the updatePack with the values from the imported pack
                        updatePack.description = pack.description;
                        updatePack.name        = pack.name;

                        //swap over our return objet to the one returned from CC.
                        pack = updatePack;

                        Roboto.Settings.stats.logStat(new statItem("Packs Synced", typeof(mod_xyzzy)));
                        lo_sync.addone();

                        success = true;
                    }
                    else
                    {
                        response += "Importing fresh pack " + pack.packCode + " - " + pack.name + " - " + pack.description;
                        logging.longOp lo_import = new logging.longOp("Import", import_answers.Count + import_questions.Count, lo_sync);
                        foreach (Helpers.cardcast_question_card q in import_questions)
                        {
                            mod_xyzzy_card x_question = new mod_xyzzy_card(q.question, pack.packID, q.nrAnswers);
                            questions.Add(x_question);
                            nr_qs++;
                            lo_import.addone();
                        }
                        foreach (Helpers.cardcast_answer_card a in import_answers)
                        {
                            mod_xyzzy_card x_answer = new mod_xyzzy_card(a.answer, pack.packID);
                            answers.Add(x_answer);
                            nr_as++;
                            lo_import.addone();
                        }

                        response += "\n\r" + "Next sync " + pack.nextSync.ToString("f") + ".";

                        response += "\n\r" + "Added " + nr_qs.ToString() + " questions and " + nr_as.ToString() + " answers.";
                        packs.Add(pack);
                        response += "\n\r" + "Added " + pack.name + " to filter list.";
                        lo_import.complete();
                    }
                }
            }
            catch (Exception e)
            {
                log("Failed to import pack " + e.ToString(), logging.loglevel.critical);
                success = false;
            }

            foreach (mod_xyzzy_chatdata c in brokenChats.Distinct())
            {
                c.check(true);
            }

            lo_sync.complete();
            log(response, logging.loglevel.normal);

            return(success);
        }