/**
* Copyright 2019 Heroic Labs and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Collections.Generic;
using System.Threading.Tasks;
using DemoGame.Scripts.DataStorage;
using DemoGame.Scripts.Gameplay.Cards;
namespace DemoGame.Scripts.Gameplay.Decks
{
///
/// Used to send and retrieve informations about user's deck.
///
public class DeckStorage : DataStorage
{
#region Properties
///
/// Determines who can change the deck on the server.
///
public override StorageWritePermission WritePermission => StorageWritePermission.NoWrite;
///
/// Determines who can read the deck.
///
public override StorageReadPermission ReadPermission => StorageReadPermission.PublicRead;
///
/// The colection this data storage saves the deck info.
///
public override string StorageCollection => "deck";
#endregion
#region Methods
///
/// Returns the key under which user's deck can be found on the server.
///
public override string StorageKey(Deck deck) => "deck";
///
/// Retrieves deck data from the server.
///
public async override Task LoadDataAsync(string userId, string key)
{
// Get deck's name
string deckNameJson = await base.LoadDataJsonAsync(userId, "name");
if (string.IsNullOrEmpty(deckNameJson) == true)
{
return null;
}
// Get cards used in deck
string usedCardsJson = await base.LoadDataJsonAsync(userId, "used_cards");
// Get owned cards not used in deck
string unusedCardsJson = await base.LoadDataJsonAsync(userId, "unused_cards");
// Parse received data
string deckName = Nakama.TinyJson.JsonParser.FromJson(deckNameJson);
List usedCards = DeserializeCards(usedCardsJson);
List unusedCards = DeserializeCards(unusedCardsJson);
// Create new deck instance
Deck deck = new Deck();
deck.deckName = deckName;
deck.usedCards = usedCards;
deck.unusedCards = unusedCards;
// Initialize cards
foreach (Card card in deck.unusedCards)
{
card.isUsed = false;
}
foreach (Card card in deck.usedCards)
{
card.isUsed = true;
}
return deck;
}
///
/// Saves supplied deck data on the server.
///
public override async Task StoreDataAsync(Deck data)
{
string key = StorageKey(data);
Dictionary> usedCards = SerializeCards(data.usedCards);
Dictionary> unusedCards = SerializeCards(data.unusedCards);
Dictionary name = new Dictionary { { "name", data.deckName } };
bool good;
good = await base.StoreDataAsync("used_cards", Nakama.TinyJson.JsonWriter.ToJson(usedCards));
if (good == false)
{
return false;
}
good = await base.StoreDataAsync("unused_cards", Nakama.TinyJson.JsonWriter.ToJson(unusedCards));
if (good == false)
{
return false;
}
good = await base.StoreDataAsync("name", Nakama.TinyJson.JsonWriter.ToJson(name));
if (good == false)
{
return false;
}
return true;
}
///
/// Serialize a list of cards into a dictionary which can be easly parsed one Json string.
/// By grouping cards by their type and level we can decrease the size of send package.
///
private Dictionary> SerializeCards(List cardList)
{
Dictionary> cards = new Dictionary>();
foreach (Card card in cardList)
{
Dictionary dictionary;
if (cards.TryGetValue(((int)card.cardType).ToString(), out dictionary) == true)
{
if (dictionary.ContainsKey(card.level.ToString()) == false)
{
dictionary.Add(card.level.ToString(), 1);
}
else
{
dictionary[card.level.ToString()] += 1;
}
}
else
{
dictionary = new Dictionary();
dictionary.Add(card.level.ToString(), 1);
cards.Add(((int)card.cardType).ToString(), dictionary);
}
}
return cards;
}
///
/// Deserializes Json string into a list of cards.
///
private List DeserializeCards(string json)
{
Dictionary> dictionary;
dictionary = Nakama.TinyJson.JsonParser.FromJson>>(json);
List cards = new List();
if (dictionary == null)
{
return cards;
}
foreach (KeyValuePair> pair in dictionary)
{
foreach (KeyValuePair innerPair in pair.Value)
{
for (int i = 0; i < innerPair.Value; i++)
{
Card card = new Card();
card.cardType = (CardType)System.Enum.Parse(typeof(CardType), pair.Key);
card.level = int.Parse(innerPair.Key);
cards.Add(card);
}
}
}
return cards;
}
#endregion
}
}