public void SetUp()
 {
     //common arrange
     _userServiceMock = new Mock <IUserService>(MockBehavior.Strict);
     _userController  = new UserController(_userServiceMock.Object);
     _user            = new User("Test User", "secret password");
     _client          = new MtcgClient(_user, "Test user-mtcgToken");
 }
示例#2
0
        public bool AddToStack(int userId, Guid cardId)
        {
            string     statement = "";
            User       user      = null;
            MtcgClient client    = null;

            if ((client =
                     ClientMapSingleton.GetInstance.ClientMap.Values.FirstOrDefault(c => c.User.UserId == userId)) == null)
            {
                statement = "SELECT * FROM mtcg.\"User\" " +
                            "WHERE \"Id\"=@userId";
                using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
                {
                    cmd.Parameters.Add("userId", NpgsqlDbType.Integer).Value = userId;
                    cmd.Prepare();
                    using (var reader = cmd.ExecuteReader(CommandBehavior.SingleResult))
                    {
                        if (reader.Read())
                        {
                            user = new User(reader);
                        }
                    }
                }

                if (user == null)
                {
                    return(false);
                }

                user.Stack.AddCard(cardId);
            }
            else
            {
                client.User.Stack.AddCard(cardId);
                ClientMapSingleton.GetInstance.ClientMap.AddOrUpdate(client.SessionToken, client,
                                                                     (key, oldValue) => client);
                user = client.User;
            }

            statement = "UPDATE mtcg.\"User\" " +
                        "SET \"Stack\"=@stack " +
                        "WHERE \"Id\"=@userId";
            using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
            {
                cmd.Parameters.Add("userId", NpgsqlDbType.Integer).Value = userId;
                cmd.Parameters.Add("stack", NpgsqlDbType.Varchar).Value  = JsonSerializer.Serialize(user.Stack.GetAllCards());
                cmd.Prepare();
                if (cmd.ExecuteNonQuery() != 1)
                {
                    return(false);
                }
            }

            return(true);
        }
 public KeyValuePair <StatusCode, object> ViewStats(ref MtcgClient client)
 {
     try
     {
         return(new KeyValuePair <StatusCode, object>(StatusCode.OK, client.User.Stats));
     }
     catch (Exception e)
     {
         return(HandleException(e));
     }
 }
 public KeyValuePair <StatusCode, object> ViewScoreboard(MtcgClient client)
 {
     try
     {
         return(new KeyValuePair <StatusCode, object>(StatusCode.OK, _userService.GetScoreboard(client)));
     }
     catch (Exception e)
     {
         return(HandleException(e));
     }
 }
示例#5
0
        public ResponseContext Get(Dictionary <string, object> param)
        {
            RequestContext request = (RequestContext)param["request"];
            MtcgClient     client  = (MtcgClient)param["client"];

            if (!request.QueryParams.ContainsKey("username"))
            {
                return(new ResponseContext(request, _marketController.GetAllOpenTradingDeals()));
            }

            return(new ResponseContext(request, _marketController.GetOpenTradingDealsForUser(request.QueryParams["username"])));
        }
 public KeyValuePair <StatusCode, object> EditProfile(ref MtcgClient client, Profile profile)
 {
     try
     {
         if (_userService.EditProfile(ref client, profile))
         {
             return(new KeyValuePair <StatusCode, object>(StatusCode.OK, profile));
         }
         return(new KeyValuePair <StatusCode, object>(StatusCode.InternalServerError, "Something went wrong"));
     }
     catch (Exception e)
     {
         return(HandleException(e));
     }
 }
        public KeyValuePair <StatusCode, object> ConfigureDeck(ref MtcgClient client, Deck deck)
        {
            try
            {
                if (client == null)
                {
                    return(new KeyValuePair <StatusCode, object>(StatusCode.Unauthorized, null));
                }

                //save old deck to fallback if necessary
                Deck oldDeck = new Deck();
                foreach (Card card in client.User.Deck.GetAllCards())
                {
                    oldDeck.AddCard(card);
                }

                //clear user deck
                client.User.Deck.ClearDeck();

                foreach (Card card in deck.GetAllCards())
                {
                    if (!client.User.Stack.GetAllCards().Any(c => c.Guid.Equals(card.Guid)))
                    {
                        return(new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You do not possess this card. Acquire some packages and you might will someday."));
                    }

                    if (!client.User.Deck.AddCard(card))
                    {
                        client.User.Deck.ClearDeck();
                        client.User.Deck.AddCards(oldDeck.GetAllCards());
                        return(new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "The given deck either contains more than 4 cards or has more than 2 same cards."));
                    }
                }

                if (((IDeckService)_userService).ConfigureDeck(ref client))
                {
                    return(new KeyValuePair <StatusCode, object>(StatusCode.OK, client.User.Deck.GetAllCards()));
                }

                client.User.Deck.ClearDeck();
                client.User.Deck.AddCards(oldDeck.GetAllCards());
                return(new KeyValuePair <StatusCode, object>(StatusCode.InternalServerError, ""));
            }
            catch (Exception e)
            {
                return(HandleException(e));
            }
        }
示例#8
0
        public ResponseContext Post(Dictionary <string, object> param)
        {
            RequestContext request = (RequestContext)param["request"];
            MtcgClient     client  = (MtcgClient)param["client"];

            //trade with existing deal
            if (!string.IsNullOrWhiteSpace(request.RequestedResource))
            {
                TradingDeal pendingDeal = null;
                if (!_marketController.TradingDealExists(request.RequestedResource, out pendingDeal))
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, $"There is no open deal with the given id {request.RequestedResource}")));
                }

                if (pendingDeal.PublisherId == client.User.UserId)
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You can't trade with yourself")));
                }

                Card cardToTrade = null;
                Guid cardGuid;
                if (string.IsNullOrWhiteSpace(request.Payload) || !Guid.TryParse(request.Payload, out cardGuid) ||
                    (cardToTrade = client.User.Stack.GetAllCards().FirstOrDefault(c => c.Guid.Equals(cardGuid))) == null)
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You must provide a card id that you possess and want to trade")));
                }

                return(new ResponseContext(request, _marketController.ProcessTrade(pendingDeal, cardToTrade, client)));
            }

            //create new deal
            TradingDeal deal = JsonSerializer.Deserialize <TradingDeal>(request.Payload);

            if (deal == null || string.IsNullOrWhiteSpace(deal.RequestedElement) || string.IsNullOrWhiteSpace(deal.RequestedType))
            {
                return(new ResponseContext(request,
                                           new KeyValuePair <StatusCode, object>(StatusCode.BadRequest,
                                                                                 "All properties must be set: CardId, RequestedElement, MinimumDamage, RequestedType")));
            }
            if (!client.User.Stack.GetAllCards().Any(c => c.Guid == deal.CardId))
            {
                return(new ResponseContext(request,
                                           new KeyValuePair <StatusCode, object>(StatusCode.BadRequest,
                                                                                 "Nice try, but you don't have this card ;)")));
            }
            deal.PublisherId = client.User.UserId;
            return(new ResponseContext(request, _marketController.AddTradingDeal(deal)));
        }
示例#9
0
        public ResponseContext Post(Dictionary <string, object> param)
        {
            RequestContext request       = (RequestContext)param["request"];
            MtcgClient     client        = (MtcgClient)param["client"];
            MtcgClient     waitingClient = null;

            foreach (KeyValuePair <string, MtcgClient> clientPair in ClientMapSingleton.GetInstance.ClientMap)
            {
                if (clientPair.Value.IsReadyForBattle)
                {
                    waitingClient = clientPair.Value;
                    break;
                }
            }

            if (waitingClient == null)
            {
                if (client.User.Deck.GetAllCards().Count() != 4)
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You have an invalid deck. Configure your deck and try again")));
                }
                client.IsReadyForBattle = true;
                ClientMapSingleton.GetInstance.ClientMap.AddOrUpdate(client.SessionToken, client,
                                                                     (key, oldValue) => client);

                while (client.IsReadyForBattle == true && client.CurrentBattleLog.Value == null)
                {
                    Thread.Sleep(100);
                    client = ClientMapSingleton.GetInstance.ClientMap[client.SessionToken];
                }

                KeyValuePair <StatusCode, object> responsePair = new KeyValuePair <StatusCode, object>(client.CurrentBattleLog.Key, client.CurrentBattleLog.Value);
                //reset battle log and ready for battle
                ResetBattleProperties(client);

                return(new ResponseContext(request, responsePair));
            }

            BattleBase battle = new BattleBase(ref client, ref waitingClient);

            if (!battle.CheckDecks())
            {
                ResetBattleProperties(client);
                return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You have an invalid deck. Configure your deck and try again")));
            }
            ResetBattleProperties(client);
            return(new ResponseContext(request, _battleController.StartBattle(battle)));
        }
示例#10
0
        public KeyValuePair <StatusCode, object> AcquirePackage(ref MtcgClient client, PackageType type)
        {
            if (!(_userService is IPackageTransactionService && _userService is ILoggable))
            {
                return(new KeyValuePair <StatusCode, object>(StatusCode.InternalServerError, null));
            }

            if (client == null)
            {
                return(new KeyValuePair <StatusCode, object>(StatusCode.Unauthorized, null));
            }

            try
            {
                int packagePrice = ((IPackageTransactionService)_userService).GetPackagePrice(type);
                if (packagePrice == -1)
                {
                    return(new KeyValuePair <StatusCode, object>(StatusCode.InternalServerError, null));
                }
                if (!HasEnoughCoins(client.User.Coins, packagePrice))
                {
                    return(new KeyValuePair <StatusCode, object>(StatusCode.Conflict, "You don't have enough coins"));
                }

                ((IPackageTransactionService)_userService).AcquirePackage(ref client, type);
                string logDescription =
                    $"{client.User.Username} acquired a {Enum.GetName(typeof(PackageType), type)} package and paid {packagePrice}.";
                bool logged = ((ILoggable)_userService).Log(new Dictionary <string, object>(new []
                {
                    new KeyValuePair <string, object>("client", client),
                    new KeyValuePair <string, object>("description", logDescription)
                }));


                if (!logged)
                {
                    Console.WriteLine("Package transaction was not logged");
                }

                return(new KeyValuePair <StatusCode, object>(StatusCode.OK, logDescription));
            }
            catch (Exception e)
            {
                return(HandleException(e));
            }
        }
示例#11
0
        /// <summary>
        /// Edit Profile
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual ResponseContext Put(Dictionary <string, object> param)
        {
            RequestContext request = (RequestContext)param["request"];

            if (!param.ContainsKey("client"))
            {
                return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.Unauthorized, "You need to log in to use this service.")));
            }
            MtcgClient client = (MtcgClient)param["client"];

            if (!request.Headers.ContainsKey("Content-Type") || request.Headers["Content-Type"] != "application/json")
            {
                return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.UnsupportedMediaType, "")));
            }

            Profile profile = JsonSerializer.Deserialize <Profile>(request.Payload);

            return(new ResponseContext(request, _userController.EditProfile(ref client, profile)));
        }
示例#12
0
        public bool EditStats(MtcgClient client)
        {
            string statement = "UPDATE mtcg.\"User\" " +
                               "SET \"Stats\"=@stats " +
                               "WHERE \"Username\"=@username AND \"Password_Hash\"=@password";

            string[] credentials = client.User.Credentials.Split(':', 2);
            using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
            {
                cmd.Parameters.Add("username", NpgsqlDbType.Varchar).Value = credentials[0];
                cmd.Parameters.Add("password", NpgsqlDbType.Bytea).Value   = Encoding.UTF8.GetBytes(credentials[1]);
                cmd.Parameters.Add("stats", NpgsqlDbType.Varchar).Value    = JsonSerializer.Serialize(client.User.Stats);
                cmd.Prepare();
                if (cmd.ExecuteNonQuery() != 1)
                {
                    return(false);
                }
            }
            return(true);
        }
示例#13
0
        public List <string> GetScoreboard(MtcgClient client)
        {
            List <User> users     = new List <User>();
            string      statement = "SELECT * FROM mtcg.\"User\"";

            using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
            {
                cmd.Prepare();
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        User user = new User(reader);
                        users.Add(user);
                    }
                }
            }

            return(users.OrderByDescending(u => u.Stats.Elo)
                   .Select((u, rank) => GetRankString(client, u, rank + 1)).ToList());
        }
        public override ResponseContext Post(Dictionary <string, object> param)
        {
            RequestContext request        = (RequestContext)param["request"];
            MtcgClient     client         = (MtcgClient)param["client"];
            PackageTypeDto packageTypeDto = null;

            if (request.Payload.Length > 0)
            {
                if (!request.Headers.ContainsKey("Content-Type") ||
                    request.Headers["Content-Type"] != "application/json")
                {
                    return(new ResponseContext(request,
                                               new KeyValuePair <StatusCode, object>(StatusCode.UnsupportedMediaType, "")));
                }

                packageTypeDto = JsonSerializer.Deserialize <PackageTypeDto>(request.Payload);
            }

            PackageType packageType = packageTypeDto?.ToObject() ?? PackageType.Basic;

            return(new ResponseContext(request, _userController.AcquirePackage(ref client, packageType)));
        }
示例#15
0
        public ResponseContext Delete(Dictionary <string, object> param)
        {
            RequestContext request = (RequestContext)param["request"];
            MtcgClient     client  = (MtcgClient)param["client"];

            //trade with existing deal
            if (!string.IsNullOrWhiteSpace(request.RequestedResource))
            {
                TradingDeal pendingDeal = null;
                if (!_marketController.TradingDealExists(request.RequestedResource, out pendingDeal))
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, $"There is no open deal with the given id {request.RequestedResource}")));
                }

                if (pendingDeal.PublisherId != client.User.UserId)
                {
                    return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You can't delete a trade that you did not create")));
                }

                return(new ResponseContext(request, _marketController.DeleteTradingDeal(pendingDeal)));
            }

            return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.BadRequest, "You must provide an id of an open trading deal")));
        }
示例#16
0
        public ResponseContext Put(Dictionary <string, object> param)
        {
            RequestContext request = (RequestContext)param["request"];
            MtcgClient     client  = (MtcgClient)param["client"];

            if (!request.Headers.ContainsKey("Content-Type") || request.Headers["Content-Type"] != "application/json")
            {
                return(new ResponseContext(request, new KeyValuePair <StatusCode, object>(StatusCode.UnsupportedMediaType, "")));
            }

            CardCollectionDto deckDto = JsonSerializer.Deserialize <CardCollectionDto>(request.Payload);

            deckDto.CardCollectionType = typeof(Deck);
            Deck deck;

            if (deckDto == null || deckDto.CardGuids.Count != 4 || (deck = deckDto.ToObject() as Deck) == null)
            {
                return(new ResponseContext(request,
                                           new KeyValuePair <StatusCode, object>(StatusCode.BadRequest,
                                                                                 "Either the deck does not contain 4 cards or some cards do not exist")));
            }

            return(new ResponseContext(request, _userController.ConfigureDeck(ref client, deck)));
        }
示例#17
0
 public BattleBase(ref MtcgClient player1, ref MtcgClient player2)
 {
     Player1 = player1;
     Player2 = player2;
 }
示例#18
0
        public KeyValuePair <StatusCode, object> ProcessTrade(TradingDeal deal, Card cardToTrade, MtcgClient client)
        {
            try
            {
                if (deal.MinimumDamage > cardToTrade.Damage || cardToTrade.GetType().Name != deal.RequestedType ||
                    Enum.GetName(typeof(ElementType), cardToTrade.Element) != deal.RequestedElement)
                {
                    return(new KeyValuePair <StatusCode, object>(StatusCode.BadRequest,
                                                                 $"The given card does not match the requirements Min Damage:{deal.MinimumDamage} Element: {deal.RequestedElement} Type: {deal.RequestedType}"));
                }

                _userService.AddToStack(deal.PublisherId, cardToTrade.Guid);
                _userService.AddToStack(client.User.UserId, deal.CardId);
                _userService.DeleteFromStack(deal.PublisherId, deal.Guid);
                _userService.DeleteFromStack(client.User.UserId, cardToTrade.Guid);

                _marketService.Trade(deal, client.User.UserId);
                return(new KeyValuePair <StatusCode, object>(StatusCode.OK, "Trade completed successfully"));
            }
            catch (Exception e)
            {
                return(HandleException(e));
            }
        }
        public bool AcquirePackage(ref MtcgClient client, PackageType type)
        {
            Package           package    = null;
            CardCollectionDto packageDto = null;
            int    price = 0;
            string statement;

            if (type == PackageType.Random)
            {
                packageDto = new CardCollectionDto()
                {
                    CardGuids          = AcquireRandomPackage(),
                    CardCollectionType = typeof(Package)
                };
                price = GetPackagePrice(PackageType.Random);
            }
            else
            {
                statement = "SELECT * FROM mtcg.\"Package\" p, mtcg.\"PackageType\" pT " +
                            "WHERE pt.\"Id\"=@packageTypeId AND p.\"PackageTypeId\"=pT.\"Id\" " +
                            "ORDER BY RANDOM() " +
                            "LIMIT 1;";

                using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
                {
                    cmd.Parameters.Add("packageTypeId", NpgsqlDbType.Integer).Value = (int)type;
                    cmd.Prepare();
                    using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
                    {
                        if (reader.HasRows)
                        {
                            reader.Read();
                            packageDto = new CardCollectionDto()
                            {
                                CardGuids          = JsonSerializer.Deserialize <List <Guid> >(reader["Cards"].ToString()),
                                CardCollectionType = typeof(Package)
                            };
                            price = (int)reader["Price"];
                        }
                    };
                }
            }

            package = packageDto?.ToObject() as Package;

            if (package == null)
            {
                return(false);
            }

            package.PackageType = type;

            //save old properties to fallback if necessary
            Stack <Package> oldUnopenedPackages = new Stack <Package>(new Stack <Package>(client.User.CurrentUnopenedPackages));

            client.User.RemoveCoins(price);
            client.User.AddPackage(package);

            statement = "UPDATE mtcg.\"User\" " +
                        "SET \"Coins\"=@coins, \"UnopenedPackages\"=@unopenedPackages " +
                        "WHERE \"Username\"=@username AND \"Password_Hash\"=@password";
            string[] credentials = client.User.Credentials.Split(':', 2);
            using (NpgsqlCommand cmd = new NpgsqlCommand(statement, PostgreSQLSingleton.GetInstance.Connection))
            {
                cmd.Parameters.Add("username", NpgsqlDbType.Varchar).Value         = credentials[0];
                cmd.Parameters.Add("password", NpgsqlDbType.Bytea).Value           = Encoding.UTF8.GetBytes(credentials[1]);
                cmd.Parameters.Add("coins", NpgsqlDbType.Integer).Value            = client.User.Coins;
                cmd.Parameters.Add("unopenedPackages", NpgsqlDbType.Varchar).Value = JsonSerializer.Serialize(client.User.CurrentUnopenedPackages);
                cmd.Prepare();
                if (cmd.ExecuteNonQuery() != 1)
                {
                    client.User.AddCoins(price);
                    client.User.CurrentUnopenedPackages = oldUnopenedPackages;
                    return(false);
                }
            }

            return(true);
        }