public async Task InitFileList()
        {
            string requestUri = FilesApi +
                                "?list" +
                                "&spaces=appDataFolder" +
                                "&q=" + Uri.EscapeDataString("trashed=false");

            bool bHasValidResponse = false;

            Reply reply = await HandleRequest("GET", requestUri);

            if (reply.bIsSuccessful)
            {
                JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(reply.contentBody);
                if (jsonOb != null)
                {
                    JsonParser.ArrayValue fileArr = (JsonParser.ArrayValue)jsonOb["files"];
                    foreach (JsonParser.Value entry in fileArr.entries)
                    {
                        JsonParser.ObjectValue entryOb = (JsonParser.ObjectValue)entry;

                        string mapKey = entryOb["name"];
                        mapFileIds.Remove(mapKey);
                        mapFileIds.Add(mapKey, entryOb["id"]);
                    }

                    bHasValidResponse = true;
                }
            }

            UpdateCurrentState(bHasValidResponse);
        }
Beispiel #2
0
        public List <ImageHashData> LoadImageHashes(JsonParser.ObjectValue jsonOb)
        {
            List <ImageHashData> list = new List <ImageHashData>();

            string[] enumArr = Enum.GetNames(typeof(EImageHashType));
            foreach (var kvp in jsonOb.entries)
            {
                EImageHashType        groupType = (EImageHashType)Array.IndexOf(enumArr, kvp.Key);
                JsonParser.ArrayValue typeArr   = (JsonParser.ArrayValue)kvp.Value;

                foreach (JsonParser.Value value in typeArr.entries)
                {
                    JsonParser.ObjectValue jsonHashOb = (JsonParser.ObjectValue)value;
                    string idStr = jsonHashOb["id"];

                    bool hasIdNum   = int.TryParse(idStr, out int idNum);
                    bool needsIdNum = (groupType != EImageHashType.Rule);
                    if (hasIdNum != needsIdNum)
                    {
                        continue;
                    }

                    ImageHashData hashEntry = new ImageHashData()
                    {
                        type = groupType, isKnown = true
                    };
                    switch (groupType)
                    {
                    case EImageHashType.Rule:
                        hashEntry.ownerOb = ParseRule(idStr);
                        break;

                    case EImageHashType.CardImage:
                        hashEntry.ownerOb = TriadCardDB.Get().cards[idNum];
                        break;

                    default:
                        hashEntry.ownerOb = idNum;
                        break;
                    }

                    if (hashEntry.ownerOb != null)
                    {
                        string descHashTLSH = jsonHashOb["hashC", JsonParser.StringValue.Empty];
                        string descHashMd5  = jsonHashOb["hashB", JsonParser.StringValue.Empty];

                        hashEntry.LoadFromString(descHashTLSH, descHashMd5);
                        if (hashEntry.IsValid())
                        {
                            list.Add(hashEntry);
                        }
                    }
                }
            }

            return(list);
        }
Beispiel #3
0
        private static Token CreateToken(string jsonStr)
        {
            JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(jsonStr);
            int validForSec = (JsonParser.IntValue)jsonOb["expires_in"];

            return(new Token
            {
                accessToken = jsonOb["access_token"],
                refreshToken = jsonOb["refresh_token", JsonParser.StringValue.Empty],
                expirationDate = DateTime.Now.AddSeconds(validForSec)
            });
        }
Beispiel #4
0
        private void TryGettingIntValue(JsonParser.ObjectValue ob, string key, ref int value)
        {
            if (ob.entries.ContainsKey(key))
            {
                var jsonValue = ob[key];
                var jsonInt   = jsonValue as JsonParser.IntValue;

                if (jsonInt != null)
                {
                    value = jsonInt.Number;
                }
            }
        }
Beispiel #5
0
        public List <ImagePatternDigit> LoadDigitHashes(JsonParser.ArrayValue jsonArr)
        {
            List <ImagePatternDigit> list = new List <ImagePatternDigit>();

            foreach (JsonParser.Value value in jsonArr.entries)
            {
                JsonParser.ObjectValue jsonOb = (JsonParser.ObjectValue)value;
                string hashValue = (JsonParser.StringValue)jsonOb["hash"];

                ImagePatternDigit digitHash = new ImagePatternDigit((JsonParser.IntValue)jsonOb["id"], ImageDataDigit.FromHexString(hashValue));
                list.Add(digitHash);
            }

            return(list);
        }
        private GameState LoadValidationConfig(string configPath)
        {
            GameState configData = new GameState();
            string    configText = File.ReadAllText(configPath);

            JsonParser.ObjectValue rootOb = JsonParser.ParseJson(configText);

            JsonParser.ArrayValue ruleArr = rootOb.entries["board"] as JsonParser.ArrayValue;
            configData.board = new int[ruleArr.entries.Count];
            for (int idx = 0; idx < ruleArr.entries.Count; idx++)
            {
                configData.board[idx] = ruleArr.entries[idx] as JsonParser.IntValue;
            }

            return(configData);
        }
Beispiel #7
0
        public List <ImageHashData> LoadImageHashes(JsonParser.ObjectValue jsonOb)
        {
            List <ImageHashData> list = new List <ImageHashData>();

            string[] enumArr = Enum.GetNames(typeof(EImageHashType));
            foreach (KeyValuePair <string, JsonParser.Value> kvp in jsonOb.entries)
            {
                EImageHashType        groupType = (EImageHashType)Array.IndexOf(enumArr, kvp.Key);
                JsonParser.ArrayValue typeArr   = (JsonParser.ArrayValue)kvp.Value;

                foreach (JsonParser.Value value in typeArr.entries)
                {
                    JsonParser.ObjectValue jsonHashOb = (JsonParser.ObjectValue)value;
                    string idStr = jsonHashOb["id"];

                    object hashOwner = null;
                    switch (groupType)
                    {
                    case EImageHashType.Rule: hashOwner = ParseRule(idStr); break;

                    case EImageHashType.Card: hashOwner = TriadCardDB.Get().cards[int.Parse(idStr)]; break;

                    case EImageHashType.Cactpot: hashOwner = CactpotGame.hashDB[int.Parse(idStr) - 1]; break;

                    default: break;
                    }

                    if (hashOwner != null)
                    {
                        HashCollection hashes    = new HashCollection(jsonHashOb["hashC", JsonParser.StringValue.Empty], jsonHashOb["hashS", JsonParser.StringValue.Empty]);
                        ImageHashData  hashEntry = new ImageHashData(hashOwner, hashes, groupType);
                        list.Add(hashEntry);
                    }
                }
            }

            return(list);
        }
Beispiel #8
0
            public void Load(JsonParser.ObjectValue configOb)
            {
                string ownerStr = configOb["player"] as JsonParser.StringValue;

                owner = (ownerStr == "blue") ? ETriadCardOwner.Blue : (ownerStr == "red") ? ETriadCardOwner.Red : ETriadCardOwner.Unknown;

                boardPos = configOb["pos"] as JsonParser.IntValue;

                if (configOb.entries.ContainsKey("board"))
                {
                    string boardCode = configOb["board"] as JsonParser.StringValue;
                    boardCode = boardCode.Replace(" ", "");

                    expectedState = new ETriadCardOwner[9];
                    for (int idx = 0; idx < expectedState.Length; idx++)
                    {
                        expectedState[idx] = (boardCode[idx] == 'R') ? ETriadCardOwner.Red : (boardCode[idx] == 'B') ? ETriadCardOwner.Blue : ETriadCardOwner.Unknown;
                    }
                }

                var cardName = configOb["card"] as JsonParser.StringValue;

                if (cardName != null)
                {
                    card = TriadCardDB.Get().Find(cardName);
                }
                else
                {
                    var cardSides = configOb["card"] as JsonParser.ArrayValue;

                    int numU = cardSides[0] as JsonParser.IntValue;
                    int numL = cardSides[1] as JsonParser.IntValue;
                    int numD = cardSides[2] as JsonParser.IntValue;
                    int numR = cardSides[3] as JsonParser.IntValue;

                    card = TriadCardDB.Get().Find(numU, numL, numD, numR);
                }
            }
Beispiel #9
0
        public async Task <bool> UploadTextFile(string fileName, string fileContent)
        {
            bool bResult = false;

            if (!mapFileIds.ContainsKey(fileName))
            {
                string uploadRequestUri = UploadApi + "?uploadType=multipart";
                string uploadMeta       = "{\"name\":\"" + fileName + "\",parents:[\"appDataFolder\"]}";

                Reply reply = await HandleRequest("POST", uploadRequestUri, uploadMeta, fileContent);

                if (reply.bIsSuccessful)
                {
                    JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(reply.contentBody);
                    if (jsonOb != null)
                    {
                        string fileId = jsonOb["id"];
                        mapFileIds.Remove(fileName);
                        mapFileIds.Add(fileName, fileId);
                        bResult = true;
                    }
                }
            }
            else
            {
                string patchRequestUri = UploadApi +
                                         "/" + mapFileIds[fileName] +
                                         "?uploadType=media";

                Reply reply = await HandleRequest("PATCH", patchRequestUri, fileContent);

                bResult = reply.bIsSuccessful;
            }

            UpdateCurrentState(bResult);
            return(bResult);
        }
Beispiel #10
0
        public static void RunTest(string configPath, bool debugMode)
        {
            string testName = System.IO.Path.GetFileNameWithoutExtension(configPath);

            string configText = System.IO.File.ReadAllText(configPath);

            JsonParser.ObjectValue configOb = JsonParser.ParseJson(configText);
            if (configOb["type"] != "Solver")
            {
                return;
            }

            TriadGameSession testSession = new TriadGameSession();

            // intial state
            ScannerTriad.VerifyConfig configData = new ScannerTriad.VerifyConfig();
            configData.Load(configOb);

            if (mapValidationRules == null)
            {
                mapValidationRules = new Dictionary <string, TriadGameModifier>();
                foreach (TriadGameModifier mod in ImageHashDB.Get().modObjects)
                {
                    mapValidationRules.Add(mod.GetCodeName(), mod);
                }
            }

            foreach (string modName in configData.rules)
            {
                testSession.modifiers.Add(mapValidationRules[modName]);
            }

            testSession.UpdateSpecialRules();
            TriadGameData testGameData = new TriadGameData()
            {
                bDebugRules = debugMode
            };

            if (configData.board.Length > 0)
            {
                Func <ScannerTriad.VerifyCard, TriadCard> ConvertToTriadCard = configCard =>
                {
                    if (configCard.state == ScannerTriad.ECardState.None)
                    {
                        return(null);
                    }
                    if (configCard.state == ScannerTriad.ECardState.Hidden)
                    {
                        return(TriadCardDB.Get().hiddenCard);
                    }

                    TriadCard matchingCard = !string.IsNullOrEmpty(configCard.name) ?
                                             TriadCardDB.Get().Find(configCard.name) :
                                             TriadCardDB.Get().Find(configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);

                    if (matchingCard == null)
                    {
                        string exceptionMsg = string.Format("Test {0} failed! Can't match validation card: '{1}' [{2},{3},{4},{5}]", testName,
                                                            configCard.name, configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);
                        throw new Exception(exceptionMsg);
                    }

                    return(matchingCard);
                };

                for (int idx = 0; idx < configData.board.Length; idx++)
                {
                    var configState = configData.board[idx].state;
                    if (configState != ScannerTriad.ECardState.None)
                    {
                        testGameData.board[idx] = new TriadCardInstance(ConvertToTriadCard(configData.board[idx]),
                                                                        (configState == ScannerTriad.ECardState.PlacedBlue) ? ETriadCardOwner.Blue :
                                                                        (configState == ScannerTriad.ECardState.PlacedRed) ? ETriadCardOwner.Red :
                                                                        ETriadCardOwner.Unknown);
                    }
                }
            }

            var deckRed  = new TriadDeck();
            var deckBlue = new TriadDeck();

            testGameData.deckBlue = new TriadDeckInstanceManual(deckBlue);
            testGameData.deckRed  = new TriadDeckInstanceManual(deckRed);

            JsonParser.ArrayValue moveArr = configOb.entries["moves"] as JsonParser.ArrayValue;
            for (int idx = 0; idx < moveArr.entries.Count; idx++)
            {
                var move = new VerifyMove();
                move.Load(moveArr.entries[idx] as JsonParser.ObjectValue);

                var useDeck = (move.owner == ETriadCardOwner.Blue) ? deckBlue : deckRed;
                useDeck.knownCards.Add(move.card);
                if (idx == 0)
                {
                    testGameData.state = (move.owner == ETriadCardOwner.Blue) ? ETriadGameState.InProgressBlue : ETriadGameState.InProgressRed;
                }

                if (debugMode)
                {
                    Logger.WriteLine("move[{0}]: [{1}] {2}: {3}", idx, move.boardPos, move.owner, move.card);
                }

                bool result = testSession.PlaceCard(testGameData, move.card, move.owner, move.boardPos);
                if (!result)
                {
                    string exceptionMsg = string.Format("Test {0} failed! Can't place card!", testName);
                    throw new Exception(exceptionMsg);
                }

                result = move.VerifyState(testGameData, debugMode);
                if (!result)
                {
                    string exceptionMsg = string.Format("Test {0} failed! Finished with bad state!", testName);
                    throw new Exception(exceptionMsg);
                }
            }
        }
Beispiel #11
0
        public bool LoadFromJson(string jsonStr)
        {
            TriadCardDB cardDB = TriadCardDB.Get();
            TriadNpcDB  npcDB  = TriadNpcDB.Get();

            try
            {
                JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(jsonStr);

                JsonParser.ObjectValue uiOb = (JsonParser.ObjectValue)jsonOb["ui", null];
                if (uiOb != null)
                {
                    useAutoScan = (JsonParser.BoolValue)uiOb["autoScan", JsonParser.BoolValue.Empty];
                }

                JsonParser.ObjectValue cloudOb = (JsonParser.ObjectValue)jsonOb["cloud", null];
                if (cloudOb != null)
                {
                    useCloudStorage = (JsonParser.BoolValue)cloudOb["use", JsonParser.BoolValue.Empty];
                    cloudToken      = (JsonParser.StringValue)cloudOb["token", null];
                }

                JsonParser.ArrayValue cardsArr = (JsonParser.ArrayValue)jsonOb["cards", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in cardsArr.entries)
                {
                    int cardId = (JsonParser.IntValue)value;
                    ownedCards.Add(cardDB.cards[cardId]);
                }

                JsonParser.ArrayValue npcsArr = (JsonParser.ArrayValue)jsonOb["npcs", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in npcsArr.entries)
                {
                    int npcId = (JsonParser.IntValue)value;
                    completedNpcs.Add(npcDB.npcs[npcId]);
                }

                JsonParser.ArrayValue decksArr = (JsonParser.ArrayValue)jsonOb["decks", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in decksArr.entries)
                {
                    JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value;
                    int npcId = (JsonParser.IntValue)deckOb["id"];

                    TriadNpc npc = TriadNpcDB.Get().npcs[npcId];
                    if (npc != null)
                    {
                        TriadDeck deckCards = new TriadDeck();

                        cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty];
                        foreach (JsonParser.Value cardValue in cardsArr.entries)
                        {
                            int cardId = (JsonParser.IntValue)cardValue;
                            deckCards.knownCards.Add(cardDB.cards[cardId]);
                        }

                        lastDeck.Add(npc, deckCards);
                    }
                }

                JsonParser.ArrayValue favDecksArr = (JsonParser.ArrayValue)jsonOb["favDecks", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in favDecksArr.entries)
                {
                    JsonParser.ObjectValue deckOb    = (JsonParser.ObjectValue)value;
                    TriadDeckNamed         deckCards = new TriadDeckNamed();

                    cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty];
                    foreach (JsonParser.Value cardValue in cardsArr.entries)
                    {
                        int cardId = (JsonParser.IntValue)cardValue;
                        deckCards.knownCards.Add(cardDB.cards[cardId]);
                    }

                    if (deckCards.knownCards.Count > 0)
                    {
                        deckCards.Name = deckOb["name", JsonParser.StringValue.Empty];
                        favDecks.Add(deckCards);
                    }
                }

                JsonParser.ObjectValue imageHashesOb = (JsonParser.ObjectValue)jsonOb["images", null];
                if (imageHashesOb != null)
                {
                    customHashes = ImageHashDB.Get().LoadImageHashes(imageHashesOb);
                }

                JsonParser.ArrayValue digitHashesArr = (JsonParser.ArrayValue)jsonOb["digits", null];
                if (digitHashesArr != null)
                {
                    customDigits = ImageHashDB.Get().LoadDigitHashes(digitHashesArr);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLine("Loading failed! Exception:" + ex);
            }

            return(ownedCards.Count > 0);
        }
        public static void RunTest(string configPath, bool debugMode)
        {
            string testName = System.IO.Path.GetFileNameWithoutExtension(configPath);

            string configText = System.IO.File.ReadAllText(configPath);

            JsonParser.ObjectValue rootOb = JsonParser.ParseJson(configText);
            if (rootOb["type"] != "Screen")
            {
                return;
            }

            ScannerTriad.VerifyConfig configData = new ScannerTriad.VerifyConfig();
            configData.Load(rootOb);

            // setup npc & modifiers
            TriadNpc testNpc = TriadNpcDB.Get().Find(configData.npc);

            if (testNpc == null)
            {
                string exceptionMsg = string.Format("Test {0} failed! Can't find npc: {1}", testName, configData.npc);
                throw new Exception(exceptionMsg);
            }

            ScannerTriad.GameState screenGame = new ScannerTriad.GameState();
            if (mapValidationRules == null)
            {
                mapValidationRules = new Dictionary <string, TriadGameModifier>();
                foreach (TriadGameModifier mod in ImageHashDB.Get().modObjects)
                {
                    mapValidationRules.Add(mod.GetCodeName(), mod);
                }
            }

            foreach (string modName in configData.rules)
            {
                screenGame.mods.Add(mapValidationRules[modName]);
            }

            Func <ScannerTriad.VerifyCard, TriadCard> ConvertToTriadCard = configCard =>
            {
                if (configCard.state == ScannerTriad.ECardState.None)
                {
                    return(null);
                }
                if (configCard.state == ScannerTriad.ECardState.Hidden)
                {
                    return(TriadCardDB.Get().hiddenCard);
                }

                TriadCard matchingCard = !string.IsNullOrEmpty(configCard.name) ?
                                         TriadCardDB.Get().Find(configCard.name) :
                                         TriadCardDB.Get().Find(configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);

                if (matchingCard == null)
                {
                    string exceptionMsg = string.Format("Test {0} failed! Can't match validation card: '{1}' [{2},{3},{4},{5}]", testName,
                                                        configCard.name, configCard.sides[0], configCard.sides[1], configCard.sides[2], configCard.sides[3]);
                    throw new Exception(exceptionMsg);
                }

                return(matchingCard);
            };

            bool needsLockedBlue = false;

            for (int idx = 0; idx < 5; idx++)
            {
                screenGame.blueDeck[idx] = ConvertToTriadCard(configData.deckBlue[idx]);
                screenGame.redDeck[idx]  = ConvertToTriadCard(configData.deckRed[idx]);

                if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Locked)
                {
                    needsLockedBlue = true;
                }
            }

            if (needsLockedBlue)
            {
                for (int idx = 0; idx < 5; idx++)
                {
                    if (configData.deckBlue[idx].state == ScannerTriad.ECardState.Visible)
                    {
                        screenGame.forcedBlueCard = screenGame.blueDeck[idx];
                        break;
                    }
                }
            }

            for (int idx = 0; idx < 9; idx++)
            {
                screenGame.board[idx]      = ConvertToTriadCard(configData.board[idx]);
                screenGame.boardOwner[idx] =
                    configData.board[idx].state == ScannerTriad.ECardState.PlacedBlue ? ETriadCardOwner.Blue :
                    configData.board[idx].state == ScannerTriad.ECardState.PlacedRed ? ETriadCardOwner.Red :
                    ETriadCardOwner.Unknown;
            }

            TriadGameScreenMemory screenMemory = new TriadGameScreenMemory {
                logScan = false
            };

            screenMemory.OnNewScan(screenGame, testNpc);
            screenMemory.gameSession.SolverFindBestMove(screenMemory.gameState, out int solverBoardPos, out TriadCard solverTriadCard, out TriadGameResultChance bestChance);

            if (bestChance.expectedResult == ETriadGameState.BlueLost && bestChance.winChance <= 0.0f && bestChance.drawChance <= 0.0f)
            {
                string exceptionMsg = string.Format("Test {0} failed! Can't find move!", testName);
                throw new Exception(exceptionMsg);
            }
        }
Beispiel #13
0
        public bool LoadFromJson(string jsonStr)
        {
            TriadCardDB cardDB = TriadCardDB.Get();
            TriadNpcDB  npcDB  = TriadNpcDB.Get();

            ownedCards.Clear();
            completedNpcs.Clear();
            lastDeck.Clear();
            favDecks.Clear();

            try
            {
                JsonParser.ObjectValue jsonOb = JsonParser.ParseJson(jsonStr);

                JsonParser.ObjectValue uiOb = (JsonParser.ObjectValue)jsonOb["ui", null];
                if (uiOb != null)
                {
                    JsonParser.Value BoolTrue  = new JsonParser.BoolValue(true);
                    JsonParser.Value BoolFalse = new JsonParser.BoolValue(false);

                    useXInput      = (JsonParser.BoolValue)uiOb["xInput", BoolTrue];
                    alwaysOnTop    = (JsonParser.BoolValue)uiOb["onTop", BoolFalse];
                    forcedLanguage = (JsonParser.StringValue)uiOb["lang", null];

                    TryGettingFloatValue(uiOb, "fontSize", ref fontSize);
                    TryGettingFloatValue(uiOb, "markerCard", ref markerDurationCard);
                    TryGettingFloatValue(uiOb, "markerSwap", ref markerDurationSwap);
                    TryGettingFloatValue(uiOb, "markerCactpot", ref markerDurationCactpot);

                    TryGettingIntValue(uiOb, "lastNpcId", ref lastNpcId);
                    TryGettingFloatValue(uiOb, "lastWidth", ref lastWidth);
                    TryGettingFloatValue(uiOb, "lastHeight", ref lastHeight);

                    fontSize = Math.Min(Math.Max(fontSize, 10), 40);
                }

                JsonParser.ObjectValue cloudOb = (JsonParser.ObjectValue)jsonOb["cloud", null];
                if (cloudOb != null)
                {
                    useCloudStorage = (JsonParser.BoolValue)cloudOb["use", JsonParser.BoolValue.Empty];
                    cloudToken      = (JsonParser.StringValue)cloudOb["token", null];
                }

                JsonParser.ArrayValue cardsArr = (JsonParser.ArrayValue)jsonOb["cards", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in cardsArr.entries)
                {
                    int cardId = (JsonParser.IntValue)value;
                    ownedCards.Add(cardDB.cards[cardId]);
                }

                JsonParser.ArrayValue npcsArr = (JsonParser.ArrayValue)jsonOb["npcs", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in npcsArr.entries)
                {
                    int npcId = (JsonParser.IntValue)value;
                    completedNpcs.Add(npcDB.npcs[npcId]);
                }

                JsonParser.ArrayValue decksArr = (JsonParser.ArrayValue)jsonOb["decks", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in decksArr.entries)
                {
                    JsonParser.ObjectValue deckOb = (JsonParser.ObjectValue)value;
                    int npcId = (JsonParser.IntValue)deckOb["id"];

                    TriadNpc npc = TriadNpcDB.Get().npcs[npcId];
                    if (npc != null)
                    {
                        TriadDeck deckCards = new TriadDeck();

                        cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty];
                        foreach (JsonParser.Value cardValue in cardsArr.entries)
                        {
                            int cardId = (JsonParser.IntValue)cardValue;
                            deckCards.knownCards.Add(cardDB.cards[cardId]);
                        }

                        lastDeck.Add(npc, deckCards);
                    }
                }

                JsonParser.ArrayValue favDecksArr = (JsonParser.ArrayValue)jsonOb["favDecks", JsonParser.ArrayValue.Empty];
                foreach (JsonParser.Value value in favDecksArr.entries)
                {
                    JsonParser.ObjectValue deckOb    = (JsonParser.ObjectValue)value;
                    TriadDeckNamed         deckCards = new TriadDeckNamed();

                    cardsArr = (JsonParser.ArrayValue)deckOb["cards", JsonParser.ArrayValue.Empty];
                    foreach (JsonParser.Value cardValue in cardsArr.entries)
                    {
                        int cardId = (JsonParser.IntValue)cardValue;
                        deckCards.knownCards.Add(cardDB.cards[cardId]);
                    }

                    if (deckCards.knownCards.Count > 0)
                    {
                        deckCards.Name = deckOb["name", JsonParser.StringValue.Empty];
                        favDecks.Add(deckCards);
                    }
                }

                JsonParser.ObjectValue imageHashesOb = (JsonParser.ObjectValue)jsonOb["images", null];
                if (imageHashesOb != null)
                {
                    customHashes = ImageHashDB.Get().LoadImageHashes(imageHashesOb);
                    ImageHashDB.Get().hashes.AddRange(customHashes);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLine("Loading failed! Exception:" + ex);
            }

            Logger.WriteLine("Loaded player cards: " + ownedCards.Count + ", npcs: " + completedNpcs.Count + ", hashes: " + customHashes.Count);
            return(ownedCards.Count > 0);
        }