Example #1
0
        public static void ShowAppropriateToast(HourViewModel currentHour, QuestionViewModel oldQuestionState, Question currentQuestionState)
        {
            if (oldQuestionState.State == currentQuestionState.State)
            {
                Debug.WriteLine(string.Format("No toast displayed because oldQuestionState.{0} == currentQuestionState.{1}", oldQuestionState.State, currentQuestionState.State));
                return;  // If the state didn't change, don't show a toast
            }

            if (currentQuestionState.State == QuestionState.Open)
            {
                Debug.WriteLine(string.Format("No toast displayed because currentQuestionState.{0} == QuestionState.Open", currentQuestionState.State));
                return;  // no need to show toast
            }

            string imageKey;
            string text;
            ToastNotification.TriviaIndication indication;

            if (currentQuestionState.State == QuestionState.Wrong)
            {
                if (oldQuestionState.IsBeingResearched == false)
                {
                    Debug.WriteLine(string.Format("No toast displayed because oldQuestionState.IsBeingResearched({0}) == false", oldQuestionState.IsBeingResearched));
                    return;  // Don't show any toast if a question's closed that you weren't working on
                }

                // Just closed, didn't get an answer
                text = string.Format("Question #{0} Now Closed.", currentQuestionState.Identifier.Number);

                indication = ToastNotification.TriviaIndication.IncorrectQuestion;

                imageKey = GetImageForQuestion(currentQuestionState.Identifier.Hour, currentQuestionState.Identifier.Number, ToastFactory.WrongImages);

                // If it's a high-pointer, let's show a special meme instead
                if (currentQuestionState.Points >= 80)
                {
                    imageKey = GetImageForQuestion(currentQuestionState.Identifier.Hour, currentQuestionState.Identifier.Number, ToastFactory.HighPointWrongImages);
                }
            }
            else if (currentQuestionState.State == QuestionState.Correct)
            {
                // Always show toast for correct questions (maybe in the future we should have a threshold)

                text = string.Format("Got Correct Answer for #{0} - {1} points!", currentQuestionState.Identifier.Number, currentQuestionState.Points);
               
                indication = ToastNotification.TriviaIndication.CorrectQuestion;

                imageKey = GetImageForQuestion(currentQuestionState.Identifier.Hour, currentQuestionState.Identifier.Number, ToastFactory.CorrectImages);
            }
            else
            {
                throw new InvalidOperationException("Toast in wrong place unexpectedly");
            }

            ImageSource image = (ImageSource)ToastFactory.mImagesDictionary[imageKey];

            bool shouldShowStopResearching = oldQuestionState.IsBeingResearched;

            ToastNotification toast = new ToastNotification(image);
            toast.Indication = indication;
            toast.BodyText = text;

            toast.Show();

            // Extra toasts for special situations?

            if (currentQuestionState.Identifier.Number == 9 &&
                currentHour.OpenQuestions.Count == 0 &&
                currentHour.Questions.All(q => q.State == QuestionState.Correct))
            {
                ToastNotification allofthethings = new ToastNotification((ImageSource)ToastFactory.mImagesDictionary["allofthethings"], false);
                allofthethings.Indication = indication;
                allofthethings.BodyText = "Perfect Hour";

                allofthethings.Show();
            }

            // If it's a low pointer that we missed, add an extra toast meme (only show the people researching though to avoid spam)
            if (currentQuestionState.State == QuestionState.Wrong &&
                currentQuestionState.Points < 20)  // Less than 20 points we'll consider small
            {
                ToastNotification fuckitbillmurray = new ToastNotification((ImageSource)ToastFactory.mImagesDictionary["fuckitbillmurray"], false);
                fuckitbillmurray.Indication = indication;
                fuckitbillmurray.BodyText = "Small Question Missed";

                fuckitbillmurray.Show();
            }

            // Always last/leftmost
            if (shouldShowStopResearching)
            {
                ToastNotification stopResearchingToast = new ToastNotification((ImageSource)ToastFactory.mImagesDictionary["StopResearching"], false);
                stopResearchingToast.Indication = indication;
                stopResearchingToast.BodyText = "Stop Researching This Question";

                stopResearchingToast.Show();
            }
        }
Example #2
0
        public QuestionViewModel(Question question, IEnumerable<Answer> submittedAnswers, DispatchableObservableCollection<Note> notes)
        {
            Contract.Requires(question != null);
            Contract.Requires(submittedAnswers != null);

            this.Identifier = question.Identifier;

            this.Update(question, playerInitiatedUpdate: true); // Set all standard fields in one place

#if DEBUG
            // Make sure we're on the UI thread here, ListCollectionView requires it
            System.Diagnostics.Debug.Assert(System.Windows.Application.Current.Dispatcher.Thread.ManagedThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId);
#endif

            this.Notes = notes;

            this.SubmittedAnswers = new TriviaObservableCollection<AnswerViewModel>(submittedAnswers.Select(answer => new AnswerViewModel(answer)));

            if (ContestConfiguration.Contest == ContestConfiguration.ContestType.HouseOfInsanity)
            {
                this.SubmittedUncalledAnswers = new ListCollectionView(this.SubmittedAnswers);
                this.SubmittedUncalledAnswers.Filter = obj => !((AnswerViewModel)obj).HasBeenCalledIn && !((AnswerViewModel)obj).WillCallInNext;
                this.SubmittedUncalledAnswers.SortDescriptions.Add(new SortDescription("Priority", ListSortDirection.Descending));
                this.SubmittedUncalledAnswers.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending));

                this.PartialAnswers = new ListCollectionView(this.SubmittedAnswers);
                this.PartialAnswers.Filter = obj => ((AnswerViewModel)obj).Partial;
                this.PartialAnswers.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending));

                this.AnswersToCallInNext = new ListCollectionView(this.SubmittedAnswers);
                this.AnswersToCallInNext.Filter = obj => !((AnswerViewModel)obj).HasBeenCalledIn && ((AnswerViewModel)obj).WillCallInNext;
                this.AnswersToCallInNext.SortDescriptions.Add(new SortDescription("Priority", ListSortDirection.Descending));
                this.AnswersToCallInNext.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending));

                this.SubmittedAnswersForReadOnlyTab = new ListCollectionView(this.SubmittedAnswers);
                this.SubmittedAnswersForReadOnlyTab.SortDescriptions.Add(new SortDescription("Text", ListSortDirection.Ascending));  // alphabetically

                this.Researchers = new DispatchableObservableCollection<string>();

                this.HighlightAppearanceOfPartialsInAnswers();
            }
            else
            {
                
                // State 1 (Ruled out), State 2 (1 star), State 3 (2 stars)... State 6 (5 stars), State 7 (single (theoretically) answer to call in) 
                this.BeerpigRankedAnswers = new ListCollectionView[8];

                for (int i = 1; i <= 8; ++i)
                {
                    int tempLocal = i;  // capture for closure

                    ListCollectionView lcv = new ListCollectionView(this.SubmittedAnswers);
                    lcv.Filter = obj => ((AnswerViewModel)obj).State == tempLocal;
                    lcv.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending));
                    this.BeerpigRankedAnswers[i - 1] = lcv;
                }
            }
        }
Example #3
0
        public EditQuestionDialog(ClientOrchestrator orchestrator, QuestionViewModel question, bool isOpeningQuestion)
            : this()
        {
            Contract.Requires(orchestrator != null);
            Contract.Requires(question != null);

            this.mQuestion = question;

            this.mSnapshotOfQuestionPriorToEdits = question.CreateModel();

            this.mViewModel = new EditQuestionViewModel(question, isOpeningQuestion);

            this.mOrchestrator = orchestrator;
            this.mOrchestrator.StartAudioTriviaRecordingResponseReceived += new ClientOrchestrator.StartAudioTriviaRecordingEventHandler(mOrchestrator_StartAudioTriviaRecordingResponseReceived);
            this.mOrchestrator.StopAudioTriviaRecordingResponseReceived += new ClientOrchestrator.StopAudioTriviaRecordingEventHandler(mOrchestrator_StopAudioTriviaRecordingResponseReceived);
            
            this.DataContext = this.mViewModel;

            this.mQuestionTextTextbox.Text = question.Text;  // Because we don't want other people's updates to change the textbox, binding is OneWayToSource, so we need to set the initial value

            // If it starts with the magic text, manually set this flag
            isOpeningQuestion |= (question.Text != null && question.Text.StartsWith("Currently being opened"));

            // Set up bindings
            if (isOpeningQuestion)
            {
                // We can do this since IsOpeningQuestion will not change
                this.mAnswerPanel.Visibility = Visibility.Collapsed;
                this.mPhoneBankPanel.Visibility = Visibility.Collapsed;
                this.mStatePanel.Visibility = Visibility.Collapsed;

                question.Text = string.Empty;  // Start with empty text if opening the question

                // Special labels for opening
                this.Title = "Open Question";
                this.mHeaderActionLabel.Text = "Open Question";

                this.mRecordAudioTriviaButton.Focus();

                this.mRecordAudioTriviaButton.Click += new RoutedEventHandler(this.OnRecordingAudioTriviaClickedWhileOpeningQuestion);

                // Hack, because it's bound to a question

                RoutedEventHandler focusHandler = null;
                
                focusHandler = (sender, e) => 
                    { 
                        this.mQuestionTextTextbox.Clear(); 
                        this.mQuestionTextTextbox.GotFocus -= focusHandler;  // only once!
                    };

                this.mQuestionTextTextbox.GotFocus += focusHandler;

            }
            else
            {
                this.mAnswerPanel.SetBinding(Panel.VisibilityProperty,
                    new ConvertingBinding<QuestionState, Visibility>("Question.State",
                        state => state == QuestionState.Open ? Visibility.Collapsed : Visibility.Visible));

                this.mPhoneBankPanel.SetBinding(Panel.VisibilityProperty,
                    new ConvertingBinding<QuestionState, Visibility>("Question.State",
                        state => state == QuestionState.Correct ? Visibility.Visible : Visibility.Collapsed));

                this.mQuestionTextTextbox.Focus();
            }
            
            // Set the text for the Record button
            this.mRecordThisQuestionButtonText.SetBinding(TextBlock.TextProperty, new ConvertingBinding<string, string>("Question.AudioTriviaFilename",
                audioTriviaFileName => string.IsNullOrWhiteSpace(audioTriviaFileName) ? "Record This Question" : "Re-Record This Question"));

            
        }
Example #4
0
 public QuestionViewModel(Question Question)
     : this(Question, new List<Answer>(), new DispatchableObservableCollection<Note>())
 {
 }
Example #5
0
        public Question CreateModel()
        {
            Question model = new Question(this.Identifier.Hour, this.Identifier.Number);
            model.Text = this.Text;
            model.Answer = this.Answer;
            model.AudioTriviaFilename = this.AudioTriviaFilename;
            model.State = this.State;
            model.Points = this.Points;
            model.PhoneBankOperator = this.PhoneBankOperator;

            return model;
        }
Example #6
0
        public void Update(Question updatedQuestion, bool playerInitiatedUpdate)
        {
            // Identifier should never change...

            // SubmittedAnswers shouldn't change as a result of an update

            
            this.Text = updatedQuestion.Text;
            this.PredictedRemainingOpenDurationInMinutes = updatedQuestion.PredictedRemainingOpenDurationInMinutes;

            if (!(playerInitiatedUpdate))
            {
                // Only things that should change as a result of an automatic update are Text and Predicted Duration
                return;
            }

            this.Answer = updatedQuestion.Answer;
            this.AudioTriviaFilename = updatedQuestion.AudioTriviaFilename;
            this.State = updatedQuestion.State;
            this.Points = updatedQuestion.Points;
            this.PhoneBankOperator = updatedQuestion.PhoneBankOperator;
        }
Example #7
0
        private void TestMemes(object sender, RoutedEventArgs e)
        {

            /* perfect hour
            HourViewModel hvm = new HourViewModel(1);
            hvm.Questions.Add(new QuestionViewModel(new Question(4, 8)) { State = QuestionState.Open });
            hvm.Questions.Add(new QuestionViewModel(new Question(4, 9)) { State = QuestionState.Correct, IsBeingResearched = true });
            ToastFactory.ShowAppropriateToast(hvm, hvm.Questions[1], hvm.Questions[1]);
            */
            /* missed small pointer
            HourViewModel hvm = new HourViewModel(1);
            hvm.Questions.Add(new QuestionViewModel(new Question(4, 9)) { State = QuestionState.Open });
            hvm.Questions.Add(new QuestionViewModel(new Question(4, 9)) { State = QuestionState.Wrong, IsBeingResearched = true, Points = 5 });
            ToastFactory.ShowAppropriateToast(hvm, hvm.Questions[1], hvm.Questions[1]);
            */

            // missed big pointer
            HourViewModel hvm = new HourViewModel(1);
            hvm.Questions.Add(new QuestionViewModel(new Question(4, 9)) { State = QuestionState.Open, IsBeingResearched = true, Points = 125 });
            Question current = new Question(4, 9) { State = QuestionState.Wrong, Points = 125 };
            ToastFactory.ShowAppropriateToast(hvm, hvm.Questions.Single(), current);
        }
Example #8
0
		private static Question GetQuestionFromDataReader(SqlDataReader reader)
		{
            int hour = int.Parse(reader["qhour"].ToString());
            int number = int.Parse(reader["qnumber"].ToString());

			Question q = new Question(hour, number);

			q.Text = reader["qtext"].ToString();
			q.Open = bool.Parse(reader["qopen"].ToString());
			q.Correct = bool.Parse(reader["correct"].ToString());
			q.Answer = reader["answer"].ToString();
			q.Points = int.Parse(reader["points"].ToString());
            q.AudioTriviaFilename = reader["audiotriviafilename"].ToString();
            q.PhoneBankOperator = reader["phoneop"].ToString();

            // Apply the Duration business rules... (this code is always assured to be running on the server (with "Server Time"))

            object predictedDurationObj = reader["predictedduration"];
            object timeOpenedObj = reader["timeopened"];  // ex: 2011-01-17 19:56:00

            if (predictedDurationObj != System.DBNull.Value &&
                timeOpenedObj != System.DBNull.Value)
            {
                int predictedDurationInMinutes = int.Parse(predictedDurationObj.ToString());
                DateTime timeOpened = (DateTime)timeOpenedObj;

                TimeSpan timeKeptOpenSoFar = DateTime.Now - timeOpened;

                /* per documentation, smalldatetime in SQL rounds to the nearest minute.  Occasionally the opened time will appear to be "in the future", but it's really a rounding error.
                if (timeOpened > DateTime.Now)
                {
                    throw new InvalidOperationException(string.Format("Wow, somehow the question was opened at {0} which is after Now={1}.  Quite illegal.", timeOpened.ToLongTimeString(), DateTime.Now.ToLongTimeString()));
                }
                */
                
                if (timeKeptOpenSoFar < TimeSpan.Zero)
                {
                    timeKeptOpenSoFar = TimeSpan.Zero;  // See above, prevent rounding error from making the UI weird.
                }

                q.PredictedRemainingOpenDurationInMinutes = predictedDurationInMinutes - (int)timeKeptOpenSoFar.TotalMinutes;
            }

			return q;
		}