From 5f69fa5c8142e847a81a1e555537a2fc38a4ea3a Mon Sep 17 00:00:00 2001 From: VladimirKhil Date: Sun, 12 Nov 2023 13:30:42 +0100 Subject: [PATCH] https://github.com/VladimirKhil/SI/issues/152 Answer options support (final part) --- src/Common/SIUI/Table.xaml | 4 ++ src/SICore/SICore/Clients/Game/Game.cs | 36 ++++++++--- src/SICore/SICore/Clients/Game/GameLogic.cs | 63 ++++++++++++++++++- .../SICore/Clients/Game/QuestionPlayState.cs | 6 ++ .../SICore/Clients/Player/PlayerHumanLogic.cs | 10 ++- .../SICore/Clients/Viewer/IViewerLogic.cs | 2 + src/SICore/SICore/Clients/Viewer/Viewer.cs | 4 ++ .../SICore/Clients/Viewer/ViewerHumanLogic.cs | 27 +++++++- src/SICore/SICore/Messages.cs | 5 ++ 9 files changed, 144 insertions(+), 13 deletions(-) diff --git a/src/Common/SIUI/Table.xaml b/src/Common/SIUI/Table.xaml index 557fd4d8..0bcd8230 100644 --- a/src/Common/SIUI/Table.xaml +++ b/src/Common/SIUI/Table.xaml @@ -275,6 +275,10 @@ + + + + diff --git a/src/SICore/SICore/Clients/Game/Game.cs b/src/SICore/SICore/Clients/Game/Game.cs index 6d71fb96..533e8c10 100644 --- a/src/SICore/SICore/Clients/Game/Game.cs +++ b/src/SICore/SICore/Clients/Game/Game.cs @@ -1983,13 +1983,31 @@ private void OnAnswer(Message message, string[] args) { if (args[1] == MessageParams.Answer_Right) { - ClientData.Answerer.Answer = args[2].Replace(Constants.AnswerPlaceholder, ClientData.Question.Right.FirstOrDefault() ?? "(...)"); - ClientData.Answerer.AnswerIsWrong = false; + if (ClientData.QuestionPlayState.AnswerOptions != null) + { + var rightLabel = ClientData.Question.Right.FirstOrDefault(); + var rightIndex = Array.FindIndex(ClientData.QuestionPlayState.AnswerOptions, o => o.Label == rightLabel); + + ClientData.Answerer.Answer = rightIndex.ToString(); + } + else + { + ClientData.Answerer.Answer = args[2].Replace(Constants.AnswerPlaceholder, ClientData.Question.Right.FirstOrDefault() ?? "(...)").GrowFirstLetter(); + ClientData.Answerer.AnswerIsWrong = false; + } } - else + else if (ClientData.QuestionPlayState.AnswerOptions != null) { - // TODO: set wrong answer option when options are used + var rightLabel = ClientData.Question.Right.FirstOrDefault(); + var rightIndex = Array.FindIndex(ClientData.QuestionPlayState.AnswerOptions, o => o.Label == rightLabel); + + var leftIndicies = Enumerable.Range(0, ClientData.QuestionPlayState.AnswerOptions.Length).Except(ClientData.QuestionPlayState.UsedAnswerOptionsIndicies).Except(new int[] { rightIndex }).ToArray(); + var wrongIndex = leftIndicies[Random.Shared.Next(leftIndicies.Length)]; + ClientData.Answerer.Answer = wrongIndex.ToString(); + } + else + { ClientData.Answerer.AnswerIsWrong = true; var restwrong = new List(); @@ -2031,11 +2049,13 @@ private void OnAnswer(Message message, string[] args) var wrongIndex = Random.Shared.Next(wrongCount); - ClientData.UsedWrongVersions.Add(restwrong[wrongIndex]); - ClientData.Answerer.Answer = args[2].Replace("#", restwrong[wrongIndex]); - } + if (ClientData.Round.Type != RoundTypes.Final) + { + ClientData.UsedWrongVersions.Add(restwrong[wrongIndex]); + } - ClientData.Answerer.Answer = ClientData.Answerer.Answer.GrowFirstLetter(); + ClientData.Answerer.Answer = args[2].Replace("#", restwrong[wrongIndex]).GrowFirstLetter(); + } } else { diff --git a/src/SICore/SICore/Clients/Game/GameLogic.cs b/src/SICore/SICore/Clients/Game/GameLogic.cs index 276f0148..2f4a32c6 100644 --- a/src/SICore/SICore/Clients/Game/GameLogic.cs +++ b/src/SICore/SICore/Clients/Game/GameLogic.cs @@ -11,6 +11,7 @@ using SIPackages.Core; using SIPackages.Providers; using SIUI.Model; +using SIUI.ViewModel; using System.Text; using System.Text.RegularExpressions; using R = SICore.Properties.Resources; @@ -1345,6 +1346,12 @@ private bool OnDecisionAnswerValidating() _gameActions.SendMessage(s.ToString()); + if (_data.QuestionPlayState.AnswerOptions != null && int.TryParse(_data.Answerer.Answer, out var answerIndex)) + { + _gameActions.SendMessageWithArgs(Messages.ContentState, ContentPlacements.Screen, answerIndex + 1, ItemState.Wrong); + _data.QuestionPlayState.UsedAnswerOptionsIndicies.Add(answerIndex); + } + _data.Answerer.Sum -= _data.CurPriceWrong; _data.Answerer.CanPress = false; _gameActions.InformSums(); @@ -1392,6 +1399,17 @@ public void ContinueQuestion() return; } + if (_data.QuestionPlayState.AnswerOptions != null) + { + var oneOptionLeft = _data.QuestionPlayState.UsedAnswerOptionsIndicies.Count + 1 == _data.QuestionPlayState.AnswerOptions.Length; + + if (oneOptionLeft) + { + ScheduleExecution(Tasks.WaitTry, 20, force: true); + return; + } + } + _data.PendingAnswererIndicies.Clear(); if (!ClientData.Settings.AppSettings.FalseStart) @@ -1506,7 +1524,20 @@ private bool OnDecisionAnswering() StopWaiting(); - _gameActions.PlayerReplic(_data.AnswererIndex, _data.Answerer.Answer); + if (_data.QuestionPlayState.AnswerOptions != null) + { + if (int.TryParse(_data.Answerer.Answer, out var answerIndex)) + { + _gameActions.SendMessageWithArgs(Messages.ContentState, ContentPlacements.Screen, answerIndex + 1, ItemState.Active); + } + + ScheduleExecution(Tasks.AskRight, 15, force: true); + return true; + } + else + { + _gameActions.PlayerReplic(_data.AnswererIndex, _data.Answerer.Answer); + } if (_data.IsOralNow) { @@ -3162,7 +3193,21 @@ private void AskRight() { _data.ShowmanDecision = false; - if (!_data.Answerer.IsHuman) + if (_data.QuestionPlayState.AnswerOptions != null) + { + _data.IsWaiting = true; + _data.Decision = DecisionType.AnswerValidating; + + var rightLabel = ClientData.Question.Right.FirstOrDefault(); + var rightIndex = Array.FindIndex(ClientData.QuestionPlayState.AnswerOptions, o => o.Label == rightLabel); + + _data.Answerer.AnswerIsRight = _data.Answerer.Answer == rightIndex.ToString(); + _data.Answerer.AnswerIsRightFactor = 1.0; + _data.ShowmanDecision = true; + + OnDecision(); + } + else if (!_data.Answerer.IsHuman) { _data.IsWaiting = true; _data.Decision = DecisionType.AnswerValidating; @@ -4405,7 +4450,19 @@ internal void OnComplexAnswer() internal void OnRightAnswerOption(string rightOptionLabel) { - _gameActions.SendMessageWithArgs(Messages.RightAnswer, ContentTypes.Text, rightOptionLabel); + var rightIndex = ClientData.QuestionPlayState.AnswerOptions != null + ? Array.FindIndex(ClientData.QuestionPlayState.AnswerOptions, o => o.Label == rightOptionLabel) + : -1; + + if (rightIndex > -1) + { + _gameActions.SendMessageWithArgs(Messages.RightAnswer, ContentTypes.Text, rightIndex); + } + else + { + var printedAnswer = $"{LO[nameof(R.RightAnswer)]}: {rightOptionLabel}"; + _gameActions.ShowmanReplic(printedAnswer); + } var answerTime = _data.Settings.AppSettings.TimeSettings.TimeForRightAnswer; ScheduleExecution(Tasks.MoveNext, (answerTime == 0 ? 2 : answerTime) * 10); diff --git a/src/SICore/SICore/Clients/Game/QuestionPlayState.cs b/src/SICore/SICore/Clients/Game/QuestionPlayState.cs index 68602175..0810be50 100644 --- a/src/SICore/SICore/Clients/Game/QuestionPlayState.cs +++ b/src/SICore/SICore/Clients/Game/QuestionPlayState.cs @@ -17,6 +17,11 @@ internal sealed class QuestionPlayState /// internal AnswerOption[]? AnswerOptions { get; set; } + /// + /// Used answer options indicies. + /// + internal HashSet UsedAnswerOptionsIndicies { get; } = new(); + /// /// Has layout been set. /// @@ -31,6 +36,7 @@ internal void Clear() { AnswererIndicies.Clear(); AnswerOptions = null; + UsedAnswerOptionsIndicies.Clear(); LayoutShown = false; AnswerOptionsShown = false; } diff --git a/src/SICore/SICore/Clients/Player/PlayerHumanLogic.cs b/src/SICore/SICore/Clients/Player/PlayerHumanLogic.cs index daacfad1..3830f7b9 100644 --- a/src/SICore/SICore/Clients/Player/PlayerHumanLogic.cs +++ b/src/SICore/SICore/Clients/Player/PlayerHumanLogic.cs @@ -40,7 +40,15 @@ public PlayerHumanLogic( TInfo.SelectTheme.CanBeExecuted = false; } - private void TInfo_AnswerSelected(ItemViewModel item) => ClientData.PlayerDataExtensions.SendAnswer.Execute(item.Label); + private void TInfo_AnswerSelected(ItemViewModel item) + { + var optionIndex = Array.IndexOf(TInfo.AnswerOptions.Options, item); + + if (optionIndex > -1) + { + ClientData.PlayerDataExtensions.SendAnswer.Execute(optionIndex.ToString()); + } + } #region PlayerInterface Members diff --git a/src/SICore/SICore/Clients/Viewer/IViewerLogic.cs b/src/SICore/SICore/Clients/Viewer/IViewerLogic.cs index 5f0e72eb..8a59e91b 100644 --- a/src/SICore/SICore/Clients/Viewer/IViewerLogic.cs +++ b/src/SICore/SICore/Clients/Viewer/IViewerLogic.cs @@ -185,4 +185,6 @@ void OnAnswerOptions(bool questionHasScreenContent, IEnumerable optionsT void OnContent(string[] mparams) { } void OnContentAppend(string[] mparams) { } + + void OnContentState(string[] mparams) { } } diff --git a/src/SICore/SICore/Clients/Viewer/Viewer.cs b/src/SICore/SICore/Clients/Viewer/Viewer.cs index a869ed58..6d282f32 100644 --- a/src/SICore/SICore/Clients/Viewer/Viewer.cs +++ b/src/SICore/SICore/Clients/Viewer/Viewer.cs @@ -820,6 +820,10 @@ await _client.Node.ConnectionsLock.WithLockAsync(() => _logic.OnContentAppend(mparams); break; + case Messages.ContentState: + _logic.OnContentState(mparams); + break; + case Messages.Atom_Hint: if (mparams.Length > 1) { diff --git a/src/SICore/SICore/Clients/Viewer/ViewerHumanLogic.cs b/src/SICore/SICore/Clients/Viewer/ViewerHumanLogic.cs index 416b8669..0d1f39ae 100644 --- a/src/SICore/SICore/Clients/Viewer/ViewerHumanLogic.cs +++ b/src/SICore/SICore/Clients/Viewer/ViewerHumanLogic.cs @@ -664,6 +664,26 @@ public void OnContentAppend(string[] mparams) TInfo.TextLength += newTextLength; } + public void OnContentState(string[] mparams) + { + if (mparams.Length < 4) + { + return; + } + + var placement = mparams[1]; + + if (TInfo.LayoutMode == LayoutMode.AnswerOptions + && placement == ContentPlacements.Screen + && int.TryParse(mparams[2], out var layoutId) + && layoutId > 0 + && layoutId <= TInfo.AnswerOptions.Options.Length + && Enum.TryParse(mparams[3], out var state)) + { + TInfo.AnswerOptions.Options[layoutId - 1].State = state; + } + } + private void OnScreenContent(IEnumerable contentInfo) { if (TInfo.TStage != TableStage.Answer && _data.Speaker != null && !_data.Speaker.IsShowman) @@ -1056,9 +1076,14 @@ public void OnRightAnswer(string answer) { var options = TInfo.AnswerOptions.Options; + if (!int.TryParse(answer, out var answerIndex)) + { + answerIndex = -1; + } + for (int i = 0; i < options.Length; i++) { - if (options[i].Label == answer) + if (i == answerIndex) { options[i].State = ItemState.Right; } diff --git a/src/SICore/SICore/Messages.cs b/src/SICore/SICore/Messages.cs index a643c348..9b6d9c09 100644 --- a/src/SICore/SICore/Messages.cs +++ b/src/SICore/SICore/Messages.cs @@ -139,6 +139,11 @@ public static class Messages /// public const string ContentShape = "CONTENT_SHAPE"; + /// + /// Updates content state. + /// + public const string ContentState = "CONTENT_STATE"; + /// /// Удаление темы ///