public void TestGuid()
        {
            HashSet <byte[]>         guids    = new HashSet <byte[]>();
            Dictionary <string, int> guidlist = new Dictionary <string, int>();
            int maxnum = 100;

            for (int i = 0; i < maxnum; i++)
            {
                byte[] g = GuidGenerator.GenerateSequentialGuid();
                guids.Add(g);
                guidlist[GuidGenerator.HelperBAToString(g)] = i;
            }
            Assert.Equal(maxnum, guids.Count);
            List <string> keys = guidlist.Keys.ToList();

            keys.Sort();
            for (int i = 1; i < keys.Count; i++)
            {
                Assert.Equal(1, guidlist[keys[i]] - guidlist[keys[i - 1]]);
            }
        }
Exemple #2
0
        private void GamesMeta(MyContext db)
        {
            Field <ListGraphType <TagType> >(
                "updateTags",
                description: "Update your game tags. The tags you provide replace all existing tags for the given game. This action is therefore idempotent.",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <UpdateTagsInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <UpdateTagsDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can tag games.");
                }

                //Check for duplicates
                HashSet <string> uniques = new HashSet <string>(from x in input.tags select x.game);
                if (uniques.Count != input.tags.Count())
                {
                    throw new ExecutionError("Your list contained duplicate game IDs. Please fix and resubmit.");
                }

                foreach (var g in input.tags)
                {
                    //Delete all existing tags for this game and user
                    db.GamesMetaTags.RemoveRange(db.GamesMetaTags.Where(x => x.OwnerId.Equals(user.OwnerId) && x.GameId.Equals(GuidGenerator.HelperStringToBA(g.game))));
                    //Add the given tags
                    foreach (var t in g.tags)
                    {
                        var tag = new GamesMetaTags
                        {
                            EntryId = GuidGenerator.GenerateSequentialGuid(),
                            GameId  = GuidGenerator.HelperStringToBA(g.game),
                            OwnerId = user.OwnerId,
                            Tag     = t
                        };
                        db.GamesMetaTags.Add(tag);
                    }
                }
                db.SaveChanges();
                // TODO:
                // For some reason, `Game` is not populating automatically in this resolver.
                // For now, I'm manually populating it, but I need to figure out why lazy loading isn't working.
                List <GamesMetaTags> retlst = new List <GamesMetaTags>();
                foreach (var rec in user.GamesMetaTags)
                {
                    if (rec.GameId == null)
                    {
                        throw new ExecutionError("GameID was null!");
                    }
                    if (rec.Game == null)
                    {
                        rec.Game = db.GamesMeta.Single(x => x.GameId.Equals(rec.GameId));
                    }
                    retlst.Add(rec);
                }
                return(retlst.ToArray());
                // return user.GamesMetaTags.ToArray();
            }
                );
            Field <ListGraphType <RankType> >(
                "updateRankings",
                description: "Update your game rankings. This input completely replaces existing rankings. This action is therefore idempotent.",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <UpdateRankingsInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <UpdateRankingsDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can rank games.");
                }

                //Check for duplicates
                HashSet <string> uniques = new HashSet <string>(from x in input.rankings select x.game);
                if (uniques.Count != input.rankings.Count())
                {
                    throw new ExecutionError("Your list contained duplicates game IDs. Please fix and resubmit.");
                }

                //Delete all existing rankings
                db.GamesMetaRanks.RemoveRange(db.GamesMetaRanks.Where(x => x.OwnerId.Equals(user.OwnerId)));

                //Populate with given input
                foreach (var r in input.rankings)
                {
                    var rank = new GamesMetaRanks
                    {
                        EntryId = GuidGenerator.GenerateSequentialGuid(),
                        GameId  = GuidGenerator.HelperStringToBA(r.game),
                        OwnerId = user.OwnerId,
                        Rank    = r.rank
                    };
                    db.GamesMetaRanks.Add(rank);
                }

                db.SaveChanges();
                // TODO:
                // For some reason, `Game` is not populating automatically in this resolver.
                // For now, I'm manually populating it, but I need to figure out why lazy loading isn't working.
                List <GamesMetaRanks> retlst = new List <GamesMetaRanks>();
                foreach (var rec in user.GamesMetaRanks)
                {
                    if (rec.GameId == null)
                    {
                        throw new ExecutionError("GameID was null!");
                    }
                    if (rec.Game == null)
                    {
                        rec.Game = db.GamesMeta.Single(x => x.GameId.Equals(rec.GameId));
                    }
                    retlst.Add(rec);
                }
                // return user.GamesMetaRanks.ToArray();
                return(retlst.ToArray());
            }
                );
        }
Exemple #3
0
        private void Profiles(MyContext db)
        {
            Field <UserType>(
                "createProfile",
                description: "Create a new profile",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <NewProfileInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var profile = _.GetArgument <NewProfileDTO>("input");
                StringInfo strinfo;

                //Validate input
                //check for duplicate cognitoId first
                if (db.Owners.Any(x => x.CognitoId.Equals(context.cognitoId)))
                {
                    throw new ExecutionError("You already have an account. Use the `updateProfile` command to make changes to an existing profile.");
                }

                //name
                if (String.IsNullOrWhiteSpace(profile.name))
                {
                    throw new ExecutionError("The 'name' field is required.");
                }
                strinfo = new StringInfo(profile.name);
                if ((strinfo.LengthInTextElements < 3) || (strinfo.LengthInTextElements > 30))
                {
                    throw new ExecutionError("The 'name' field must be between 3 and 30 utf-8 characters in length.");
                }
                if (db.OwnersNames.Any(x => x.Name.Equals(profile.name)))
                {
                    throw new ExecutionError("The name you requested is either in use or has been recently used. Please choose a different one.");
                }

                //country
                if ((!String.IsNullOrWhiteSpace(profile.country)) && (profile.country.Length != 2))
                {
                    throw new ExecutionError("The 'country' field must consist of only two characters, representing a valid ISO 3166-1 alpha-2 country code.");
                }
                profile.country = profile.country.ToUpper();

                //tagline
                if (!String.IsNullOrWhiteSpace(profile.tagline))
                {
                    strinfo = new StringInfo(profile.tagline);
                    if (strinfo.LengthInTextElements > 255)
                    {
                        throw new ExecutionError("The 'tagline' field may not exceed 255 utf-8 characters.");
                    }
                }

                //anonymous
                //Apparently doesn't need to be checked. Should auto-default to false.

                //consent
                if (profile.consent != true)
                {
                    throw new ExecutionError("You must consent to the terms of service and to the processing of your data to create an account and use Abstract Play.");
                }

                //Create record
                DateTime now    = DateTime.UtcNow;
                byte[] ownerId  = GuidGenerator.GenerateSequentialGuid();
                byte[] playerId = Guid.NewGuid().ToByteArray();
                Owners owner    = new Owners {
                    OwnerId     = ownerId,
                    CognitoId   = context.cognitoId,
                    PlayerId    = playerId,
                    DateCreated = now,
                    ConsentDate = now,
                    Anonymous   = profile.anonymous,
                    Country     = profile.country,
                    Tagline     = profile.tagline
                };
                OwnersNames ne = new OwnersNames {
                    EntryId       = GuidGenerator.GenerateSequentialGuid(),
                    OwnerId       = ownerId,
                    EffectiveFrom = now,
                    Name          = profile.name
                };
                owner.OwnersNames.Add(ne);
                db.Add(owner);
                db.SaveChanges();
                return(owner);
            }
                );

            Field <UserType>(
                "updateProfile",
                description: "Update your existing profile",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <PatchProfileInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <PatchProfileDTO>("input");
                // LambdaLogger.Log(JsonConvert.SerializeObject(input));

                //Load profile first
                Owners rec = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (rec == null)
                {
                    throw new ExecutionError("Could not find your profile. You need to do `createProfile` first.");
                }

                //name
                if (!String.IsNullOrWhiteSpace(input.name))
                {
                    var strinfo = new StringInfo(input.name);
                    if ((strinfo.LengthInTextElements < 3) || (strinfo.LengthInTextElements > 30))
                    {
                        throw new ExecutionError("The 'name' field must be between 3 and 30 utf-8 characters in length.");
                    }
                    if (db.OwnersNames.Any(x => x.Name.Equals(input.name)))
                    {
                        throw new ExecutionError("The name you requested is either in use or has been recently used. Please choose a different one.");
                    }
                    DateTime now   = DateTime.UtcNow;
                    OwnersNames ne = new OwnersNames {
                        EntryId       = GuidGenerator.GenerateSequentialGuid(),
                        OwnerId       = rec.OwnerId,
                        EffectiveFrom = now,
                        Name          = input.name
                    };
                    rec.OwnersNames.Add(ne);
                }

                //country
                if (!String.IsNullOrWhiteSpace(input.country))
                {
                    if (input.country.Length != 2)
                    {
                        throw new ExecutionError("The 'country' field must consist of only two characters, representing a valid ISO 3166-1 alpha-2 country code.");
                    }
                    rec.Country = input.country.ToUpper();
                    //If it's not null, it's an empty or whitespace string, so remove from the profile
                }
                else if (input.country != null)
                {
                    rec.Country = null;
                }

                //tagline
                if (!String.IsNullOrWhiteSpace(input.tagline))
                {
                    var strinfo = new StringInfo(input.tagline);
                    if (strinfo.LengthInTextElements > 255)
                    {
                        throw new ExecutionError("The 'tagline' field may not exceed 255 utf-8 characters.");
                    }
                    rec.Tagline = input.tagline;
                }
                else if (input.tagline != null)
                {
                    rec.Tagline = null;
                }

                //anonymous
                if (input.anonymous != null)
                {
                    rec.Anonymous = (bool)input.anonymous;
                }

                db.Owners.Update(rec);
                db.SaveChanges();
                return(rec);
            }
                );
        }
Exemple #4
0
        private void Dms(MyContext db)
        {
            Field <DmsType>(
                "sendDm",
                description: "Send a new direct message",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <SendDmInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <SendDmDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can send messages.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.recipient);
                }
                catch
                {
                    throw new ExecutionError("The recipient ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var receiver = db.Owners.SingleOrDefault(x => x.OwnerId.Equals(binaryid));
                if (receiver == null)
                {
                    throw new ExecutionError("Could not find the requested recipient.");
                }

                if (receiver.OwnerId == user.OwnerId)
                {
                    throw new ExecutionError("You can't send messages to yourself.");
                }

                var dm = new Dms
                {
                    EntryId    = GuidGenerator.GenerateSequentialGuid(),
                    SenderId   = user.OwnerId,
                    Sender     = user,
                    ReceiverId = binaryid,
                    Receiver   = receiver,
                    DateSent   = DateTime.UtcNow,
                    Message    = input.message,
                    Read       = false
                };
                db.Dms.Add(dm);
                db.SaveChanges();
                return(dm);
            }
                );
            Field <ListGraphType <DmsType> >(
                "deleteDms",
                description: "Delete direct messages",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <DeleteDmsInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <DeleteDmsDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can use the messaging system.");
                }

                var binids = input.ids.Select(x => GuidGenerator.HelperStringToBA(x));
                db.Dms.RemoveRange(db.Dms.Where(x => x.ReceiverId.Equals(user.OwnerId) && binids.Contains(x.EntryId)));
                db.SaveChanges();
                return(db.Dms.Where(x => x.ReceiverId.Equals(user.OwnerId)).ToArray());
            }
                );
            Field <ListGraphType <DmsType> >(
                "readDms",
                description: "Mark direct messages as read",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <ReadDmsInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <ReadDmsDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can use the messaging system.");
                }

                var binids = input.ids.Select(x => GuidGenerator.HelperStringToBA(x));
                foreach (var rec in db.Dms.Where(x => x.ReceiverId.Equals(user.OwnerId) && binids.Contains(x.EntryId)))
                {
                    rec.Read = true;
                }
                db.SaveChanges();
                return(db.Dms.Where(x => x.ReceiverId.Equals(user.OwnerId) && x.Read.Equals(false)).ToArray());
            }
                );
        }
Exemple #5
0
        private void Console(MyContext db)
        {
            Field <GamesDataType>(
                "newConsole",
                description: "Issue a new console command to a game",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <NewConsoleInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <NewConsoleDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                if (!Enum.IsDefined(typeof(ConsoleCommands), input.command))
                {
                    throw new ExecutionError("The command you issued was unrecognized. This shouldn't happen if you issued the request through the official front end.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The game ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var game = db.GamesData.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (game == null)
                {
                    throw new ExecutionError("The game id you provided (" + input.id + ") does not appear to exist.");
                }

                if (game.Closed)
                {
                    throw new ExecutionError("This game has ended. No further actions are possible.");
                }

                //For some reason, `.Any(x => x.OwnerId.Equals(user.OwnerId))` is not working. I don't know why yet.
                if (!game.GamesDataPlayers.Select(x => x.Owner).Contains(user))
                {
                    throw new ExecutionError("You're not participating in this game and so cannot issue console commands.");
                }

                //Command-specific error checks
                switch ((ConsoleCommands)input.command)
                {
                case ConsoleCommands.DRAW:
                    break;

                case ConsoleCommands.FREEZE:
                    if (game.ClockFrozen)
                    {
                        throw new InvalidOperationException("The clocks are already frozen.");
                    }
                    break;

                case ConsoleCommands.THAW:
                    if (!game.ClockFrozen)
                    {
                        throw new InvalidOperationException("The clocks are not frozen.");
                    }
                    break;
                }

                var consolekey = GuidGenerator.GenerateSequentialGuid();
                var cmd        = new Consoles
                {
                    EntryId = consolekey,
                    GameId  = game.EntryId,
                    Game    = game,
                    OwnerId = user.OwnerId,
                    Owner   = user,
                    Command = input.command
                };
                db.Consoles.Add(cmd);

                var vote = new ConsolesVotes
                {
                    EntryId         = GuidGenerator.GenerateSequentialGuid(),
                    ConsoleId       = consolekey,
                    Voter           = user.OwnerId,
                    VoterNavigation = user,
                    Vote            = true
                };
                db.ConsolesVotes.Add(vote);
                db.SaveChanges();

                return(game);
            }
                );
            Field <GamesDataType>(
                "withdrawConsole",
                description: "Withdraw a console command",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <WithdrawConsoleInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <WithdrawConsoleDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The command ID you provided is malformed. Please verify and try again.");
                }

                //Does this console command exist?
                var cmd = db.Consoles.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (cmd == null)
                {
                    throw new ExecutionError("The command id you provided (" + input.id + ") does not appear to exist.");
                }

                if (cmd.OwnerId != user.OwnerId)
                {
                    throw new ExecutionError("Only the person who issued the command can withdraw it.");
                }

                GamesData game = cmd.Game;
                db.Consoles.Remove(cmd);
                db.SaveChanges();

                return(game);
            }
                );
            Field <GamesDataType>(
                "voteConsole",
                description: "Vote on a console command",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <VoteConsoleInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <VoteConsoleDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The command ID you provided is malformed. Please verify and try again.");
                }

                //Does this console command exist?
                var cmd = db.Consoles.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (cmd == null)
                {
                    throw new ExecutionError("The command id you provided (" + input.id + ") does not appear to exist.");
                }

                GamesData game = cmd.Game;
                //Delete any existing votes by this user
                db.ConsolesVotes.RemoveRange(db.ConsolesVotes.Where(x => x.ConsoleId.Equals(cmd.EntryId) && x.Voter.Equals(user.OwnerId)));
                //Set their vote
                var vote = new ConsolesVotes
                {
                    EntryId         = GuidGenerator.GenerateSequentialGuid(),
                    ConsoleId       = cmd.EntryId,
                    Console         = cmd,
                    Voter           = user.OwnerId,
                    VoterNavigation = user,
                    Vote            = input.vote
                };
                db.ConsolesVotes.Add(vote);
                db.SaveChanges();

                //Check if all the votes are in and execute if so
                if (db.ConsolesVotes.Where(x => x.ConsoleId.Equals(cmd.EntryId)).ToArray().Length == game.GamesDataPlayers.Count)
                {
                    //Load the latest game state
                    Game gameobj;
                    try
                    {
                        gameobj = GameFactory.LoadGame(game.GameMeta.Shortcode, game.GamesDataStates.Last().State);
                    }
                    catch (Exception e)
                    {
                        throw new ExecutionError("An error occurred while trying to load the game. Please alert the administrators. The game code said the following: " + e.Message);
                    }

                    var args = new ExecuteCommandInput
                    {
                        Gameobj = gameobj,
                        Gamerec = game,
                        Console = cmd
                    };
                    DBFuncs.ExecuteCommand(db, args);
                    db.Consoles.Remove(cmd);
                }

                db.SaveChanges();
                return(game);
            }
                );
        }
Exemple #6
0
        private void Challenges(MyContext db)
        {
            Field <ChallengeType>(
                "issueChallenge",
                description: "Issue a new challenge",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <NewChallengeInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <NewChallengeDTO>("input");

                var game = db.GamesMeta.SingleOrDefault(x => x.Shortcode.Equals(input.game));
                if (game == null)
                {
                    throw new ExecutionError("Could not find a game with the name " + input.game + ".");
                }
                //Validate numPlayers
                int[] counts = game.PlayerCounts.Split(',').Select(x => int.Parse(x)).ToArray();
                if (!counts.Contains(input.numPlayers))
                {
                    throw new ExecutionError("The number of players you requested (" + input.numPlayers.ToString() + ") is not supported by " + game.Name + ". Only the following are acceptable: " + game.PlayerCounts + ".");
                }
                //Set clock to default if necessary
                if ((input.clockStart == null) || (input.clockStart < 1))
                {
                    input.clockStart = 72;
                }
                if ((input.clockInc == null) || (input.clockInc < 1))
                {
                    input.clockInc = 24;
                }
                if ((input.clockMax == null) || (input.clockMax < 1))
                {
                    input.clockMax = 240;
                }
                //Validate variants
                List <string> vars = game.GamesMetaVariants.Select(x => x.Name).ToList();
                vars.Add("Unrated");
                vars.Add("Hard Time");
                foreach (var variant in input.variants)
                {
                    if (!vars.Contains(variant))
                    {
                        throw new ExecutionError("The variant '" + variant + "' is not supported by " + game.Name + ".");
                    }
                }
                //Validate any challengees (including seat)
                foreach (var player in input.challengees)
                {
                    if (!db.Owners.Any(x => x.OwnerId.Equals(GuidGenerator.HelperStringToBA(player))))
                    {
                        throw new ExecutionError("Could not find player ID " + player + ".");
                    }
                }

                //Build record
                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You do not appear to have a user profile. You must create a profile before playing.");
                }
                byte[] challengeId = GuidGenerator.GenerateSequentialGuid();
                var rec            = new Challenges {
                    ChallengeId = challengeId,
                    GameId      = game.GameId,
                    OwnerId     = user.OwnerId,
                    NumPlayers  = (byte)input.numPlayers,
                    Notes       = input.notes,
                    ClockStart  = (ushort)input.clockStart,
                    ClockInc    = (ushort)input.clockInc,
                    ClockMax    = (ushort)input.clockMax,
                };
                if (input.variants.Length > 0)
                {
                    rec.Variants = String.Join('\n', input.variants);
                }
                //Add issuer
                var issuer = new ChallengesPlayers {
                    EntryId     = GuidGenerator.GenerateSequentialGuid(),
                    ChallengeId = challengeId,
                    OwnerId     = user.OwnerId,
                    Confirmed   = true
                };
                bool seated = false;
                if (input.seat != null)
                {
                    if (input.numPlayers != 2)
                    {
                        throw new ExecutionError("The 'seat' field is only meaningful in two-player games.");
                    }
                    if ((input.seat != 1) && (input.seat != 2))
                    {
                        throw new ExecutionError("The only valid values of 'seat' are '1' and '2'.");
                    }
                    seated      = true;
                    issuer.Seat = (byte)input.seat;
                }
                rec.ChallengesPlayers.Add(issuer);
                foreach (var player in input.challengees)
                {
                    var node = new ChallengesPlayers {
                        EntryId     = GuidGenerator.GenerateSequentialGuid(),
                        ChallengeId = challengeId,
                        OwnerId     = GuidGenerator.HelperStringToBA(player),
                        Confirmed   = false
                    };
                    if (seated)
                    {
                        node.Seat = (byte)((input.seat % 2) + 1);
                    }
                    rec.ChallengesPlayers.Add(node);
                }

                db.Challenges.Add(rec);
                db.SaveChanges();
                return(rec);
            }
                );
            Field <ChallengeType>(
                "respondChallenge",
                description: "Confirm or withdraw from a pending challenge",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <RespondChallengeInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <RespondChallengeDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! You must create a profile before you can play.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The challenge ID you provided is malformed. Please verify and try again.");
                }

                var challenge = db.Challenges.SingleOrDefault(x => x.ChallengeId.Equals(binaryid));
                if (challenge == null)
                {
                    throw new ExecutionError("The challenge '" + input.id + "' does not appear to exist.");
                }

                var player = db.ChallengesPlayers.SingleOrDefault(x => x.ChallengeId.Equals(challenge.ChallengeId) && x.OwnerId.Equals(user.OwnerId));
                //challenge.ChallengesPlayers.SingleOrDefault(x => x.OwnerId.Equals(user.OwnerId));

                //if confirming
                if (input.confirmed)
                {
                    //They were directly invited and so are already in the database
                    if ((player != null) && (!player.Confirmed))
                    {
                        player.Confirmed = true;
                        db.ChallengesPlayers.Update(player);
                    }
                    //otherwise, add them
                    else if (player == null)
                    {
                        var node = new ChallengesPlayers
                        {
                            EntryId     = GuidGenerator.GenerateSequentialGuid(),
                            ChallengeId = GuidGenerator.HelperStringToBA(input.id),
                            OwnerId     = user.OwnerId,
                            Confirmed   = true,
                            Seat        = null
                        };
                        db.ChallengesPlayers.Add(node);
                    }

                    //Check for full challenge and create game if necessary
                    if (challenge.ChallengesPlayers.Where(x => x.Confirmed).Count() == challenge.NumPlayers)
                    {
                        //Prepare the variant and player lists for the game factory
                        string[] variants;
                        if (String.IsNullOrWhiteSpace(challenge.Variants))
                        {
                            variants = new string[0];
                        }
                        else
                        {
                            variants = challenge.Variants.Split('\n');
                        }
                        string[] players;
                        if (challenge.NumPlayers == 2)
                        {
                            var plist  = new List <string>();
                            var parray = challenge.ChallengesPlayers.ToArray();
                            //only one of the players will have a defined seat
                            if ((parray[0].Seat == 1) || (parray[1].Seat == 2))
                            {
                                plist.Add(GuidGenerator.HelperBAToString(parray[0].Owner.PlayerId));
                                plist.Add(GuidGenerator.HelperBAToString(parray[1].Owner.PlayerId));
                            }
                            else if ((parray[0].Seat == 2) || (parray[1].Seat == 1))
                            {
                                plist.Add(GuidGenerator.HelperBAToString(parray[1].Owner.PlayerId));
                                plist.Add(GuidGenerator.HelperBAToString(parray[0].Owner.PlayerId));
                            }
                            else
                            {
                                foreach (var o in challenge.ChallengesPlayers.Select(x => (Owners)x.Owner))
                                {
                                    plist.Add(GuidGenerator.HelperBAToString(o.PlayerId));
                                }
                                plist.Shuffle();
                            }
                            players = plist.ToArray();
                        }
                        else
                        {
                            var plist = new List <string>();
                            foreach (var o in challenge.ChallengesPlayers.Select(x => (Owners)x.Owner))
                            {
                                plist.Add(GuidGenerator.HelperBAToString(o.PlayerId));
                            }
                            plist.Shuffle();
                            players = plist.ToArray();
                        }

                        //Now create the game object. If it fails, then everything aborts.
                        Game gameobj;
                        try
                        {
                            gameobj = GameFactory.CreateGame(challenge.Game.Shortcode, players, variants);
                        }
                        catch (ArgumentException e)
                        {
                            throw new ExecutionError("An error occurred while trying to create the game. Please alert the administrators. The game code said the following: " + e.Message);
                        }
                        //Everything appears to be in order, so now we create the various DB objects and store them
                        var ngdata = new NewGameInput
                        {
                            Gameobj    = gameobj,
                            Shortcode  = challenge.Game.Shortcode,
                            ClockStart = challenge.ClockStart,
                            ClockMax   = challenge.ClockMax,
                            ClockInc   = challenge.ClockInc,
                            Variants   = challenge.Variants
                        };
                        var newgame = DBFuncs.NewGame(db, ngdata);

                        //Delete the challenge
                        db.Challenges.Remove(challenge);
                    }
                }
                //if withdrawing and the player entry already exists
                else if (player != null)
                {
                    //Is it the challenge issuer who's withdrawing?
                    if (player.OwnerId.SequenceEqual(challenge.OwnerId))
                    {
                        db.Challenges.Remove(challenge);
                    }
                    //Or someone else?
                    else
                    {
                        db.ChallengesPlayers.Remove(player);
                    }
                }
                db.SaveChanges();
                return(challenge);
            }
                );
        }
Exemple #7
0
        private void GamesData(MyContext db)
        {
            Field <GamesDataType>(
                "moveGame",
                description: "Submit a move to a game",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <MoveGameInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <MoveGameDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The game ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var game = db.GamesData.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (game == null)
                {
                    throw new ExecutionError("The game id you provided (" + input.id + ") does not appear to exist.");
                }

                if (game.Closed)
                {
                    throw new ExecutionError("This game has ended. No further moves are possible.");
                }

                //Load the latest game state
                Game gameobj;
                try
                {
                    gameobj = GameFactory.LoadGame(game.GameMeta.Shortcode, game.GamesDataStates.Last().State);
                }
                catch (Exception e)
                {
                    throw new ExecutionError("An error occurred while trying to load the game. Please alert the administrators. The game code said the following: " + e.Message);
                }

                //Is the move legal?
                Game newgameobj;
                try
                {
                    newgameobj = gameobj.Move(GuidGenerator.HelperBAToString(user.PlayerId), input.move);
                }
                catch (Exception e)
                {
                    throw new ExecutionError("Your move was not accepted. The game code said the following: " + e.Message);
                }

                //Build game object
                var uginput = new UpdateGameInput
                {
                    Gameobj = newgameobj,
                    Gamerec = game,
                    Mover   = user.OwnerId
                };
                DBFuncs.UpdateGame(db, uginput);
                db.SaveChanges();

                return(game);
            }
                );
            Field <GamesDataPreviewType>(
                "moveGamePreview",
                description: "Preview a move to a game",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <MoveGameInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <MoveGameDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The game ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var game = db.GamesData.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (game == null)
                {
                    throw new ExecutionError("The game id you provided (" + input.id + ") does not appear to exist.");
                }

                if (game.Closed)
                {
                    throw new ExecutionError("This game has ended. No further moves are possible.");
                }

                //Load the latest game state
                Game gameobj;
                try
                {
                    gameobj = GameFactory.LoadGame(game.GameMeta.Shortcode, game.GamesDataStates.Last().State);
                }
                catch (Exception e)
                {
                    throw new ExecutionError("An error occurred while trying to load the game. Please alert the administrators. The game code said the following: " + e.Message);
                }

                //Is the move legal?
                Game newgameobj;
                try
                {
                    newgameobj = gameobj.Move(GuidGenerator.HelperBAToString(user.PlayerId), input.move);
                }
                catch (Exception e)
                {
                    throw new ExecutionError("Your move was not accepted. The game code said the following: " + e.Message);
                }

                return(newgameobj);
            }
                );
            Field <GamesDataChatType>(
                "newChat",
                description: "Post a new chat message to a game",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <NewChatInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <NewChatDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can chat in games.");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The game ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var game = db.GamesData.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (game == null)
                {
                    throw new ExecutionError("The game id you provided (" + input.id + ") does not appear to exist.");
                }

                var rec = new GamesDataChats
                {
                    ChatId  = GuidGenerator.GenerateSequentialGuid(),
                    GameId  = binaryid,
                    OwnerId = user.OwnerId,
                    Message = input.message
                };
                db.GamesDataChats.Add(rec);
                db.SaveChanges();
                return(rec);
            }
                );
            Field <GamesDataType>(
                "resignGame",
                description: "Resign from a game in progress",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <ResignGameInputType> > {
                Name = "input"
            }
                    ),
                resolve: _ => {
                var context = (UserContext)_.UserContext;
                var input   = _.GetArgument <ResignGameDTO>("input");

                var user = db.Owners.SingleOrDefault(x => x.CognitoId.Equals(context.cognitoId));
                if (user == null)
                {
                    throw new ExecutionError("You don't appear to have a user account! Only registered users can play.");
                }

                if (!input.confirmed)
                {
                    throw new ExecutionError("You must set `confirmed` to `true` to proceed. This action cannot be undone!");
                }

                byte[] binaryid;
                try
                {
                    binaryid = GuidGenerator.HelperStringToBA(input.id);
                }
                catch
                {
                    throw new ExecutionError("The game ID you provided is malformed. Please verify and try again.");
                }

                //Does this game id exist?
                var game = db.GamesData.SingleOrDefault(x => x.EntryId.Equals(binaryid));
                if (game == null)
                {
                    throw new ExecutionError("The game id you provided (" + input.id + ") does not appear to exist.");
                }

                if (game.Closed)
                {
                    throw new ExecutionError("This game has ended. No further moves are possible.");
                }

                //Load the latest game state
                Game gameobj;
                try
                {
                    gameobj = GameFactory.LoadGame(game.GameMeta.Shortcode, game.GamesDataStates.Last().State);
                }
                catch (Exception e)
                {
                    throw new ExecutionError("An error occurred while trying to load the game. Please alert the administrators. The game code said the following: " + e.Message);
                }

                //Is the move legal?
                Game newgameobj;
                try
                {
                    newgameobj = gameobj.Resign(GuidGenerator.HelperBAToString(user.PlayerId));
                }
                catch (Exception e)
                {
                    throw new ExecutionError("The resignation failed. The game code said the following: " + e.Message);
                }

                //Build game object
                var uginput = new UpdateGameInput
                {
                    Gameobj = newgameobj,
                    Gamerec = game,
                    Mover   = user.OwnerId
                };
                DBFuncs.UpdateGame(db, uginput);
                db.SaveChanges();

                return(game);
            }
                );
        }