//        private EigoTestLabelItem _answerBox;
 /*
 public event PropertyChangedEventHandler PropertyChanged;
 private void NotifyPropertyChanged(string propertyName)
 {
     if (null == PropertyChanged) return;
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 }
 */
 public ShomonStateTyping(EPuzzleWindow window, Shomon shomon)
     : base(window, shomon)
 {
     // Back Space
     Action1 += (sender, e) =>
     {
         var answerBox = GetAnswerBox();
         if ("" == answerBox.Text) return;
         answerBox.Text = answerBox.Text.Substring(0, answerBox.Text.Length - 1);
     };
     UpdateItemsToBeDrawn();
 }
		public ShomonStateHard(EPuzzleWindow window, Shomon shomon) : base(window, shomon)
		{
			((ObservableCollection<EigoTestDrawingObject>)_kaitouBox.Items).CollectionChanged += (sender, e) => 
			{
				if (e.Action != NotifyCollectionChangedAction.Add) return;
				foreach (var wordCard in e.NewItems.OfType<WordCard>())
				{
					wordCard.LettersThatAreShown = LettersThatAreShown.All;
				}
			};
			window.PropertyChanged += (sender, e) => 
			{
				if ("InputDevice" != e.PropertyName) return;
				foreach (var wordCard in _sentakuBox.Items.OfType<WordCard>())
				{
					if (object.ReferenceEquals(wordCard, CurrentItem)) continue;
					HideLettersOnCard(wordCard);
				}
				Invalidate();
			};
			_sentakuBox.AnyPropertyOfAnyChildChanged += (sender, e) => 
			{
				if ("IsClickable" != e.PropertyName) return;
				foreach (var wordCard in _sentakuBox.Items.OfType<WordCard>())
				{
					if (wordCard.IsClickable)
					{
						HideLettersOnCard(wordCard);
					}
					else
					{
						wordCard.LettersThatAreShown = LettersThatAreShown.All;
					}
				}
			};
			
			SetNullToCurrentItemWhenStoredItemBecomeInvalid = true;
		}
        public static Shomon CreateShomon(EmpElement shomonElement)
        {
            var shomon = new Shomon()
            {
                Id = shomonElement.GetValue("id"),
                Mondaibun = shomonElement.GetValue("mon"),
            };
            var seikaiTexts = shomonElement.GetValues("sei").Select(x => 余分な空白を取り除く(x));
            if (seikaiTexts.Any(x => string.IsNullOrWhiteSpace(x))) throw new EmpException("seiが指定されていません。: id :" + shomon.Id);

            var display = shomonElement.GetValue("display");
            if (!string.IsNullOrWhiteSpace(display))
            {
                shomon.LettersThatAreDisplayedOnCard = (LettersThatAreDisplayedOnCard)Enum.Parse(typeof(LettersThatAreDisplayedOnCard), display, true);
            }

            // 正解項目の設定
            foreach (var seikaiText in seikaiTexts.Select(text => MondaiWord.分割指示記号を取り除く(text)))
            {
                shomon.CorrectAnswers.Add(new CorrectAnswer(seikaiText));
            }

            var wordTexts = shomonElement.GetValues("word").Select(x => 余分な空白を取り除く(x));
            shomon.MondaiWords = wordTexts.Select(s => new MondaiWord(s)).ToArray();

            // word項目で正解が組み立てられない場合は、正解項目を分割処理してword項目を作成する。
            var result = shomon.正解探索();
            if (result.Any(array => null == array))
            {
                var otoriTexts = shomonElement.GetValues("otori").Concat(shomonElement.GetValues("otr")).Select(x => 余分な空白を取り除く(x));
                var texts = seikaiTexts.Concat(otoriTexts);
                shomon.MondaiWords = MondaiWord.Split2(texts).Concat(shomon.MondaiWords).ToArray();
            }
            /*
            #if DEBUG
            if (Environment.StackTrace.Contains("括弧とクォーテーションに対応させる"))
            {
                foreach (var mondaiWord in shomon.MondaiWords)
                {
                    Console.WriteLine(mondaiWord);
                }
            }
            #endif // DEBUG
            */
            if (shomon.正解探索().Any(array => null == array))
            {
                throw new ApplicationException(string.Format("正解の組み合わせが見つかりません。: id: {0}", shomon.Id));
            }
            return shomon;
        }
        public static EmpElement Create(Shomon shomon)
        {
            if (null == shomon) throw new ArgumentNullException();
            var shomonElement = new EmpElement("shomon");
            shomonElement.Items.Add(new EmpElement("id", shomon.Id));
            shomonElement.Items.Add(new EmpElement("mon", shomon.Mondaibun));

            var list = new List<MondaiWord>(shomon.MondaiWords);
            shomonElement.Items.AddRange(shomon.CorrectAnswers.Select(seikai =>
            {
                var mondaiWords = Shomon.正解探索(seikai, shomon.MondaiWords);
                foreach (var w in mondaiWords)
                {
                    var index = list.IndexOf(w);
                    if (-1 == index)
                    {
                        continue;
                    }
                    list.RemoveAt(index);
                }
                var result = MondaiWord.相互変換可能なテキスト形式を取得する(mondaiWords);
                return new EmpElement("sei", result);
            }));
            shomonElement.Items.AddRange(list.Select(mondaiWord => new EmpElement("word", mondaiWord.Text.Replace(" ", "+"))));
            return shomonElement;
        }
 public ShomonStateBase CreateShomonState(Shomon shomon)
 {
     if (ShomonInputMethod.Typing == shomon.InputMethod)
     {
         return new ShomonStateTyping(this, shomon);
     }
     else
     {
         switch (EPuzzleData.CurrentUserInfo.Difficulty)
         {
             case Difficulty.Normal :
             {
                 return new ShomonState(this, shomon);
             }
             case Difficulty.Hard :
             {
                 if (LettersThatAreDisplayedOnCard.All == shomon.LettersThatAreDisplayedOnCard)
                 {
                     return new ShomonState(this, shomon);
                 }
                 else
                 {
                     return new ShomonStateHard(this, shomon);
                 }
             }
             default :
             {
                 throw new ApplicationException("never reach here.");
             }
         }
     }
 }
        public ShomonStateBase(EPuzzleWindow window, Shomon shomon)
            : base(window)
        {
            if (null == shomon) throw new ArgumentNullException();
            Shomon = shomon;
            _shomonStateHelper = new ShomonStateHelper(this);

            NeedToPlaySounds += (sender, e) =>
            {
            /*
                foreach (var sound in e.Sounds)
                {
                    Window.EPuzzleData.CurrentUserInfo.SoundPlayer.Play(sound.FileName);
                }
                */
                Window.EPuzzleData.CurrentUserInfo.SoundPlayer.Play(e.Sounds.Select(x => x.FileName), true);
            };
            Action0 += (sender, e) =>
            {
                if (null == CurrentItem) return;
                switch (CurrentItem.Name)
                {
                    case "info" :
                    {
                        _shomonStateHelper.ShowInformation();
                        break;
                    }
                    case "back" :
                    {
                        BackToChumonMenu();
                        break;
                    }
                    case "hajimekara" :
                    {
                        WindowState.Chumonを開始する((Chumon)Shomon.Parent, Window.WindowStateWhichHasStartedChumon);
                        break;
                    }
                    case "pause" :
                    {
                        Pause();
                        break;
                    }
                    case "showCorrectAnswer" :
                    {
                        _userHasSeenCorrectAnswer = true;
                        var text = string.Join(Environment.NewLine, shomon.CorrectAnswers.Select(x => string.Format(@"{0}", x.Text)).ToArray());
                        Window.State = new InformationState(Window, this, text);
                        break;
                    }
                    case "playSound" :
                    {
                        PlaySounds();
                        break;
                    }
                }
            };
            Action3 += (sender, e) =>
            {
                Pause();
            };
            Action4 += (sender, e) =>
            {
                PlaySounds();
            };
        }
 protected abstract TimeSpan GetTimeLimit(Shomon shomon);
 protected override TimeSpan GetTimeLimit(Shomon shomon)
 {
     if (ShomonInputMethod.Card == shomon.InputMethod)
     {
         var mondaiWordsArray = shomon.正解探索();
         if (mondaiWordsArray.Any(x => null == x))
         {
             var message = string.Format("正解の組み合わせが見つかりません: id: " + shomon.Id);
             throw new MondaiDocumentException(message);
         }
         try
         {
             var a = mondaiWordsArray.Select(x => x.Count()).Average();
             var b = CountLetters(shomon.Mondaibun) * 0.125d;
             return TimeSpan.FromSeconds(Math.Max(a, b));
         }
         catch
         {
             Trace.WriteLine("id: " + shomon.Id);
             throw;
         }
     }
     else if (ShomonInputMethod.Typing == shomon.InputMethod)
     {
         var average = shomon.CorrectAnswers.Select(x => x.Text.Count()).Average();
         return TimeSpan.FromMinutes(average / (KeystrokesPerMinute / 2d));
     }
     else
     {
         throw new ApplicationException("never reach here.");
     }
 }
        public void Xmlとの相互変換テストでピリオドと前の単語が結合されていない不具合()
        {
            using (var tempFile1 = new TempFile())
            using (var tempFile2 = new TempFile())
            {
                FileUtility.Save(tempFile1.Value, _test91);
                var mondaiDocument = MondaiDocument.Load(tempFile1.Value);
                Assert.AreEqual("mondaiDocument1", mondaiDocument.Id);

                var emp = EmpElement.Create(mondaiDocument);
                var shomonElement = emp.GetAllItems().First(x => "shomon" == x.Name);
                Assert.AreEqual("3-2-1", shomonElement.GetValue("id"));
                Assert.AreEqual("[英訳] これはボールです。", shomonElement.GetValue("mon"));
                Assert.AreEqual("This+is a+ball+.", shomonElement.GetValue("sei"));

                CollectionAssert.IsEmpty(shomonElement.GetValues("word").Select(s => new MondaiWord(s)));

                {
                    var seikaiTexts = shomonElement.GetValues("sei");

                    CollectionAssert.AreEqual(new []
                    {
                        "This+is a+ball+.",
                    }, seikaiTexts);

                    CollectionAssert.AreEqual(new []
                    {
                        new MondaiWord("This is"),
                        new MondaiWord("a ball."),

                    }, MondaiWord.Split2(seikaiTexts));
                }
                {
                    var shomon = new Shomon();
                    shomon.CorrectAnswers.Add(new CorrectAnswer("This is a ball."));

                    shomon.MondaiWords = new []
                    {
                        new MondaiWord("This is"),
                        new MondaiWord("a ball."),
                    };
                    var result = shomon.正解探索();
                    Assert.AreEqual(1, result.Count());

                    CollectionAssert.AreEqual
                    (
                        shomon.MondaiWords,
                        result[0]
                    );
                }
                {
                    var shomon = EmpElement.CreateShomon(shomonElement);
                    Assert.AreEqual("3-2-1", shomon.Id);

                    mondaiDocument = emp.GetMondaiDocument();
                    mondaiDocument.Save(tempFile2.Value);
            //				TestUtility.ShowFile(tempFile2.Name);
            //				Assert.AreEqual(FileUtility.Load(tempFile1.Name), FileUtility.Load(tempFile2.Name));
                    FileAssert.AreEqual(tempFile1.Value, tempFile2.Value);
                }
            }
        }
 public ShomonResult(Shomon shomon, bool isPerfect)
 {
     Shomon = shomon;
     IsPerfect = isPerfect;
 }