コード例 #1
0
        /// <summary>
        ///     Uses an enumerable list of frame data to create a list of FrameViewModels
        /// </summary>
        /// <param name="framesData"></param>
        /// <returns></returns>
        public static IEnumerable <FrameViewModel> CreateFrameViewModels(IEnumerable <FrameDataModel> framesData)
        {
            // Prevent duplicate enumeration.
            List <FrameDataModel> frameDataModels = framesData.ToList();
            List <FrameViewModel> output          = new List <FrameViewModel>();

            for (Int32 i = 0; i < frameDataModels.Count; i++)
            {
                FrameDataModel thisFrame     = frameDataModels.ElementAt(i);
                FrameDataModel nextFrame     = frameDataModels.ElementAtOrDefault(i + 1);
                FrameDataModel nextNextFrame = frameDataModels.ElementAtOrDefault(i + 2);

                FrameViewModel newView = new FrameViewModel
                {
                    Throws      = GetThrowCharacters(thisFrame),
                    FrameNumber = frameDataModels.IndexOf(thisFrame) + 1
                };

                if (CanScore(thisFrame, nextFrame, nextNextFrame))
                {
                    Int32 score = (thisFrame.FirstThrow ?? 0) + (thisFrame.SecondThrow ?? 0) +
                                  (thisFrame.ThirdThrow ?? 0);

                    // If this is a spare, add the first throw of next frame.
                    // Bonus points only count for non-final frames.
                    if (thisFrame.FrameNumber < 10 && thisFrame.IsSpare)
                    {
                        score += nextFrame?.FirstThrow ?? 0;
                    }

                    // If this is a strike...
                    if (thisFrame.FrameNumber < 10 && thisFrame.IsStrike)
                    {
                        // For frame 1-8, next frame being strikes means add 10 to next-next's first throw.
                        if (thisFrame.FrameNumber < 9 && nextFrame != null && nextFrame.IsStrike)
                        {
                            score += 10 + (nextNextFrame?.FirstThrow ?? 0);
                        }

                        // Otherwise, use next's first and second throw.
                        else
                        {
                            score += (nextFrame?.FirstThrow ?? 0) + (nextFrame?.SecondThrow ?? 0);
                        }
                    }

                    newView.Score = score;
                }

                output.Add(newView);
            }

            return(output);
        }
コード例 #2
0
        /// <summary>
        /// Creates Frame Data List from FrameDataModel class.
        /// </summary>
        /// <returns>String list of Frame data model constants</returns>
        public List <string> FrameDataList()
        {
            FrameDataModel fdm = new FrameDataModel();

            List <string> fdmList = new List <string>
            {
                fdm.LargeAdvantageConst,
                fdm.SlightAdvantageConst,
                fdm.NeutralEvenConst,
                fdm.SlightDisadvantageConst,
                fdm.LargeDisadvantageConst
            };

            return(fdmList);
        }
コード例 #3
0
        /// <summary>
        ///     Gets the list of throw characters for this specific Frame.
        /// </summary>
        /// <param name="f">The frame to generate characters for.</param>
        /// <returns></returns>
        private static List <Char> GetThrowCharacters(FrameDataModel f)
        {
            List <char> throwCharacters = new List <Char>();

            if (f.FirstThrow.HasValue)
            {
                throwCharacters.Add(f.FirstThrow == 10 ? 'X' : f.FirstThrow.ToString()[0]);
            }

            if (f.SecondThrow.HasValue)
            {
                if (f.SecondThrow == 10)
                {
                    throwCharacters.Add('X');
                }
                else if (f.FirstThrow + f.SecondThrow == 10)
                {
                    throwCharacters.Add('/');
                }
                else
                {
                    throwCharacters.Add(f.SecondThrow.ToString()[0]);
                }
                ;
            }

            if (f.ThirdThrow.HasValue)
            {
                if (f.ThirdThrow == 10)
                {
                    throwCharacters.Add('X');
                }
                // If we weren't already a Spare, then mark Spare.
                else if (f.FirstThrow + f.SecondThrow != 10 && f.ThirdThrow + f.SecondThrow == 10)
                {
                    throwCharacters.Add('/');
                }
                else
                {
                    throwCharacters.Add(f.SecondThrow.ToString()[0]);
                }
                ;
            }

            return(throwCharacters);
        }
コード例 #4
0
        public async Task <IActionResult> CreateGame([FromBody] CreateGameRequest request)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            PlayerDataModel player = await _context.Players.FindAsync(request.PlayerId);

            if (player == null)
            {
                return(BadRequest($"No player with Id {request.PlayerId} exists."));
            }

            // Create new Game entry in DB.
            GameDataModel gameDataModel = new GameDataModel
            {
                Player = player, CreationDate = DateTime.Now, Frames = new List <FrameDataModel>()
            };

            _context.Games.Add(gameDataModel);
            await _context.SaveChangesAsync();

            // Create first Frame entry for the new Game.
            FrameDataModel firstFrameDataModel = new FrameDataModel
            {
                CreationDate = DateTime.Now,
                GameId       = gameDataModel.Id,
                FrameNumber  = 1
            };

            _context.Frames.Add(firstFrameDataModel);
            await _context.SaveChangesAsync();

            // Update new Game entry with the new Frame and throw.
            gameDataModel.Frames.Add(firstFrameDataModel);
            gameDataModel.CurrentFrameId = gameDataModel.Frames.First().Id;
            gameDataModel.CurrentThrow   = 1;
            await _context.SaveChangesAsync();

            return(CreatedAtAction("GetGame", new { gameId = gameDataModel.Id },
                                   ViewModelFactory.CreateGameViewModel(gameDataModel)));
        }
コード例 #5
0
        /// <summary>
        ///     Determine whether or not this Frame (based on the next two frames) can be scored.
        /// </summary>
        /// <param name="thisFrame"></param>
        /// <param name="nextFrame"></param>
        /// <param name="nextNextFrame"></param>
        /// <returns></returns>
        private static bool CanScore(FrameDataModel thisFrame, FrameDataModel nextFrame, FrameDataModel nextNextFrame)
        {
            // If we are looking at a spare, we need the next Frame to have a value in order to score.
            if (thisFrame.IsSpare)
            {
                // Frame 10 will only depend on this frame's third throw.
                if (thisFrame.FrameNumber == 10)
                {
                    return(thisFrame?.ThirdThrow != null);
                }

                // Otherwise, we check for next frame's first throw.
                return(nextFrame?.FirstThrow != null);
            }

            // If we are looking at a strike...
            if (thisFrame.IsStrike)
            {
                // Frame 10 will only ever be dependent on this frame.
                if (thisFrame.FrameNumber == 10)
                {
                    return(thisFrame?.SecondThrow != null && thisFrame?.ThirdThrow != null);
                }

                // Frame 9 will only ever be dependent on next frame.
                if (thisFrame.FrameNumber == 9)
                {
                    return(nextFrame?.FirstThrow != null && nextFrame.SecondThrow != null);
                }

                // If next frame is a strike, check if next-next has a value.
                if (nextFrame != null && nextFrame.IsStrike)
                {
                    return(nextNextFrame?.FirstThrow != null);
                }

                // Otherwise check that nextFrame has a Second Throw.
                return(nextFrame?.SecondThrow != null);
            }

            // Otherwise, we can score when the frame is finished.
            return(thisFrame.IsFinished);
        }
コード例 #6
0
        public async Task <IActionResult> AddThrow([FromRoute] Guid gameId, [FromBody] CreateThrowRequest request)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (request.PinsDropped > 10)
            {
                return(BadRequest("A maximum of 10 pins may be dropped."));
            }

            GameDataModel thisGame = await _context.Games
                                     .Include(g => g.Player)
                                     .Include(g => g.Frames)
                                     .SingleOrDefaultAsync(g => g.Id == gameId);

            if (thisGame == null)
            {
                return(BadRequest($"No game with Id {gameId} exists."));
            }
            if (thisGame.IsFinished)
            {
                return(BadRequest("This game is complete, no more throws allowed."));
            }

            // Set current throw to the value we just received.
            FrameDataModel currentFrame = await _context.Frames.SingleAsync(f => f.Id == thisGame.CurrentFrameId);

            // First Throw
            if (thisGame.CurrentThrow == 1)
            {
                currentFrame.FirstThrow = request.PinsDropped;
                if (request.PinsDropped == 10)
                {
                    currentFrame.IsStrike   = true;
                    currentFrame.IsFinished = true;
                }
            }

            // Second Throw
            else if (thisGame.CurrentThrow == 2)
            {
                currentFrame.SecondThrow = request.PinsDropped;
                // Mark if Spare.
                currentFrame.IsSpare = currentFrame.FirstThrow + request.PinsDropped == 10;

                // Non-Final Frames are finished at this point, and can score if not a strike or spare.
                if (currentFrame.FrameNumber < 10)
                {
                    currentFrame.IsFinished = true;
                }
                // Final Frame.
                else
                {
                    currentFrame.IsFinished = !(currentFrame.IsStrike || currentFrame.IsSpare);
                    thisGame.IsFinished     = !(currentFrame.IsStrike || currentFrame.IsSpare);
                }
            }

            // Third Throw (Final Frame Only)
            else if (thisGame.CurrentThrow == 3)
            {
                currentFrame.ThirdThrow = request.PinsDropped;
                currentFrame.IsFinished = true;
                thisGame.IsFinished     = true;
            }


            // If we need a new frame, create one and set it to throw 1 of that new frame.
            Boolean needsNewFrame = currentFrame.IsFinished && currentFrame.FrameNumber < 10;

            if (needsNewFrame)
            {
                FrameDataModel newFrame = new FrameDataModel
                {
                    CreationDate = DateTime.Now,
                    GameId       = thisGame.Id,
                    FrameNumber  = currentFrame.FrameNumber + 1
                };
                _context.Frames.Add(newFrame);
                await _context.SaveChangesAsync();

                thisGame.Frames.Add(newFrame);
                thisGame.CurrentFrameId = newFrame.Id;
                thisGame.CurrentThrow   = 1;
            }
            else if (!thisGame.IsFinished)
            {
                thisGame.CurrentThrow++;
            }

            await _context.SaveChangesAsync();


            return(Ok(ViewModelFactory.CreateGameViewModel(thisGame)));
        }
コード例 #7
0
        /// <summary>
        ///     Generates in-memory mock data for FrameDataModels.
        /// </summary>
        /// <returns></returns>
        private List <FrameDataModel> MockFrameData(Guid gameId)
        {
            FrameDataModel Frame1 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch,
                GameId       = gameId,
                FrameNumber  = 1,
                FirstThrow   = 5,
                SecondThrow  = 5,
                IsSpare      = true,
                IsFinished   = true
            };

            FrameDataModel Frame2 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch.AddMinutes(1),
                GameId       = gameId,
                FrameNumber  = 2,
                FirstThrow   = 10,
                IsStrike     = true,
                IsFinished   = true
            };

            FrameDataModel Frame3 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch.AddMinutes(2),
                GameId       = gameId,
                FrameNumber  = 3,
                FirstThrow   = 1,
                SecondThrow  = 8,
                IsFinished   = true
            };

            FrameDataModel Frame4 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch.AddMinutes(1),
                GameId       = gameId,
                FrameNumber  = 4,
                FirstThrow   = 10,
                IsStrike     = true,
                IsFinished   = true
            };

            FrameDataModel Frame5 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch.AddMinutes(1),
                GameId       = gameId,
                FrameNumber  = 5,
                FirstThrow   = 10,
                IsStrike     = true,
                IsFinished   = true
            };

            FrameDataModel Frame6 = new FrameDataModel
            {
                Id           = Guid.NewGuid(),
                CreationDate = DateTime.UnixEpoch.AddMinutes(2),
                GameId       = gameId,
                FrameNumber  = 6,
                FirstThrow   = 6
            };

            return(new List <FrameDataModel> {
                Frame1, Frame2, Frame3, Frame4, Frame5, Frame6
            });
        }