public PlayerFeedback GeneratePlayerFeedback(IOverallAnalysisResult overallAnalysisResult)
        {
            var resultAnalyser = new ResultAnalyser();
            var stateCode      = resultAnalyser.GetStateCode(overallAnalysisResult);
            var doNotShowImplementedTooMuchMessage = GetDoNotShowImplementedTooMuchMessage(overallAnalysisResult);
            var progress  = GetProgressMessage(stateCode, overallAnalysisResult, resultAnalyser, doNotShowImplementedTooMuchMessage);
            var debugInfo = GetDebugInfo(overallAnalysisResult);
            var hint      = GetHint(overallAnalysisResult, stateCode, doNotShowImplementedTooMuchMessage);

            return
                (new PlayerFeedback
            {
                Progress = progress,
                Hint = hint,
                KataCompleted = IsKataCompleted(overallAnalysisResult),
                KataStateCode = stateCode,
                //StepShouldDo = testMethodMeta.StepShoudlDo,
                //EdgeCaseHint = testMethodMeta.EdgeCaseHint,
                //SuggestedTestName = testMethodMeta.SuggestedTestName,
                DebugInfo = debugInfo,
                PlayerTestState = overallAnalysisResult.PlayerTestsPlayerImplementationRunResult.ToString()
            });
        }
        private string GetInvalidTestHint(IOverallAnalysisResult overallAnalysisResult, ResultAnalyser resultAnalyser)
        {
            var implementationLevel         = overallAnalysisResult.PlayerImplementationRunResult.Level;
            var playerTestsRunResult        = overallAnalysisResult.PlayerTestsRunResult;
            var minLevelEdgeCasesNotCovered = resultAnalyser.GetMinLevelEdgeCasesNotCovered(playerTestsRunResult);

            if (minLevelEdgeCasesNotCovered != -1 && minLevelEdgeCasesNotCovered <= implementationLevel)
            {
                return(string.Empty);
            }
            var testMethod = overallAnalysisResult.GoldenTestMethods.FirstOrDefault(method => method.Level == implementationLevel + 1);

            if (testMethod == null)
            {
                return(string.Empty);
            }
            var invalidTestHintAttributes = testMethod.KataAnnotations.OfType <InvalidTestHintAttribute>();
            var invalidTestHintAttribute  = invalidTestHintAttributes.FirstOrDefault();

            return(invalidTestHintAttribute == null ? string.Empty : invalidTestHintAttribute.InvalidTestHint);
        }
        private string GetProgressMessage(string stateCode, IOverallAnalysisResult overallAnalysisResult, ResultAnalyser resultAnalyser, bool doNotShowImplementedTooMuchMessage)
        {
            string progress;

            switch (stateCode)
            {
            case "HTC":
                progress = "Use of attribute [TestCase] is not permitted";
                break;

            case "HEE":
                progress = "Use of attribute [ExpectedException] is not permitted";
                break;

            case "[G] T=I (I=1)":
                progress = "Great, Katarai has noticed you’ve built the solution, and your kata timer has started! Please go ahead and write the first test.";
                break;

            case "[G] T=I (I=Last)":
            case "[G] T=I (EC=EI) (I=Last)":
            case "[G] T=I (TE=EC) (EC=EI) (I=Last)":
                progress = "Congratulations! You have successfully completed the Kata." +
                           Environment.NewLine + "Remember to review your code to check for any refactorings that could be done.";
                break;

            case "[R] T=I+1":
            case "[R] T=I+1 (I=1)":
            case "[R] T=I+1 (EC=EI)":
            case "[R] T=I (EC=EI)":
            case "[R] T=I (EC>EI)":
            case "[R] T=I (EC>EI) (I=Last)":
            //case "[R] T=I+1 (EC=EI) (I=1)": to test
            case "[R] T=I+1 (EC<EI)":
            case "[R] T=I+1 (EI=0)":
            case "[R] T=I":
            case "[R] T=I (TE>EC)":
            case "[R] T=I+1 (TE=EC) (EC=EI)":
            case "[R] T=I (TE=EC) (EC=EI)":
            case "[R] T=I (EI=0)":
            case "[R] T=I (TE=EC) (EC=EI) (I=Last)":
                progress = "You’ve written a valid failing test; please continue to write the implementation that will get this test to pass.";
                break;

            case "[G] T=I+1 (I=1)":
            case "[G] T=I+1":
            case "[G] T=I+1 (EI=0)":
            case "[G] T=I+1 (TE=EC) (EC=EI)":
            case "[G] T>I+1":
                progress = "Success! Your test is passing. To improve your implementation to be more generic, write another test for the same scenario with different values and then go on to get that test to pass too.";
                break;

            case "[R] T>I+1 (I=1)":
                progress = "You wrote a valid test, but there is a simpler first test that could be written. Remember that we are looking for the simplest test at all times to drive the code in tiny increments."
                           + Environment.NewLine + "For a bigger discussion of this, see Uncle Bob’s Three Rules of TDD" + Environment.NewLine + "(http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd)";
                break;

            case "[R] T>I+1":
                progress = "You wrote a valid test, but there is a simpler test that could be written first. Remember that we are looking for the next simplest test at all times to drive the code in tiny increments."
                           + Environment.NewLine + "For a bigger discussion of this, see Uncle Bob’s Three Rules of TDD" + Environment.NewLine + "(http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd)";
                break;

            case "[R] T=I+1 (TE>EC)":
            case "[R] T>I+1 (TE>EC)":
                progress = "You must cover all edge cases before moving to the next step in the kata - can you find the edge cases that should be tested?";
                break;

            case "[G] T=I":
            case "[G] T=I (EC=EI)":
            case "[G] T=I (TE=EC) (EC=EI)":
                progress = GetNextTestProgress(overallAnalysisResult);
                break;

            case "[G] T<I":
            case "[G] T<I (I=Last)":
                if (doNotShowImplementedTooMuchMessage)
                {
                    progress = GetNextTestProgress(overallAnalysisResult);
                }
                else
                {
                    progress = "The implementation you wrote could be simpler than it is – your test is passing but there is a simpler solution. Remember that you are trying to write the simplest/least possible production code to get your tests to pass."
                               + Environment.NewLine + "For a bigger discussion of this, see Uncle Bob’s Three Rules of TDD" + Environment.NewLine + "(http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd)";
                }
                break;

            case "[G] T=I (EC<EI)":
            case "[G] T=I (EC<EI) (I=Last)":
            case "[G] T=I+1 (EC<EI)":
            case "[G] T=I+1 (EC<EI) (I=1)":
            case "[G] T=I+1 (TE>EC)":
            case "[G] T>I+1 (TE>EC)":
            case "[G] T=I (TE>EC)":
            case "[G] T=I (TE>EC) (I=Last)":
                progress = "Success! Your test is passing. It is good practice to ensure that you are testing edge cases – can you find another edge case that should be tested in this same scenario?";
                break;

            case "[R] T=I+1 (EC>EI)":
            case "[R] T=I+1 (EC>EI) (I=1)":
                progress = "You’ve written a valid failing test; please continue to write the implementation that will get this test to pass.";
                break;

            case "[G] T=I+1 (EC>EI)":
            case "[G] T=I+1 (EC>EI) (I=1)":
                progress = "Success! Your test is passing. To improve your implementation to be more generic, write another test for the same scenario with different values and then go on to get that test to pass too.";
                break;

            case "[G] T=I+1 (EC=EI)":
                //case "T=I+1 (EC=EI) (I=Last)": test this
                progress = "Success! Your test is passing but it looks like you missed an edge case."
                           + Environment.NewLine + "Can you find the edge cases that should be tested?";
                break;

            case "[R] T=-1":
            case "[R] T=-1 (I=1)":
            case "[R] T=-1 (I=Last)":
                progress = "Katarai senses that there is an issue with your failing test – please correct the test before you try to get it passing." + Environment.NewLine +
                           GetInvalidTestHint(overallAnalysisResult, resultAnalyser);
                break;

            case "[G] T=-1":
            case "[G] T=-1 (I=1)":
            case "[G] T=-1 (I=Last)":
                progress = "Katarai senses that there is an issue with your passing test – please correct the test before moving on.";
                break;

            default:
                progress = "Unknown kata state";
                break;
            }
            return(progress);
        }