private List <ResultModel> FilterForCorrectResponsesClick(SlideQuestionModel slideQuestionModel, List <ResultModel> responses)
        {
            var correctResponses = new List <ResultModel>();

            var correctAnswerOptionPositions      = slideQuestionModel.AnswerOptions.Where(ao => ao.IsTrue).Select(ao => ao.Position).Select(correctAnswerOptionPosition => correctAnswerOptionPosition - 1).ToList();
            var correctAnswerOptionPositionsCount = correctAnswerOptionPositions.Count();

            switch (slideQuestionModel.QuestionType)
            {
            case QuestionTypeEnum.SingleChoiceClick:
            case QuestionTypeEnum.YesNoClick:
            case QuestionTypeEnum.TrueFalseClick:
                var correctAnswerOptionPosition = correctAnswerOptionPositions.First();
                foreach (var response in responses)
                {
                    if (response.answerOptionNumber.First() == correctAnswerOptionPosition)
                    {
                        correctResponses.Add(response);
                    }
                }
                break;

            case QuestionTypeEnum.MultipleChoiceClick:
                foreach (var response in responses)
                {
                    if (correctAnswerOptionPositionsCount == response.answerOptionNumber.Count)
                    {
                        var allCorrect = true;

                        foreach (var answerOption in response.answerOptionNumber)
                        {
                            if (correctAnswerOptionPositions.All(ca => ca != answerOption))
                            {
                                allCorrect = false;
                            }
                        }

                        if (allCorrect)
                        {
                            correctResponses.Add(response);
                        }
                    }
                }
                break;

            case QuestionTypeEnum.RangedQuestionClick:
                correctResponses.AddRange(this.GetCorrectRangedAnswerResults(slideQuestionModel, responses));
                break;

            case QuestionTypeEnum.FreeTextClick:
                correctResponses.AddRange(this.GetCorrectFreeTextResults(slideQuestionModel, responses));
                break;

            case QuestionTypeEnum.SurveyClick:
                correctResponses = responses;
                break;
            }

            return(correctResponses);
        }
Пример #2
0
        public static SlideQuestionModel CopySlideQuestionModel(SlideQuestionModel currentSlideQuestionModel)
        {
            var newSlideQuestionModel = new SlideQuestionModel
            {
                Id                      = currentSlideQuestionModel.Id,
                Hashtag                 = currentSlideQuestionModel.Hashtag,
                QuestionType            = currentSlideQuestionModel.QuestionType,
                QuestionTypeSet         = currentSlideQuestionModel.QuestionTypeSet,
                QuestionText            = currentSlideQuestionModel.QuestionText,
                AnswerOptionsSet        = currentSlideQuestionModel.AnswerOptionsSet,
                AnswerOptionAmount      = currentSlideQuestionModel.AnswerOptionAmount,
                QuestionInitType        = currentSlideQuestionModel.QuestionInitType,
                Index                   = currentSlideQuestionModel.Index,
                RecalculatedOnlineIndex = currentSlideQuestionModel.RecalculatedOnlineIndex,
                ChartType               = currentSlideQuestionModel.ChartType,
                ResultsSlideId          = currentSlideQuestionModel.ResultsSlideId,
                QuestionTimerSlideId    = currentSlideQuestionModel.QuestionTimerSlideId,
                QuestionInfoSlideId     = currentSlideQuestionModel.QuestionInfoSlideId,
                AnswerOptions           = new ObservableCollection <GeneralAnswerOption>()
            };


            if (currentSlideQuestionModel.AnswerOptions != null)
            {
                foreach (var answerOption in currentSlideQuestionModel.AnswerOptions)
                {
                    newSlideQuestionModel.AnswerOptions.Add(CopyAnswerOptionModel(newSlideQuestionModel, answerOption));
                }
            }

            return(newSlideQuestionModel);
        }
        public void GetAndDisplayArsnovaVotingResults(SlideQuestionModel slideQuestionModel)
        {
            var slideSessionModel = this.GetSlideSessionModel();
            var resultsSlide      = SlideTracker.GetSlideById(slideQuestionModel.ResultsSlideId.Value);

            this.sessionManager.GetAndDisplayArsnovaVotingResults(slideSessionModel, slideQuestionModel, resultsSlide);
        }
Пример #4
0
        private void HandleTimerEvent(object source, ElapsedEventArgs e)
        {
            this.countdown--;
            if (this.countdown >= 0)
            {
                this.slideManipulator.SetTimerOnSlide(this.currentQuestionModel, this.questionTimerSlide, this.countdown);
            }

            if (this.countdown == 0)
            {
                this.timer.Stop();

                var responses = this.arsnovaClickService.GetResultsForHashtag(this.currentSlideSessionModel.Hashtag, this.currentQuestionModel.RecalculatedOnlineIndex);
                if (responses != null)
                {
                    this.slideManipulator.SetClickResults(this.currentQuestionModel, this.resultsSlide, responses);
                }


                // move to next slide (results)
                this.ShowNextSlideEventHandler?.Invoke(this, EventArgs.Empty);

                // clean up
                this.timer = null;
                this.currentQuestionModel     = null;
                this.currentSlideSessionModel = null;
                this.questionTimerSlide       = null;
                this.resultsSlide             = null;
            }
        }
Пример #5
0
        private static GeneralAnswerOption CopyAnswerOptionModel(SlideQuestionModel slideQuestionModel, GeneralAnswerOption answerOption)
        {
            if (answerOption.AnswerOptionType == AnswerOptionType.ShowRangedAnswerOption)
            {
                var newAnswerOption = new GeneralAnswerOption
                {
                    Id = answerOption.Id,
                    RangedLowerLimit   = answerOption.RangedLowerLimit,
                    RangedCorrectValue = answerOption.RangedCorrectValue,
                    RangedHigherLimit  = answerOption.RangedHigherLimit,
                    AnswerOptionType   = AnswerOptionType.ShowRangedAnswerOption
                };

                return(newAnswerOption);
            }
            else
            {
                var newAnswerOption = new GeneralAnswerOption();

                newAnswerOption.ObjectChangedEventHandler += delegate {
                    slideQuestionModel.AnswerOptionsSet = true;
                    slideQuestionModel.AnswerOptionModelChanged();
                };

                newAnswerOption.Id                 = answerOption.Id;
                newAnswerOption.Position           = answerOption.Position;
                newAnswerOption.AlphabeticPosition = answerOption.AlphabeticPosition;
                newAnswerOption.Text               = answerOption.Text;
                newAnswerOption.IsTrue             = answerOption.IsTrue;

                return(newAnswerOption);
            }

            throw new ArgumentException($"Unknow answer option type {answerOption.GetType()}");
        }
        public void SetTimerOnSlide(SlideQuestionModel slideQuestionModel, Slide questionTimerSlide, int countdown)
        {
            var answerOptionType           = this.sessionInformationProvider.GetAnswerOptionType(slideQuestionModel.QuestionType);
            var isRangedOrFreetextQuestion = answerOptionType == AnswerOptionType.ShowRangedAnswerOption ||
                                             answerOptionType == AnswerOptionType.ShowFreeTextAnswerOptions;

            questionTimerSlide.Shapes[isRangedOrFreetextQuestion ? 4 : 5].TextFrame.TextRange.Text = countdown.ToString();
        }
        public AnswerOptionViewViewModel(ViewModelRequirements requirements, Guid questionId, bool isNew, SlideQuestionModel questionBeforeEdit)
            : base(requirements)
        {
            this.questionId         = questionId;
            this.isNew              = isNew;
            this.questionBeforeEdit = questionBeforeEdit;

            this.InitializeWindowCommandBindings();

            this.InitAnswerOptionList();
        }
        private LectureQuestionModel SlideQuestionModelToLectureQuestionModel(SlideQuestionModel questionModel, string sessionKey)
        {
            var leqtureQuestion = new LectureQuestionModel
            {
                abstention      = false, // TODO should abstention be allowed?
                active          = false,
                imageQuestion   = false,
                number          = questionModel.Index - 1,
                questionType    = this.QuestionTypeToVotingQuestionType(questionModel.QuestionType),
                questionVariant = "preparation",
                releasedFor     = "all",
                sessionKeyword  = sessionKey,
                showStatistic   = true,
                subject         = "powerpoint generated questions", // TODO
                text            = questionModel.QuestionText,
                type            = "skill_question",
                votingDisabled  = true // Disabled by default!
            };

            if (questionModel.QuestionType != QuestionTypeEnum.FreeTextVoting)
            {
                var answerOptionList = new List <PossibleAnswerObject>();

                foreach (var answerOption in questionModel.AnswerOptions)
                {
                    answerOptionList.Add(new PossibleAnswerObject
                    {
                        correct = answerOption.IsTrue,
                        text    = answerOption.Text,
                        value   = answerOption.IsTrue ? 10 : -10
                    });
                }

                leqtureQuestion.possibleAnswers = answerOptionList;
            }
            else
            {
                // freetext
                var answerOption = questionModel.AnswerOptions.First();

                leqtureQuestion.strictMode          = true;
                leqtureQuestion.textAnswerEnabled   = true;
                leqtureQuestion.correctAnswer       = answerOption.Text;
                leqtureQuestion.fixedAnswer         = true;
                leqtureQuestion.ignoreCaseSensitive = answerOption.ConfigCaseSensitive;
                leqtureQuestion.ignorePunctuation   = answerOption.ConfigUsePunctuation;
                leqtureQuestion.ignoreWhitespaces   = answerOption.ConfigTrimWhitespaces;
            }

            return(leqtureQuestion);
        }
        protected void AddSessionToSlides(SlideQuestionModel slideQuestionModel)
        {
            var hasIntroSlide = this.HasIntroSlide();

            if (!hasIntroSlide)
            {
                var introSlide = this.RibbonHelper.CreateNewSlide(1);

                this.SlideManipulator.AddIntroSlide(this.SlideSessionModel, introSlide);

                this.SlideSessionModel.IntroSlideId = introSlide.SlideID;

                PresentationInformationStore.SetArsnovaIntroSlideAdded();
            }

            var questionInfoSlide = SlideTracker.GetSlideById(slideQuestionModel.QuestionInfoSlideId);

            if (this.SessionInformationProvider.IsClickQuestion(slideQuestionModel.QuestionType))
            {
                // arsnova.click
                var questionTimerSlide = slideQuestionModel.QuestionTimerSlideId.HasValue
                    ? SlideTracker.GetSlideById(slideQuestionModel.QuestionTimerSlideId.Value)
                    : this.RibbonHelper.CreateNewSlide(questionInfoSlide.SlideIndex + 1);
                slideQuestionModel.QuestionTimerSlideId = questionTimerSlide.SlideID;

                var resultsSlide = slideQuestionModel.ResultsSlideId.HasValue
                                        ? SlideTracker.GetSlideById(slideQuestionModel.ResultsSlideId.Value)
                                        : this.RibbonHelper.CreateNewSlide(questionInfoSlide.SlideIndex + 2);
                slideQuestionModel.ResultsSlideId = resultsSlide.SlideID;

                this.SlideManipulator.AddQuizToStyledSlides(slideQuestionModel, questionInfoSlide, questionTimerSlide, resultsSlide);
            }
            else
            {
                // arsnova.voting
                slideQuestionModel.QuestionTimerSlideId = slideQuestionModel.QuestionInfoSlideId;

                var resultsSlide = slideQuestionModel.ResultsSlideId.HasValue
                                        ? SlideTracker.GetSlideById(slideQuestionModel.ResultsSlideId.Value)
                                        : this.RibbonHelper.CreateNewSlide(questionInfoSlide.SlideIndex + 1);
                slideQuestionModel.ResultsSlideId = resultsSlide.SlideID;

                this.SlideManipulator.AddQuizToStyledSlides(slideQuestionModel, questionInfoSlide, resultsSlide);
            }

            PresentationInformationStore.StoreSlideSessionModel(this.SlideSessionModel);
            this.ViewPresenter.CloseWithoutPrompt();
        }
        private List <ResultModel> GetCorrectRangedAnswerResults(SlideQuestionModel slideQuestionModel, List <ResultModel> responses)
        {
            var correctResponses = new List <ResultModel>();
            var answerOption     = slideQuestionModel.AnswerOptions.First();

            foreach (var response in responses)
            {
                if (response.rangedInputValue >= answerOption.RangedLowerLimit &&
                    response.rangedInputValue <= answerOption.RangedHigherLimit)
                {
                    correctResponses.Add(response);
                }
            }

            return(correctResponses);
        }
Пример #11
0
        public QuestionViewViewModel(ViewModelRequirements requirements, Guid questionId, bool isNew, SlideQuestionModel questionBeforeEdit = null)
            : base(requirements)
        {
            this.questionId = questionId;
            this.isNew      = isNew;

            this.questionBeforeEdit = questionBeforeEdit ?? CopyHelper.CopySlideQuestionModel(this.SlideQuestionModel);

            this.InitializeWindowCommandBindings();

            this.QuestionTypes = this.SlideSessionModel.SessionType == SessionType.ArsnovaClick
                ? this.SessionInformationProvider.GetAvailableQuestionsClick()
                : this.SessionInformationProvider.GetAvailableQuestionsVoting();

            this.ExcelChartTypes = this.SessionInformationProvider.GetExcelChartTypes();
        }
        public void AddQuizToStyledSlides(SlideQuestionModel slideQuestionModel, Slide questionInfoSlide, Slide resultsSlide)
        {
            var answerOptionType           = this.sessionInformationProvider.GetAnswerOptionType(slideQuestionModel.QuestionType);
            var isRangedOrFreetextQuestion = answerOptionType == AnswerOptionType.ShowRangedAnswerOption ||
                                             answerOptionType == AnswerOptionType.ShowFreeTextAnswerOptions;

            this.RemoveShapesFromSlide(questionInfoSlide);
            this.RemoveShapesFromSlide(resultsSlide);

            questionInfoSlide.FollowMasterBackground = MsoTriState.msoTrue;
            resultsSlide.FollowMasterBackground      = MsoTriState.msoTrue;

            this.SetQuestionInfoSlidecontent(slideQuestionModel, questionInfoSlide, isRangedOrFreetextQuestion);

            this.CleanResultsPage(resultsSlide);
        }
        private List <ArsnovaVotingResultReturnElement> GetCorrectFreeTextResultsVoting(
            SlideQuestionModel slideQuestionModel, List <ArsnovaVotingResultReturnElement> responses)
        {
            var correctResponses  = new List <ArsnovaVotingResultReturnElement>();
            var answerOption      = slideQuestionModel.AnswerOptions.First();
            var answerOptionText  = answerOption.Text;
            var punctutationRegex = new Regex(@"(\.)*(,)*(!)*("")*(;)*(\?)*");
            var whiteSpaceRegex   = new Regex(@" ");

            if (!answerOption.ConfigCaseSensitive)
            {
                answerOptionText = answerOptionText.ToLower();
            }

            if (!answerOption.ConfigUsePunctuation)
            {
                answerOptionText = punctutationRegex.Replace(answerOptionText, "");
            }

            foreach (var response in responses)
            {
                var responseText = response.answerText;

                if (!answerOption.ConfigCaseSensitive)
                {
                    responseText = responseText.ToLower();
                }

                if (!answerOption.ConfigUsePunctuation)
                {
                    responseText = punctutationRegex.Replace(responseText, "");
                }

                if (!answerOption.ConfigTrimWhitespaces)
                {
                    responseText = whiteSpaceRegex.Replace(responseText, "");
                }

                if (answerOptionText == responseText)
                {
                    correctResponses.Add(response);
                }
            }

            return(correctResponses);
        }
        public void StartQuiz(SlideQuestionModel slideQuestionModel)
        {
            var slideSessionModel = this.GetSlideSessionModel();
            var resultsSlide      = SlideTracker.GetSlideById(slideQuestionModel.ResultsSlideId.Value);

            if (this.sessionInformationProvider.IsClickQuestion(slideQuestionModel.QuestionType))
            {
                // arsnova click
                var questionTimerSlide = SlideTracker.GetSlideById(slideQuestionModel.QuestionTimerSlideId.Value);
                this.sessionManager.StartClickQuestion(slideSessionModel, slideQuestionModel.Index, questionTimerSlide,
                                                       resultsSlide);
            }
            else
            {
                // arsnova.voting
                this.sessionManager.StartVotingQuestion(slideSessionModel, slideQuestionModel);
            }
        }
        public void AddQuizToStyledSlides(SlideQuestionModel slideQuestionModel, Slide questionInfoSlide, Slide questionTimerSlide, Slide resultsSlide)
        {
            var isClickQuestion   = this.sessionInformationProvider.IsClickQuestion(slideQuestionModel.QuestionType);
            var sessionInfoString = isClickQuestion ? "https://arsnova.click/" + slideQuestionModel.Hashtag : "https://arsnova.eu/mobile/#id/" + slideQuestionModel.Hashtag;

            var answerOptionType           = this.sessionInformationProvider.GetAnswerOptionType(slideQuestionModel.QuestionType);
            var isRangedOrFreetextQuestion = answerOptionType == AnswerOptionType.ShowRangedAnswerOption ||
                                             answerOptionType == AnswerOptionType.ShowFreeTextAnswerOptions;

            this.RemoveShapesFromSlide(questionTimerSlide);
            this.RemoveShapesFromSlide(resultsSlide);

            questionInfoSlide.FollowMasterBackground  = MsoTriState.msoTrue;
            questionTimerSlide.FollowMasterBackground = MsoTriState.msoTrue;
            resultsSlide.FollowMasterBackground       = MsoTriState.msoTrue;

            this.SetQuestionInfoSlidecontent(slideQuestionModel, questionInfoSlide, isRangedOrFreetextQuestion);


            questionTimerSlide.Layout = PpSlideLayout.ppLayoutBlank;
            this.AddQuestionSlideContent(slideQuestionModel, questionTimerSlide, isRangedOrFreetextQuestion, sessionInfoString);

            // Timer
            var timerLabelTextBox   = questionTimerSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 300, 450, 150, 90);
            var timerLabelTextRange = timerLabelTextBox.TextFrame.TextRange;

            timerLabelTextRange.Text               = this.localizationService.Translate("Countdown:");
            timerLabelTextRange.Font.Name          = this.font;
            timerLabelTextRange.Font.Size          = 26;
            timerLabelTextBox.TextEffect.FontBold  = MsoTriState.msoTrue;
            timerLabelTextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            var timerTextBox   = questionTimerSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 500, 450, 150, 90);
            var timerTextRange = timerTextBox.TextFrame.TextRange;

            timerTextRange.Text               = slideQuestionModel.Countdown.ToString();
            timerTextRange.Font.Name          = this.font;
            timerTextRange.Font.Size          = 26;
            timerTextBox.TextEffect.FontBold  = MsoTriState.msoTrue;
            timerTextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            this.CleanResultsPage(resultsSlide);
        }
        private List <ResultModel> GetBest10Responses(SlideQuestionModel slideQuestionModel, List <ResultModel> responses)
        {
            var correctResponsesresponses = this.FilterForCorrectResponsesClick(slideQuestionModel, responses);

            var best10Responses = new List <ResultModel>();

            for (var i = 0; i < 10; i++)
            {
                if (correctResponsesresponses.Count == 0)
                {
                    break;
                }

                var minResponse = correctResponsesresponses.First(r => r.responseTime == correctResponsesresponses.Min(r2 => r2.responseTime));
                best10Responses.Add(minResponse);
                correctResponsesresponses.Remove(minResponse);
            }

            return(best10Responses.OrderBy(r => r.responseTime).ToList());
        }
        private void AddQuestionSlideContent(SlideQuestionModel slideQuestionModel, Slide questionSlide, bool isRangedOrFreetextQuestion, string sessionInfoString)
        {
            // session info
            var sessionInfoTextBox = questionSlide.Shapes.AddTextbox(
                MsoTextOrientation.msoTextOrientationHorizontal, 50, 25, 850, 60);
            var sessionInfoTextRange = sessionInfoTextBox.TextFrame.TextRange;

            sessionInfoTextRange.Text               = sessionInfoString;
            sessionInfoTextRange.Font.Name          = this.font;
            sessionInfoTextRange.Font.Size          = 22;
            sessionInfoTextBox.TextEffect.FontBold  = MsoTriState.msoTrue;
            sessionInfoTextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            // question
            var questionTextBox = questionSlide.Shapes.AddTextbox(
                MsoTextOrientation.msoTextOrientationHorizontal,
                50,
                isRangedOrFreetextQuestion ? 240 : 100,
                850,
                isRangedOrFreetextQuestion ? 100 : 60);
            var questionTextRange = questionTextBox.TextFrame.TextRange;

            questionTextRange.Text               = slideQuestionModel.QuestionText;
            questionTextRange.Font.Name          = this.font;
            questionTextRange.Font.Size          = 22;
            questionTextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            // answer options
            // no answer options on ranged questions or on free text
            if (!isRangedOrFreetextQuestion)
            {
                var answerOptionsString = slideQuestionModel.AnswerOptions
                                          .Aggregate(string.Empty, (current, castedAnswerOption) => current + $"{this.PositionNumberToLetter(castedAnswerOption.Position - 1)}: {castedAnswerOption.Text}{Environment.NewLine}");

                var answerOptionsTextBox   = questionSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 50, 170, 850, 150);
                var answerOptionsTextRange = answerOptionsTextBox.TextFrame.TextRange;
                answerOptionsTextRange.Text      = answerOptionsString;
                answerOptionsTextRange.Font.Name = this.font;
                answerOptionsTextRange.Font.Size = 20;
            }
        }
        private QuestionModel SlideQuestionModelToQuestionModel(SlideQuestionModel slideQuestionModel, string hashtag)
        {
            var questionModel = new QuestionModel
            {
                hashtag           = Uri.EscapeDataString(hashtag),
                questionText      = Uri.EscapeDataString(slideQuestionModel.QuestionText),
                timer             = slideQuestionModel.Countdown,
                startTime         = 0,
                questionIndex     = slideQuestionModel.RecalculatedOnlineIndex,
                displayAnswerText = false,
                type = this.QuestionTypeToClickQuestionType(slideQuestionModel.QuestionType)
            };

            if (slideQuestionModel.QuestionType == QuestionTypeEnum.RangedQuestionClick)
            {
                var rangedAnswerOption = slideQuestionModel.AnswerOptions.First();

                if (rangedAnswerOption == null)
                {
                    throw new ArgumentException("no answer options provided");
                }

                questionModel.rangeMin     = rangedAnswerOption.RangedLowerLimit;
                questionModel.rangeMax     = rangedAnswerOption.RangedHigherLimit;
                questionModel.correctValue = rangedAnswerOption.RangedCorrectValue;

                questionModel.answerOptionList = new List <AnswerOptionModel>();
            }
            else
            {
                var isFreetextAnswerOption = slideQuestionModel.QuestionType == QuestionTypeEnum.FreeTextClick;

                var answerOptionModelList =
                    slideQuestionModel.AnswerOptions.Select(a => this.SlideAnswerOptionModelToAnswerOptionModel(a, hashtag, slideQuestionModel.RecalculatedOnlineIndex, isFreetextAnswerOption))
                    .ToList();

                questionModel.answerOptionList = answerOptionModelList;
            }

            return(questionModel);
        }
        private void SetQuestionInfoSlidecontent(SlideQuestionModel slideQuestionModel, Slide questionInfoSlide, bool isRangedOrFreetextQuestion)
        {
            var isClickQuestion   = this.sessionInformationProvider.IsClickQuestion(slideQuestionModel.QuestionType);
            var sessionInfoString = isClickQuestion ? "https://arsnova.click/" + slideQuestionModel.Hashtag : "https://arsnova.eu/mobile/#id/" + slideQuestionModel.Hashtag;

            this.RemoveShapesFromSlide(questionInfoSlide);

            questionInfoSlide.Layout = PpSlideLayout.ppLayoutBlank;
            this.AddQuestionSlideContent(slideQuestionModel, questionInfoSlide, isRangedOrFreetextQuestion, sessionInfoString);

            // Button not possible, just added a textbox to start quiz on next slide (when in click, voting will start immediately)
            if (isClickQuestion)
            {
                var startQuizTextBox   = questionInfoSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 50, 450, 850, 50);
                var startQuizTextRange = startQuizTextBox.TextFrame.TextRange;
                startQuizTextRange.Text               = this.localizationService.Translate("Move to the next slide to start the quiz.");
                startQuizTextRange.Font.Name          = this.font;
                startQuizTextRange.Font.Size          = 20;
                startQuizTextBox.TextEffect.FontBold  = MsoTriState.msoTrue;
                startQuizTextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;
            }
        }
        private void AddQuizToSlide(Slide slide)
        {
            var slideSessionModel = this.GetSlideSessionModel();

            if (!slideSessionModel.SessionTypeSet)
            {
                this.viewPresenter.ShowInNewWindow(
                    new SelectArsnovaTypeViewViewModel(
                        new ViewModelRequirements(
                            this.viewPresenter,
                            this.questionTypeTranslator,
                            this.localizationService,
                            this.sessionManager,
                            this.sessionInformationProvider,
                            this.slideManipulator,
                            slideSessionModel)),
                    vm =>
                {
                    vm.OnSelectArsnovaTypeViewClose += () => this.AddQuizToSlide(slide);
                });
                return;
            }

            var newQuestion = new SlideQuestionModel
            {
                QuestionType = slideSessionModel.SessionType == SessionType.ArsnovaClick
                                                                ? QuestionTypeEnum.SingleChoiceClick
                                                                : QuestionTypeEnum.SingleChoiceVoting,
                Index   = slideSessionModel.Questions.Count,
                Hashtag = slideSessionModel.Hashtag,
                RecalculatedOnlineIndex = slideSessionModel.Questions.Count(q => !q.Hidden),
                QuestionInfoSlideId     = slide.SlideID
            };

            slideSessionModel.Questions.Add(newQuestion);

            this.viewPresenter.ShowInNewWindow(
                new QuestionViewViewModel(this.CreateViewModelRequirements(slideSessionModel), newQuestion.Id, true));
        }
Пример #21
0
        public void StartClickQuestion(SlideSessionModel slideSessionModel, int questionIndex, Slide questionTimerSlideParam, Slide resultsSlideParam)
        {
            var validationResult = new ValidationResult();

            this.currentQuestionModel = slideSessionModel.Questions.First(q => q.Index == questionIndex);

            this.questionTimerSlide       = questionTimerSlideParam;
            this.resultsSlide             = resultsSlideParam;
            this.currentSlideSessionModel = slideSessionModel;

            validationResult = this.arsnovaClickService.StartNextQuestion(slideSessionModel, this.currentQuestionModel.RecalculatedOnlineIndex);

            this.countdown      = this.currentQuestionModel.Countdown;
            this.timer          = new Timer(1000);
            this.timer.Elapsed += this.HandleTimerEvent;
            this.timer.Start();

            if (!validationResult.Success)
            {
                throw new CommunicationException(validationResult.FailureMessage);
            }
        }
        private void SetQuestionState(SlideSessionModel slideSessionModel, SlideQuestionModel slideQuestionModel,
                                      bool sessionStatus)
        {
            this.CheckAuthentification(slideSessionModel);

            var lectureObject = this.GetLectureQuestion(slideSessionModel, slideQuestionModel.ArsnovaVotingId);

            lectureObject.active = sessionStatus;

            var apiPath     = "lecturerquestion/" + slideQuestionModel.ArsnovaVotingId + "/publish?_dc=" + this.ConvertToUnixTimestampString(DateTime.Now);
            var requestBody = JsonConvert.SerializeObject(lectureObject);

            try
            {
                var request = this.CreateWebRequest(slideSessionModel, apiPath, HttpMethod.Post);
                request = this.AddContentToRequest(request, requestBody);

                this.SendRequest(request);
            }
            catch (JsonReaderException exception)
            {
                throw new CommunicationException("Start question failed", exception);
            }
        }
        public void SetVotingResults(SlideQuestionModel slideQuestionModel, Slide resultsSlide,
                                     List <ArsnovaVotingResultReturnElement> results)
        {
            var floatLeft = 150;
            var floatTop  = 300;
            var width     = 650;
            var height    = 350;

            switch (slideQuestionModel.ChartType)
            {
            case Excel.XlChartType.xl3DColumnClustered:
            case Excel.XlChartType.xl3DBarClustered:
                floatLeft = 150;
                floatTop  = 150;
                break;

            case Excel.XlChartType.xl3DPie:
                floatLeft = 200;
                width     = 350;
                height    = 350;
                break;
            }
            this.AddChartToShape(slideQuestionModel, resultsSlide, null, results, floatLeft, floatTop, width, height);
        }
        public void SetClickResults(SlideQuestionModel slideQuestionModel, Slide resultsSlide, List <ResultModel> results)
        {
            // chart init dimensions
            var floatLeft = 150;
            var floatTop  = 280;
            var width     = 650;
            var height    = 250;

            var best10Responses = this.GetBest10Responses(slideQuestionModel, results);

            var resultsColumn1Text = string.Empty;
            var resultsColumn2Text = string.Empty;
            var i = 1;

            foreach (var response in best10Responses)
            {
                if (i % 2 == 0)
                {
                    resultsColumn2Text += $"{i}. {response.userNick}{Environment.NewLine}";
                }
                else
                {
                    resultsColumn1Text += $"{i}. {response.userNick}{Environment.NewLine}";
                }

                i++;
            }

            var leaderBoardColumn1TextBox =
                resultsSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 50, 120, 400, 200);
            var leaderBoardColumn1TextRange = leaderBoardColumn1TextBox.TextFrame.TextRange;

            leaderBoardColumn1TextRange.Text               = resultsColumn1Text;
            leaderBoardColumn1TextRange.Font.Name          = this.font;
            leaderBoardColumn1TextRange.Font.Size          = 20;
            leaderBoardColumn1TextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            var leaderBoardColumn2TextBox =
                resultsSlide.Shapes.AddTextbox(MsoTextOrientation.msoTextOrientationHorizontal, 500, 120, 400, 200);
            var leaderBoardColumn2TextRange = leaderBoardColumn2TextBox.TextFrame.TextRange;

            leaderBoardColumn2TextRange.Text               = resultsColumn2Text;
            leaderBoardColumn2TextRange.Font.Name          = this.font;
            leaderBoardColumn2TextRange.Font.Size          = 20;
            leaderBoardColumn2TextBox.TextEffect.Alignment = MsoTextEffectAlignment.msoTextEffectAlignmentCentered;

            // chart dimensions
            switch (slideQuestionModel.ChartType)
            {
            case Excel.XlChartType.xl3DColumnClustered:
            case Excel.XlChartType.xl3DBarClustered:
                // use default values
                break;

            case Excel.XlChartType.xlPie:
                floatLeft = 275;
                width     = 250;
                break;
            }

            this.AddChartToShape(slideQuestionModel, resultsSlide, results, null, floatLeft, floatTop, width, height);
        }
Пример #25
0
        private void InitializeWindowCommandBindings()
        {
            this.WindowCommandBindings.AddRange(
                new List <CommandBinding>
            {
                new CommandBinding(
                    NavigationButtonCommands.Finish,
                    (e, o) =>
                {
                    PresentationInformationStore.StoreSlideSessionModel(this.SlideSessionModel);

                    this.ViewPresenter.CloseWithoutPrompt();
                },
                    (e, o) => o.CanExecute = true),

                /*new CommandBinding(
                 *  NavigationButtonCommands.Back,
                 *  (e, o) =>
                 *  {
                 *      this.ViewPresenter.Show(
                 *          new SelectArsnovaTypeViewViewModel(this.GetViewModelRequirements()));
                 *  },
                 *  (e, o) => o.CanExecute = true),
                 * new CommandBinding(
                 *  NavigationButtonCommands.New,
                 *  (e, o) =>
                 *  {
                 *      var newQuestion = new SlideQuestionModel(this.QuestionTypeTranslator)
                 *                        {
                 *                            QuestionType = this.SlideSessionModel.SessionType
                 *                                           == SessionType.ArsnovaClick
                 *                                               ? QuestionTypeEnum.SingleChoiceClick
                 *                                               : QuestionTypeEnum.SingleChoiceVoting,
                 *                            Index = this.SlideSessionModel.Questions.Count
                 *                            // no new question without selected slide!
                 *                        };
                 *
                 *
                 *      this.SlideSessionModel.Questions.Add(newQuestion);
                 *
                 *      this.OpenQuestionEditDialog(newQuestion.Id, true);
                 *  },
                 *  (e, o) => o.CanExecute = true),*/
                new CommandBinding(
                    NavigationButtonCommands.Edit,
                    (e, o) =>
                {
                    this.OpenQuestionEditDialog(this.SelectedSlideQuestionModel.Id, false);
                },
                    (e, o) => o.CanExecute = this.SelectedSlideQuestionModel != null),
                new CommandBinding(
                    NavigationButtonCommands.Delete,
                    (e, o) =>
                {
                    var questionText =
                        $"{this.LocalizationService.Translate("Do you really want to delete this question?")}{Environment.NewLine}{Environment.NewLine}";
                    questionText += this.SelectedSlideQuestionModel.QuestionText;

                    var deleteQuestion = PopUpWindow.ConfirmationWindow(
                        this.LocalizationService.Translate("Delete"),
                        questionText);

                    if (deleteQuestion)
                    {
                        var questionModel = this.SelectedSlideQuestionModel;
                        SlideTracker.RemoveSlide(questionModel.QuestionInfoSlideId);
                        SlideTracker.RemoveSlide(questionModel.QuestionTimerSlideId.Value);
                        SlideTracker.RemoveSlide(questionModel.ResultsSlideId.Value);
                        this.SelectedSlideQuestionModel = null;
                        this.SlideSessionModel.Questions.Remove(questionModel);
                    }
                },
                    (e, o) => o.CanExecute = this.SelectedSlideQuestionModel != null)
            });
        }
 public void StartQuestion(SlideSessionModel slideSessionModel, SlideQuestionModel slideQuestionModel)
 {
     this.SetQuestionState(slideSessionModel, slideQuestionModel, true);
 }
        public List <ArsnovaVotingResultReturnElement> GetResults(SlideSessionModel slideSessionModel, SlideQuestionModel slideQuestionModel)
        {
            this.SetQuestionState(slideSessionModel, slideQuestionModel, false);

            var apiPath = "lecturerquestion/" + slideQuestionModel.ArsnovaVotingId + "/answer/?piround=1&_dc=" + this.ConvertToUnixTimestampString(DateTime.Now);

            try
            {
                var request = this.CreateWebRequest(slideSessionModel, apiPath, HttpMethod.Get, false);
                request.Headers.Add(HttpRequestHeader.AcceptEncoding, " sdch");

                var responseString = this.GetResponseString(slideSessionModel, request);

                return(JsonConvert.DeserializeObject <List <ArsnovaVotingResultReturnElement> >(responseString));
            }
            catch (JsonReaderException exception)
            {
                throw new CommunicationException("Get results or json deserialization failed", exception);
            }
        }
        private Tuple <string, string> UpdateQuestion(SlideSessionModel slideSessionModel, SlideQuestionModel questionModel, string arsnovaVotingQuestionId)
        {
            var oldQuestion = this.GetLectureQuestion(slideSessionModel, arsnovaVotingQuestionId);

            // update entries
            oldQuestion.questionType = this.QuestionTypeToVotingQuestionType(questionModel.QuestionType);
            oldQuestion.text         = questionModel.QuestionText;

            if (questionModel.QuestionType == QuestionTypeEnum.FreeTextVoting)
            {
                var answerOption = questionModel.AnswerOptions.First();

                oldQuestion.strictMode          = true;
                oldQuestion.textAnswerEnabled   = true;
                oldQuestion.correctAnswer       = answerOption.Text;
                oldQuestion.fixedAnswer         = true;
                oldQuestion.ignoreCaseSensitive = answerOption.ConfigCaseSensitive;
                oldQuestion.ignorePunctuation   = answerOption.ConfigUsePunctuation;
                oldQuestion.ignoreWhitespaces   = answerOption.ConfigTrimWhitespaces;
            }
            else
            {
                var answerOptionList = new List <PossibleAnswerObject>();

                foreach (var answerOption in questionModel.AnswerOptions)
                {
                    answerOptionList.Add(new PossibleAnswerObject
                    {
                        correct = answerOption.IsTrue,
                        text    = answerOption.Text,
                        value   = answerOption.IsTrue ? 10 : -10
                    });
                }

                oldQuestion.possibleAnswers = answerOptionList;
            }

            var apiPath     = "lecturerquestion/" + arsnovaVotingQuestionId;
            var requestBody = JsonConvert.SerializeObject(oldQuestion);

            try
            {
                var request = this.CreateWebRequest(slideSessionModel, apiPath, HttpMethod.Put);
                request = this.AddContentToRequest(request, requestBody);

                var responseString = this.GetResponseString(slideSessionModel, request);

                var newQuestionModel = JsonConvert.DeserializeObject <LectureQuestionModelWithId>(responseString);

                return(new Tuple <string, string>(newQuestionModel._id, newQuestionModel._rev));
            }
            catch (JsonReaderException exception)
            {
                throw new CommunicationException("Update question failed", exception);
            }
        }
        private List <ResultModel> GetCorrectFreeTextResults(SlideQuestionModel slideQuestionModel, List <ResultModel> responses)
        {
            var correctResponses  = new List <ResultModel>();
            var answerOption      = slideQuestionModel.AnswerOptions.First();
            var answerOptionText  = answerOption.Text;
            var punctutationRegex = new Regex(@"(\.)*(,)*(!)*("")*(;)*(\?)*");
            var whiteSpaceRegex   = new Regex(@" ");

            if (!answerOption.ConfigCaseSensitive)
            {
                answerOptionText = answerOptionText.ToLower();
            }

            if (!answerOption.ConfigUsePunctuation)
            {
                answerOptionText = punctutationRegex.Replace(answerOptionText, "");
            }

            if (answerOption.ConfigUseKeywords && !answerOption.ConfigTrimWhitespaces)
            {
                answerOptionText = whiteSpaceRegex.Replace(answerOptionText, "");
            }

            foreach (var response in responses)
            {
                var isCorrect    = false;
                var responseText = response.freeTextInputValue;

                if (!answerOption.ConfigCaseSensitive)
                {
                    responseText = responseText.ToLower();
                }

                if (!answerOption.ConfigUsePunctuation)
                {
                    responseText = punctutationRegex.Replace(responseText, "");
                }

                if (answerOption.ConfigUseKeywords)
                {
                    if (!answerOption.ConfigTrimWhitespaces)
                    {
                        responseText = whiteSpaceRegex.Replace(responseText, "");
                    }

                    isCorrect = answerOptionText == responseText;
                }
                else
                {
                    isCorrect = true;
                    var responseWords     = responseText.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    var answerOptionWords = answerOptionText.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (var answerOptionWord in answerOptionWords)
                    {
                        if (responseWords.Any(r => r != answerOptionWord))
                        {
                            isCorrect = false;
                        }
                    }
                }

                if (isCorrect)
                {
                    correctResponses.Add(response);
                }
            }

            return(correctResponses);
        }
        private void AddChartToShape(
            SlideQuestionModel slideQuestionModel,
            Slide resultsSlide,
            List <ResultModel> clickResults,
            List <ArsnovaVotingResultReturnElement> votingResults,
            int floatLeft,
            int floatTop,
            int width,
            int height)
        {
            var chartName         = "ARSnova Results Chart";
            var currentAssembly   = System.Reflection.Assembly.GetExecutingAssembly().Location;
            var excelWorkBookPath = Path.GetDirectoryName(currentAssembly) + "\\" + "resultsChartData.xlsx";

            var excelApp = new Excel.Application();
            var workBook = excelApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);

            try
            {
                if (File.Exists(excelWorkBookPath))
                {
                    File.Delete(excelWorkBookPath);
                }

                var workSheet = (Excel.Worksheet)(workBook.Worksheets[1]);
                workSheet.Name = "ARSnovaResults";
                Excel.Range dataRange;

                switch (slideQuestionModel.QuestionType)
                {
                case QuestionTypeEnum.MultipleChoiceClick:
                case QuestionTypeEnum.FreeTextClick:
                case QuestionTypeEnum.RangedQuestionClick:
                    var correctAnswerOptionsAmount = this.FilterForCorrectResponsesClick(slideQuestionModel, clickResults).Count;
                    var wrongAnswerOptionsAmount   = clickResults.Count - correctAnswerOptionsAmount;

                    this.SetExcelCellValue(workSheet, "A1", this.localizationService.Translate("Right"));
                    this.SetExcelCellValue(workSheet, "B1", correctAnswerOptionsAmount);
                    this.SetExcelCellValue(workSheet, "A2", this.localizationService.Translate("Wrong"));
                    this.SetExcelCellValue(workSheet, "B2", wrongAnswerOptionsAmount);

                    dataRange = workSheet.get_Range("A1", "B2");
                    break;

                case QuestionTypeEnum.SingleChoiceClick:
                case QuestionTypeEnum.YesNoClick:
                case QuestionTypeEnum.TrueFalseClick:
                case QuestionTypeEnum.SurveyClick:
                    // Range: One Column for each answer option
                    // One row for the amount of students voted for that answer option
                    for (var i = 0; i < slideQuestionModel.AnswerOptions.Count; i++)
                    {
                        var answerOption = slideQuestionModel.AnswerOptions.First(ao => ao.Position - 1 == i);
                        this.SetExcelCellValue(workSheet, $"A{i + 1}", answerOption.Text);
                        this.SetExcelCellValue(workSheet, $"B{i + 1}", clickResults.Count(r => r.answerOptionNumber.Contains(answerOption.Position - 1)));
                    }

                    dataRange = workSheet.get_Range("A1", $"B{slideQuestionModel.AnswerOptions.Count}");
                    break;

                // arsnova.voting
                case QuestionTypeEnum.SingleChoiceVoting:
                case QuestionTypeEnum.YesNoVoting:
                case QuestionTypeEnum.EvaluationVoting:
                case QuestionTypeEnum.GradsVoting:
                    for (var i = 0; i < slideQuestionModel.AnswerOptions.Count; i++)
                    {
                        var answerOption = slideQuestionModel.AnswerOptions.First(ao => ao.Position - 1 == i);
                        var resultItem   = votingResults.FirstOrDefault(vr => vr.answerText == answerOption.Text);
                        var answerCount  = resultItem?.answerCount ?? 0;

                        this.SetExcelCellValue(workSheet, $"A{i + 1}", answerOption.Text);
                        this.SetExcelCellValue(workSheet, $"B{i + 1}", answerCount);
                    }
                    dataRange = workSheet.get_Range("A1", $"B{slideQuestionModel.AnswerOptions.Count}");
                    break;

                case QuestionTypeEnum.MultipleChoiceVoting:
                    var correctAnswerOptionsCount = 0;
                    var wrongAnswerOptionsCount   = 0;

                    var correctAnswerOptionString = string.Empty;
                    for (var i = 0; i < slideQuestionModel.AnswerOptions.Count; i++)
                    {
                        var answerOption = slideQuestionModel.AnswerOptions.First(ao => ao.Position - 1 == i);
                        if (answerOption.IsTrue)
                        {
                            correctAnswerOptionString += "1";
                        }
                        else
                        {
                            correctAnswerOptionString += "0";
                        }
                    }


                    foreach (var resultElement in votingResults)
                    {
                        var answerTextString = resultElement.answerText.Replace(",", string.Empty);

                        if (correctAnswerOptionString == answerTextString)
                        {
                            correctAnswerOptionsCount += resultElement.answerCount;
                        }
                        else
                        {
                            wrongAnswerOptionsCount += resultElement.answerCount;
                        }
                    }

                    this.SetExcelCellValue(workSheet, "A1", this.localizationService.Translate("Right"));
                    this.SetExcelCellValue(workSheet, "B1", correctAnswerOptionsCount);
                    this.SetExcelCellValue(workSheet, "A2", this.localizationService.Translate("Wrong"));
                    this.SetExcelCellValue(workSheet, "B2", wrongAnswerOptionsCount);

                    dataRange = workSheet.get_Range("A1", "B2");
                    break;

                case QuestionTypeEnum.FreeTextVoting:
                    var correctFreeTextAnswers = this.GetCorrectFreeTextResultsVoting(slideQuestionModel, votingResults).Count;
                    var falseFreeTextAnswers   = votingResults.Count - correctFreeTextAnswers;

                    this.SetExcelCellValue(workSheet, "A1", this.localizationService.Translate("Right"));
                    this.SetExcelCellValue(workSheet, "B1", correctFreeTextAnswers);
                    this.SetExcelCellValue(workSheet, "A2", this.localizationService.Translate("Wrong"));
                    this.SetExcelCellValue(workSheet, "B2", falseFreeTextAnswers);

                    dataRange = workSheet.get_Range("A1", "B2");
                    break;

                default:
                    dataRange = workSheet.get_Range("A1", "B2");
                    break;
                    // 0,0,0,1 -> answeroption 4; 1,0,0,0 -> answeroption 1 etc.; create tuples of position and answerElemt
                    // 1,1,0,0 is a answerText of a mulitple choice question1
                }

                var chartObjects   = (Excel.ChartObjects)workSheet.ChartObjects(Type.Missing);
                var newChartObject = chartObjects.Add(floatLeft, floatTop, width, height);
                newChartObject.Name = chartName;

                newChartObject.Chart.ChartWizard(
                    dataRange,
                    slideQuestionModel.ChartType,
                    this.GetChartFormat(slideQuestionModel.ChartType), // chart format
                    Excel.XlRowCol.xlColumns,
                    1,                                                 //slideQuestionModel.AnswerOptions.Count - 1, // category labels
                    0,                                                 // series labels
                    false,                                             // has legend
                    slideQuestionModel.QuestionText,                   // title
                    this.localizationService.Translate("Answers"),     // category title
                    this.localizationService.Translate("Amount"),      // value title
                    Type.Missing);                                     // extra titel

                // save before edit - user needs to confirm the overwriting of the file -> don't save the file twice!
                //workBook.SaveAs(excelWorkBookPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                //Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

                // editing
                newChartObject.Chart.Perspective = 0;

                Excel.Series serie = newChartObject.Chart.SeriesCollection(1);

                // Evaluation, grades and surveys shouldn't be colorized
                switch (slideQuestionModel.QuestionType)
                {
                case QuestionTypeEnum.SingleChoiceVoting:
                case QuestionTypeEnum.YesNoVoting:
                case QuestionTypeEnum.SingleChoiceClick:
                case QuestionTypeEnum.YesNoClick:
                case QuestionTypeEnum.TrueFalseClick:
                    // normal evaluated graph (correct = green, any other answer option = red)
                    for (var i = 0; i < slideQuestionModel.AnswerOptions.Count; i++)
                    {
                        var point = (Excel.Point)serie.Points(i + 1);

                        point.Interior.Color = slideQuestionModel.AnswerOptions.First(ao => ao.Position == i + 1).IsTrue
                                ? Color.FromArgb(0, 255, 0).ToArgb()
                                : Color.FromArgb(0, 0, 255).ToArgb();
                    }
                    break;

                case QuestionTypeEnum.MultipleChoiceVoting:
                case QuestionTypeEnum.FreeTextVoting:
                case QuestionTypeEnum.MultipleChoiceClick:
                case QuestionTypeEnum.FreeTextClick:
                case QuestionTypeEnum.RangedQuestionClick:
                    // freetext, ranged and multiple: right and wrong only
                    // the part above sets the first point of the series as the correct answer and the second one as the false one
                    serie.Points(1).Interior.Color = Color.FromArgb(0, 255, 0).ToArgb();     // green
                    serie.Points(2).Interior.Color = Color.FromArgb(0, 0, 255).ToArgb();     // red
                    break;
                }

                // save again to avoid question before closing
                workBook.SaveAs(excelWorkBookPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

                // Copy chart to PowerPoint slide

                newChartObject.Copy();
                var shapeRange = resultsSlide.Shapes.Paste();

                shapeRange.Left = floatLeft;
                shapeRange.Top  = floatTop;

                shapeRange.LinkFormat.Update();

                excelApp.Quit();
            }
            catch (Exception e)
            {
                // Error handling?
                workBook.SaveAs(excelWorkBookPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
                                Type.Missing, Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
                excelApp.Quit();
            }
        }