Example #1
0
        /// <summary>
        /// Updates the statistics of the entries in the same way the given character would train this plan.
        /// </summary>
        /// <param name="scratchpad">The scratchpad.</param>
        /// <param name="applyRemappingPoints">if set to <c>true</c> [apply remapping points].</param>
        /// <param name="trainSkills">When true, the character will train every skill, increasing SP, etc.</param>
        /// <exception cref="System.ArgumentNullException">scratchpad</exception>
        public void UpdateStatistics(CharacterScratchpad scratchpad, bool applyRemappingPoints, bool trainSkills)
        {
            scratchpad.ThrowIfNull(nameof(scratchpad));

            CharacterScratchpad scratchpadWithoutImplants = scratchpad.Clone();

            scratchpadWithoutImplants.ClearImplants();
            DateTime time = DateTime.Now;

            // Update the statistics
            foreach (PlanEntry entry in Items)
            {
                // Apply the remapping
                if (applyRemappingPoints && entry.Remapping != null &&
                    entry.Remapping.Status == RemappingPointStatus.UpToDate)
                {
                    scratchpad.Remap(entry.Remapping);
                    scratchpadWithoutImplants.Remap(entry.Remapping);
                }

                // Update entry's statistics
                entry.UpdateStatistics(scratchpad, scratchpadWithoutImplants, ref time);

                // Update the scratchpad
                if (!trainSkills)
                {
                    continue;
                }

                scratchpad.Train(entry.Skill, entry.Level);
                scratchpadWithoutImplants.Train(entry.Skill, entry.Level);
            }
        }
        /// <summary>
        /// Updates controls on the form.
        /// </summary>
        /// <param name="remapping">An <see cref="AttributesOptimizer.Remapping"/> object</param>
        /// <param name="remappingList">List of remappings</param>
        private void UpdateForm(AttributesOptimizer.RemappingResult remapping, List <AttributesOptimizer.RemappingResult> remappingList)
        {
            // If the thread has been canceled, we stop right now to prevent an exception
            if (m_thread == null)
            {
                return;
            }

            // Hide the throbber and the waiting message
            this.throbber.State    = ThrobberState.Stopped;
            this.panelWait.Visible = false;

            // Update the attributes
            if (remapping != null)
            {
                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                UpdateForRemapping(remapping);
            }
            else
            {
                UpdateForRemappingList(remappingList);
            }

            // Update the plan order's column
            if (m_planEditor != null && (remapping != null || remappingList.Count != 0))
            {
                this.m_planEditor.ShowWithPluggable(this);
            }

            m_thread = null;
        }
Example #3
0
        /// <summary>
        /// Gets a character scratchpad representing this character after the provided skill levels trainings.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="trainings"></param>
        /// <returns></returns>
        public CharacterScratchpad After <T>(IEnumerable <T> trainings)
            where T : ISkillLevel
        {
            CharacterScratchpad scratchpad = new CharacterScratchpad(this);

            scratchpad.Train(trainings);
            return(scratchpad);
        }
Example #4
0
        /// <summary>
        /// Constructor without any remapping point associated.
        /// </summary>
        /// <param name="baseScratchpad">The base scratchpad.</param>
        /// <exception cref="System.ArgumentNullException">baseScratchpad</exception>
        public RemappingResult(CharacterScratchpad baseScratchpad)
        {
            baseScratchpad.ThrowIfNull(nameof(baseScratchpad));

            Skills         = new Collection <ISkillLevel>();
            BaseScratchpad = baseScratchpad;
            StartTime      = BaseScratchpad.TrainingTime;
        }
Example #5
0
        /// <summary>
        /// Constructor without any remapping point associated.
        /// </summary>
        /// <param name="baseScratchpad">The base scratchpad.</param>
        /// <exception cref="System.ArgumentNullException">baseScratchpad</exception>
        public RemappingResult(CharacterScratchpad baseScratchpad)
        {
            baseScratchpad.ThrowIfNull(nameof(baseScratchpad));

            Skills = new Collection<ISkillLevel>();
            BaseScratchpad = baseScratchpad;
            StartTime = BaseScratchpad.TrainingTime;
        }
Example #6
0
        /// <summary>
        /// Constructor for a result bound to a remapping point.
        /// </summary>
        /// <param name="point">Associated remapping point, may be null.</param>
        /// <param name="baseScratchpad"></param>
        public RemappingResult(RemappingPoint point, CharacterScratchpad baseScratchpad)
            : this(baseScratchpad)
        {
            if (point == null)
                return;

            Point = point;
        }
Example #7
0
        /// <summary>
        /// Constructor for a manually edited result from a base result.
        /// </summary>
        /// <param name="result">Associated remapping point, may be null.</param>
        /// <param name="bestScratchpad">The best scratchpad.</param>
        /// <exception cref="System.ArgumentNullException">result</exception>
        public RemappingResult(RemappingResult result, CharacterScratchpad bestScratchpad)
            : this(result?.Point, result?.BaseScratchpad)
        {
            result.ThrowIfNull(nameof(result));

            Skills.AddRange(result.Skills);
            BestScratchpad = bestScratchpad;
        }
Example #8
0
        /// <summary>
        /// Constructor for a manually edited result from a base result.
        /// </summary>
        /// <param name="result">Associated remapping point, may be null.</param>
        /// <param name="bestScratchpad">The best scratchpad.</param>
        /// <exception cref="System.ArgumentNullException">result</exception>
        public RemappingResult(RemappingResult result, CharacterScratchpad bestScratchpad)
            : this(result?.Point, result?.BaseScratchpad)
        {
            result.ThrowIfNull(nameof(result));

            Skills.AddRange(result.Skills);
            BestScratchpad = bestScratchpad;
        }
Example #9
0
        /// <summary>
        /// Constructor for a result bound to a remapping point.
        /// </summary>
        /// <param name="point">Associated remapping point, may be null.</param>
        /// <param name="baseScratchpad"></param>
        public RemappingResult(RemappingPoint point, CharacterScratchpad baseScratchpad)
            : this(baseScratchpad)
        {
            if (point == null)
            {
                return;
            }

            Point = point;
        }
Example #10
0
        /// <summary>
        /// Updates the statistics for the plan editor.
        /// </summary>
        /// <param name="plan"></param>
        /// <param name="areRemappingPointsActive"></param>
        /// <exception cref="System.ArgumentNullException">plan</exception>
        public void UpdateStatistics(BasePlan plan, out bool areRemappingPointsActive)
        {
            plan.ThrowIfNull(nameof(plan));

            areRemappingPointsActive = true;

            CharacterScratchpad scratchpad = CreateModifiedScratchpad(m_character.After(m_plan.ChosenImplantSet));

            plan.UpdateStatistics(scratchpad, true, true);
            plan.UpdateOldTrainingTimes();
        }
Example #11
0
        /// <summary>
        /// Updates the labels on the right of the numeric box.
        /// </summary>
        /// <param name="attrib"></param>
        /// <param name="myValue"></param>
        /// <param name="lblAdjust"></param>
        /// <param name="lblEffectiveAttribute"></param>
        private void UpdateAttributeLabels(EveAttribute attrib, int myValue, Control lblAdjust, Control lblEffectiveAttribute)
        {
            CharacterScratchpad characterScratchpad = m_plan.Character.After(m_plan.ChosenImplantSet);

            long baseAttr = characterScratchpad[attrib].EffectiveValue - characterScratchpad[attrib].ImplantBonus;
            long adjust   = myValue - baseAttr;

            lblAdjust.ForeColor        = adjust >= 0 ? SystemColors.ControlText : Color.Red;
            lblAdjust.Text             = $"{(adjust >= 0 ? "+" : string.Empty)}{adjust}";
            lblEffectiveAttribute.Text = characterScratchpad[attrib].EffectiveValue.ToNumericString(0);
        }
Example #12
0
        /// <summary>
        /// Gets a character scratchpad representing this character after a switch to the provided implant set.
        /// </summary>
        /// <param name="set">The set.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">set</exception>
        public CharacterScratchpad After(ImplantSet set)
        {
            set.ThrowIfNull(nameof(set));

            CharacterScratchpad scratchpad = new CharacterScratchpad(this);

            for (int i = 0; i < 5; i++)
            {
                EveAttribute attribute = (EveAttribute)i;
                scratchpad[attribute].ImplantBonus = set[attribute].Bonus;
            }
            return(scratchpad);
        }
Example #13
0
        /// <summary>
        /// Creates a scratchpad with the new implants values.
        /// </summary>
        /// <returns></returns>
        private CharacterScratchpad CreateModifiedScratchpad(BaseCharacter character)
        {
            // Creates a scratchpad with new implants
            CharacterScratchpad scratchpad = new CharacterScratchpad(character);

            scratchpad.Memory.ImplantBonus       += (int)nudMemory.Value - character.Memory.EffectiveValue;
            scratchpad.Charisma.ImplantBonus     += (int)nudCharisma.Value - character.Charisma.EffectiveValue;
            scratchpad.Intelligence.ImplantBonus += (int)nudIntelligence.Value - character.Intelligence.EffectiveValue;
            scratchpad.Perception.ImplantBonus   += (int)nudPerception.Value - character.Perception.EffectiveValue;
            scratchpad.Willpower.ImplantBonus    += (int)nudWillpower.Value - character.Willpower.EffectiveValue;

            return(scratchpad);
        }
Example #14
0
        /// <summary>
        /// Creates a scrahcpad with the new implants values.
        /// </summary>
        /// <returns></returns>
        private CharacterScratchpad CreateModifiedScratchpad()
        {
            // Creates a scratchpad with new implants
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);

            scratchpad.Memory.ImplantBonus       += (int)this.nudMemory.Value - m_character.Memory.PreLearningEffectiveAttribute;
            scratchpad.Charisma.ImplantBonus     += (int)this.nudCharisma.Value - m_character.Charisma.PreLearningEffectiveAttribute;
            scratchpad.Intelligence.ImplantBonus += (int)this.nudIntelligence.Value - m_character.Intelligence.PreLearningEffectiveAttribute;
            scratchpad.Perception.ImplantBonus   += (int)this.nudPerception.Value - m_character.Perception.PreLearningEffectiveAttribute;
            scratchpad.Willpower.ImplantBonus    += (int)this.nudWillpower.Value - m_character.Willpower.PreLearningEffectiveAttribute;

            return(scratchpad);
        }
Example #15
0
        /// <summary>
        /// Gets the total training time for this plan, using the given scratchpad.
        /// </summary>
        /// <param name="scratchpad">The scratchpad to use for the computation, may be null.</param>
        /// <param name="applyRemappingPoints"></param>
        /// <returns></returns>
        public TimeSpan GetTotalTime(CharacterScratchpad scratchpad, bool applyRemappingPoints)
        {
            // No scratchpad ? Let's create one
            if (scratchpad == null)
            {
                scratchpad = new CharacterScratchpad(Character);
            }

            // Train entries
            TimeSpan time = TimeSpan.Zero;

            scratchpad.TrainEntries(Items, applyRemappingPoints);
            return(scratchpad.TrainingTime - time);
        }
        /// <summary>
        /// Racalculating plan and summary page after change of a <see cref="AttributesOptimizationControl"/>.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="remapping"></param>
        void AttributesOptimizationControl_AttributeChanged(AttributesOptimizationControl control, AttributesOptimizer.RemappingResult remapping)
        {
            // Update the plan order's column
            if (m_planEditor != null)
            {
                if (m_strategy == Strategy.RemappingPoints)
                {
                    m_remappingDictionary[control] = remapping;
                    UpdateSummaryInformation(m_remappingDictionary.Values);
                }

                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                this.m_planEditor.ShowWithPluggable(this);
            }
        }
Example #17
0
        /// <summary>
        /// Updates the form controls to reflect the status of the Plan specified by the Plan property.
        /// </summary>
        private void UpdatePlanStatus()
        {
            if (m_loadoutFormat == LoadoutFormat.None)
            {
                return;
            }

            // Compute the skills to add
            m_skillsToAdd.Clear();
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);

            // Compute the training time for the prerequisites
            foreach (Item obj in m_objects)
            {
                scratchpad.Train(obj.Prerequisites.Where(x => m_character.Skills[x.Skill.ID].Level < x.Level));
            }
            m_skillsToAdd.AddRange(scratchpad.TrainedSkills);

            // All skills already trained ?
            if (m_skillsToAdd.Count == 0)
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible     = true;
                PlanedLabel.Text        = @"All skills already trained.";
                TrainTimeLabel.Visible  = false;
            }
            // Are skills already planned ?
            else if (m_plan.AreSkillsPlanned(m_skillsToAdd))
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible     = true;
                PlanedLabel.Text        = @"All skills already trained or planned.";
                TrainTimeLabel.Visible  = false;
            }
            // There is at least one untrained or non-planned skill
            else
            {
                AddToPlanButton.Enabled = true;
                PlanedLabel.Text        = String.Empty;
                PlanedLabel.Visible     = false;
                TrainTimeLabel.Visible  = true;

                // Compute training time
                TimeSpan trainingTime = m_character.GetTrainingTimeToMultipleSkills(m_skillsToAdd);
                TrainTimeLabel.Text = trainingTime.ToDescriptiveText(
                    DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
            }
        }
Example #18
0
        /// <summary>
        /// Recalculating plan and summary page after change of a <see cref="AttributesOptimizerControl"/>.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="AttributeChangedEventArgs"/> instance containing the event data.</param>
        private void AttributesOptimizationControl_AttributeChanged(object sender, AttributeChangedEventArgs e)
        {
            AttributesOptimizerControl control = (AttributesOptimizerControl)sender;

            if (m_strategy == AttributeOptimizationStrategy.RemappingPoints)
            {
                m_remappingDictionary[control] = e.Remapping;
                UpdateSummaryInformation(m_remappingDictionary.Values);
            }

            m_statisticsScratchpad = e.Remapping.BestScratchpad.Clone();
            m_remapping            = e.Remapping;

            // Update the plan order's column
            m_planEditor.ShowWithPluggable(this);
        }
        /// <summary>
        /// Update the plan status : training time, skills already trained, etc
        /// </summary>
        private void UpdatePlanningControls()
        {
            // Are all the prerequisites trained ?
            if (m_prerequisites.All(x => m_character.GetSkillLevel(x.Skill) >= x.Level))
            {
                btnPlan.Enabled      = false;
                lblPlanned.Visible   = true;
                lblPlanned.Text      = "All skills already trained.";
                lblTrainTime.Visible = false;
                return;
            }

            // Are all the prerequisites planned ?
            if (m_plan.AreSkillsPlanned(m_prerequisites.Where(x => m_character.Skills[x.Skill].Level < x.Level)))
            {
                btnPlan.Enabled      = false;
                lblPlanned.Visible   = true;
                lblPlanned.Text      = "All skills already trained or planned.";
                lblTrainTime.Visible = false;
                return;
            }

            // Compute the training time
            var scratchpad = new CharacterScratchpad(m_character);

            foreach (var entry in m_plan)
            {
                scratchpad.Train(entry);
            }

            var startTime = scratchpad.TrainingTime;

            foreach (var prereq in m_prerequisites)
            {
                scratchpad.Train(prereq);
            }

            var trainingTime = scratchpad.TrainingTime.Subtract(startTime);

            // update the labels
            btnPlan.Enabled      = true;
            lblPlanned.Text      = String.Empty;
            lblPlanned.Visible   = false;
            lblTrainTime.Visible = true;
            lblTrainTime.Text    = trainingTime.ToDescriptiveText(
                DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
        }
Example #20
0
        /// <summary>
        /// Update all the numeric boxes
        /// </summary>
        private async Task UpdateContentAsync()
        {
            gbAttributes.Text = $"Attributes of \"{m_plan.ChosenImplantSet.Name}\"";

            CharacterScratchpad characterScratchpad = m_plan.Character.After(m_plan.ChosenImplantSet);

            nudCharisma.Value     = characterScratchpad.Charisma.EffectiveValue;
            nudWillpower.Value    = characterScratchpad.Willpower.EffectiveValue;
            nudIntelligence.Value = characterScratchpad.Intelligence.EffectiveValue;
            nudPerception.Value   = characterScratchpad.Perception.EffectiveValue;
            nudMemory.Value       = characterScratchpad.Memory.EffectiveValue;

            // If the implant set isn't the active one we notify the user
            lblNotice.Visible = m_plan.ChosenImplantSet != m_character.ImplantSets.Current;

            //  Update all the times on the right pane
            await UpdateTimesAsync();
        }
Example #21
0
        /// <summary>
        /// Gets a string representation of the attribute.
        /// </summary>
        /// <param name="attrib">The attribute.</param>
        /// <param name="oldScratchpad">The old scratchpad.</param>
        /// <param name="newScratchpad">The new scratchpad.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">
        /// oldScratchpad
        /// or
        /// newScratchpad
        /// </exception>
        public static string GetStringForAttribute(EveAttribute attrib, CharacterScratchpad oldScratchpad,
                                                   CharacterScratchpad newScratchpad)
        {
            oldScratchpad.ThrowIfNull(nameof(oldScratchpad));

            newScratchpad.ThrowIfNull(nameof(newScratchpad));

            long bonusDifference = newScratchpad[attrib].Base - oldScratchpad[attrib].Base;

            if (bonusDifference == 0)
            {
                return(newScratchpad[attrib].ToString("%N (0) = %e = (%B + %r + %i)"));
            }

            return(newScratchpad[attrib].ToString(bonusDifference > 0
                ? $"%N (+{bonusDifference}) = %e = (%B + %r + %i)"
                : $"%N ({bonusDifference}) = %e = (%B + %r + %i)"));
        }
Example #22
0
        /// <summary>
        /// Update the plan status : training time, skills already known, etc
        /// </summary>
        private void UpdatePlanningControls()
        {
            // Are all the prerequisites known ?
            if (m_prerequisites.All(x => m_character.GetSkillLevel(x.Skill) > x.Level))
            {
                btnPlan.Enabled      = false;
                lblPlanned.Visible   = true;
                lblPlanned.Text      = "All skills already known.";
                lblTrainTime.Visible = false;
                return;
            }

            // Are all the prequisites planned
            if (m_plan.AreSkillsPlanned(m_prerequisites))
            {
                btnPlan.Enabled      = false;
                lblPlanned.Visible   = true;
                lblPlanned.Text      = "All skills already known or planned.";
                lblTrainTime.Visible = false;
                return;
            }

            // Compute the training time
            var scratchpad = new CharacterScratchpad(m_character);

            foreach (var entry in m_plan)
            {
                scratchpad.Train(entry);
            }
            var startTime = scratchpad.TrainingTime;

            foreach (var prereq in m_prerequisites)
            {
                scratchpad.Train(prereq);
            }
            var trainingTime = scratchpad.TrainingTime - startTime;

            // update the labels
            btnPlan.Enabled      = true;
            lblPlanned.Text      = "";
            lblPlanned.Visible   = false;
            lblTrainTime.Visible = true;
            lblTrainTime.Text    = Skill.TimeSpanToDescriptiveText(trainingTime, DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
        }
Example #23
0
        /// <summary>
        /// Update all the times on the right pane (base time, best time, etc).
        /// </summary>
        private async Task UpdateTimesAsync()
        {
            // Current (with implants)
            TimeSpan currentSpan = await UpdateTimesForCharacter(m_character.After(m_plan.ChosenImplantSet));

            // Current (without implants)
            ImplantSet noneImplantSet = m_character.ImplantSets.None;
            TimeSpan   baseSpan       = await UpdateTimesForCharacter(m_character.After(noneImplantSet));

            // This
            CharacterScratchpad scratchpad = CreateModifiedScratchpad(m_character.After(m_plan.ChosenImplantSet));
            TimeSpan            thisSpan   = await UpdateTimesForCharacter(scratchpad);

            lblCurrentSpan.Text = currentSpan.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
            lblCurrentDate.Text = DateTime.Now.Add(currentSpan).ToString(CultureConstants.DefaultCulture);
            lblBaseSpan.Text    = baseSpan.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
            lblBaseDate.Text    = DateTime.Now.Add(baseSpan).ToString(CultureConstants.DefaultCulture);
            lblThisSpan.Text    = thisSpan.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
            lblThisDate.Text    = DateTime.Now.Add(thisSpan).ToString(CultureConstants.DefaultCulture);

            // Are the new attributes better than current (without implants) ?
            lblComparedToBase.ForeColor = thisSpan > baseSpan
                ? Color.Red
                : thisSpan < baseSpan ? Color.Green : SystemColors.ControlText;
            lblComparedToBase.Text = thisSpan > baseSpan
                ? $"{thisSpan.Subtract(baseSpan).ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)} slower than current base"
                : thisSpan < baseSpan
                    ? $"{baseSpan.Subtract(thisSpan).ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)} faster than current base"
                    : @"No time difference than current base";

            // Are the new attributes better than current (with implants) ?
            lblComparedToCurrent.ForeColor = thisSpan > currentSpan
                ? Color.DarkRed
                : thisSpan < currentSpan ? Color.DarkGreen : SystemColors.ControlText;
            lblComparedToCurrent.Text = thisSpan > currentSpan
                ? $"{thisSpan.Subtract(currentSpan).ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)} slower than current"
                : thisSpan < currentSpan
                    ? $"{currentSpan.Subtract(thisSpan).ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)} faster than current"
                    : @"No time difference than current base";

            // Update the plan's pluggable column
            m_planEditor?.ShowWithPluggable(this);
        }
Example #24
0
        /// <summary>
        /// Performs the sort.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<PlanEntry> Sort()
        {
            int initialCount = m_entries.Count();

            // Apply first pass (priorities grouping)
            // We split the entries into multiple priority groups if that selection is made
            List<PlanScratchpad> groupedPlan = new List<PlanScratchpad>();
            var scratchpad = new CharacterScratchpad(m_character);

            if (m_groupByPriority)
            {
                foreach (var group in m_entries.GroupBy(x => x.Priority).OrderBy(x => x.Key))
                {
                    groupedPlan.Add(new PlanScratchpad(scratchpad, group));
                }
            }
            else
            {
                groupedPlan.Add(new PlanScratchpad(scratchpad, m_entries));
            }

            // Apply second pass (sorts)
            // We sort every group, and merge them once they're sorted
            List<PlanEntry> list = new List<PlanEntry>();

            foreach (var group in groupedPlan)
            {
                group.UpdateStatistics(scratchpad, false, false);
                group.SimpleSort(m_sort, m_reverseOrder);
                list.AddRange(group);
            }

            // Fix prerequisites order
            FixPrerequisitesOrder(list);

            // Check we didn't mess up anything
            if (initialCount != list.Count)
                throw new UnauthorizedAccessException("The sort algorithm messed up and deleted items");

            // Return
            return list;
        }
        /// <summary>
        /// Updates the controls with the values from the current remapping point.
        /// </summary>
        /// <param name="point"></param>
        /// <exception cref="System.ArgumentNullException">point</exception>
        public void UpdateValuesFrom(RemappingPoint point)
        {
            point.ThrowIfNull(nameof(point));

            // Creates a scratchpad with the base values from the provided point.
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character.After(m_plan.ChosenImplantSet));
            for (int i = 0; i < 5; i++)
            {
                scratchpad[(EveAttribute)i].Base = point[(EveAttribute)i];
            }

            RemappingResult remapping = new RemappingResult(m_remapping, scratchpad);
            remapping.Update();

            // Update the controls
            UpdateControls(m_character, m_plan, remapping, m_description);

            // Fires the event
            AttributeChanged?.ThreadSafeInvoke(this, new AttributeChangedEventArgs(remapping));
        }
Example #26
0
        /// <summary>
        /// Autonomously updates the status bar with the plan's training time.
        /// </summary>
        internal void UpdateStatusBar()
        {
            // Training time
            CharacterScratchpad scratchpad;

            if (m_plan.ChosenImplantSet != null)
            {
                scratchpad = m_plan.Character.After(m_plan.ChosenImplantSet);
            }
            else
            {
                scratchpad = new CharacterScratchpad(Character);
            }

            TimeSpan totalTime = planEditor.DisplayPlan.GetTotalTime(scratchpad, true);

            UpdateSkillStatusLabel(false, m_plan.Count, m_plan.UniqueSkillsCount);
            UpdateTimeStatusLabel(m_plan.Count, totalTime);
            UpdateCostStatusLabel(false, m_plan.TotalBooksCost, m_plan.NotKnownSkillBooksCost);
        }
Example #27
0
        /// <summary>
        /// Calculates new remapping from values of controls.
        /// </summary>
        private void Recalculate()
        {
            CharacterScratchpad scratchpad = m_remapping.BaseScratchpad.Clone();

            scratchpad.Memory.Base       = pbMEMRemappable.Value + EveConstants.CharacterBaseAttributePoints;
            scratchpad.Charisma.Base     = pbCHARemappable.Value + EveConstants.CharacterBaseAttributePoints;
            scratchpad.Willpower.Base    = pbWILRemappable.Value + EveConstants.CharacterBaseAttributePoints;
            scratchpad.Perception.Base   = pbPERRemappable.Value + EveConstants.CharacterBaseAttributePoints;
            scratchpad.Intelligence.Base = pbINTRemappable.Value + EveConstants.CharacterBaseAttributePoints;

            // Get remapping for provided attributes
            RemappingResult manualRemapping = new RemappingResult(m_remapping,
                                                                  scratchpad);

            manualRemapping.Update();
            UpdateControls(m_character, m_plan, manualRemapping, m_description);

            // Notify the changes
            AttributeChanged?.ThreadSafeInvoke(this, new AttributeChangedEventArgs(manualRemapping));
        }
        /// <summary>
        /// Updates the form controls to reflect the status of the Plan specified by the Plan property.
        /// </summary>
        private void UpdatePlanStatus()
        {
            // Compute the skills to add
            m_skillsToAdd.Clear();
            var scratchpad = new CharacterScratchpad(m_character);

            foreach (var obj in m_objects)
            {
                scratchpad.Train(obj.Prerequisites);
            }
            m_skillsToAdd.AddRange(scratchpad.TrainedSkills);

            // All skills already known ?
            if (m_skillsToAdd.Count == 0)
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible     = true;
                PlanedLabel.Text        = "All skills already known.";
                TrainTimeLabel.Visible  = false;
            }
            // Are skills already planned ?
            else if (m_plan.AreSkillsPlanned(m_skillsToAdd))
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible     = true;
                PlanedLabel.Text        = "All skills already known or planned.";
                TrainTimeLabel.Visible  = false;
            }
            // There is at least one unknown and non-planned skill
            else
            {
                AddToPlanButton.Enabled = true;
                PlanedLabel.Text        = "";
                PlanedLabel.Visible     = false;
                TrainTimeLabel.Visible  = true;

                // Compute training time
                TimeSpan trainingTime = m_character.GetTrainingTimeToMultipleSkills(m_skillsToAdd);
                TrainTimeLabel.Text = Skill.TimeSpanToDescriptiveText(trainingTime, DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
            }
        }
Example #29
0
        /// <summary>
        /// Will set the provided character scratchpad's base attributes as the target values to remap.
        /// </summary>
        /// <param name="newScratchpad">The scratchpad with the target base values to assign to this point</param>
        /// <param name="oldScratchpad">The scratchpad before we remapped</param>
        internal void SetBaseAttributes(CharacterScratchpad newScratchpad, CharacterScratchpad oldScratchpad)
        {
            // Update the status
            Status = RemappingPointStatus.UpToDate;

            // Initialize the string
            StringBuilder builder = new StringBuilder();

            // Scroll through attributes
            for (int i = 0; i < 5; i++)
            {
                // Compute the new base attribute
                EveAttribute attrib = (EveAttribute)i;
                m_attributes[i] = newScratchpad[attrib].Base;

                // Update description
                builder.AppendLine().Append(GetStringForAttribute(attrib, oldScratchpad, newScratchpad));
            }

            // Return the final string
            m_description = builder.ToString();
        }
Example #30
0
        /// <summary>
        /// Updates the controls with the values from the current remapping point.
        /// </summary>
        /// <param name="point"></param>
        /// <exception cref="System.ArgumentNullException">point</exception>
        public void UpdateValuesFrom(RemappingPoint point)
        {
            point.ThrowIfNull(nameof(point));

            // Creates a scratchpad with the base values from the provided point.
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character.After(m_plan.ChosenImplantSet));

            for (int i = 0; i < 5; i++)
            {
                scratchpad[(EveAttribute)i].Base = point[(EveAttribute)i];
            }

            RemappingResult remapping = new RemappingResult(m_remapping, scratchpad);

            remapping.Update();

            // Update the controls
            UpdateControls(m_character, m_plan, remapping, m_description);

            // Fires the event
            AttributeChanged?.ThreadSafeInvoke(this, new AttributeChangedEventArgs(remapping));
        }
Example #31
0
        /// <summary>
        /// Updates controls on the form.
        /// </summary>
        /// <param name="remapping">An <see cref="RemappingResult"/> object</param>
        /// <param name="remappingList">List of remappings</param>
        private void UpdateForm(RemappingResult remapping, ICollection <RemappingResult> remappingList)
        {
            // Update the attributes
            if (remapping != null)
            {
                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                UpdateForRemapping(remapping);
            }
            else
            {
                UpdateForRemappingList(remappingList);
            }

            // Update the plan order's column
            if ((remapping != null) || (remappingList.Count != 0))
            {
                m_planEditor.ShowWithPluggable(this);
            }

            // Hide the throbber and the waiting message
            panelWait.Hide();
        }
        /// <summary>
        /// Updates the controls with the values from the current remapping point.
        /// </summary>
        /// <param name="point"></param>
        public void UpdateValuesFrom(RemappingPoint point)
        {
            // Creates a scratchpad with the base values from the provided point.
            var scratchpad = new CharacterScratchpad(m_character);

            for (int i = 0; i < 5; i++)
            {
                scratchpad[(EveAttribute)i].Base = point[(EveAttribute)i];
            }

            var remapping = new AttributesOptimizer.RemappingResult(m_remapping, scratchpad);

            remapping.Update();

            // Update the controls
            UpdateControls(m_character, remapping);

            // Fires the event
            if (AttributeChanged != null)
            {
                AttributeChanged(this, remapping);
            }
        }
Example #33
0
        /// <summary>
        /// On load, fill the list and update the labels.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SuggestionWindow_Load(object sender, EventArgs e)
        {
            if (this.DesignMode)
            {
                return;
            }

            // Update the suggestions list
            lbSkills.Items.Clear();
            foreach (var entry in m_suggestions)
            {
                lbSkills.Items.Add(entry.ToString());
            }

            // Update the times labels
            CharacterScratchpad character = m_plan.Character.After(m_plan.ChosenImplantSet);
            TimeSpan            preTime   = m_plan.GetTotalTime(character, true);
            TimeSpan            postTime  = preTime.Subtract(m_suggestions.TimeBenefit);

            lblBeforeTime.Text = preTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
            lblAfterTime.Text  = postTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
            lblDiffTime.Text   = m_suggestions.TimeBenefit.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
        }
Example #34
0
        /// <summary>
        /// Updates the statistics of the entries in the same way the given character would train this plan.
        /// </summary>
        /// <param name="scratchpad">The scratchpad.</param>
        /// <param name="applyRemappingPoints">if set to <c>true</c> [apply remapping points].</param>
        /// <param name="trainSkills">When true, the character will train every skill, increasing SP, etc.</param>
        /// <exception cref="System.ArgumentNullException">scratchpad</exception>
        public void UpdateOldTrainingTimes(CharacterScratchpad scratchpad, bool applyRemappingPoints, bool trainSkills)
        {
            scratchpad.ThrowIfNull(nameof(scratchpad));

            // Update the statistics
            foreach (PlanEntry entry in Items)
            {
                // Apply the remapping
                if (applyRemappingPoints && entry.Remapping != null &&
                    entry.Remapping.Status == RemappingPointStatus.UpToDate)
                {
                    scratchpad.Remap(entry.Remapping);
                }

                // Update entry's statistics
                entry.UpdateOldTrainingTime(scratchpad);

                // Update the scratchpad
                if (trainSkills)
                {
                    scratchpad.Train(entry.Skill, entry.Level);
                }
            }
        }
Example #35
0
        /// <summary>
        /// Completes the items initialization or refresh them. Especially their columns values.
        /// </summary>
        private void UpdateListViewItems()
        {
            // When there is a pluggable (implants calculator or attributes optimizer)
            // This one provides us the scratchpad to update training times.
            m_areRemappingPointsActive = true;
            if (m_pluggable != null)
            {
                m_pluggable.UpdateStatistics(m_displayPlan, out m_areRemappingPointsActive);
            }
            else
            {
                var scratchpad = new CharacterScratchpad(m_character);
                if (m_plan.ChosenImplantSet != null)
                    scratchpad = scratchpad.After(m_plan.ChosenImplantSet);

                m_displayPlan.UpdateStatistics(scratchpad, true, true);
            }

            // Start updating the list
            lvSkills.BeginUpdate();
            try
            {
                NumberFormatInfo nfi = NumberFormatInfo.CurrentInfo;

                // Scroll through entries
                for (int i = 0; i < lvSkills.Items.Count; i++)
                {
                    ListViewItem lvi = lvSkills.Items[i];
                    var entry = lvi.Tag as PlanEntry;

                    // Add enough subitems to match the number of columns
                    while (lvi.SubItems.Count < lvSkills.Columns.Count)
                    {
                        lvi.SubItems.Add(String.Empty);
                    }

                    if (entry != null)
                    {
                        // Checks if this entry has not prereq-met
                        if (!entry.CharacterSkill.IsKnown)
                            lvi.ForeColor = Color.Red;

                        // Checks if this entry is a non-public skill
                        if (!entry.CharacterSkill.IsPublic)
                            lvi.ForeColor = Color.DarkRed;

                        // Checks if this entry is not known but has prereq-met
                        if (!entry.CharacterSkill.IsKnown && entry.CharacterSkill.IsPublic && entry.CharacterSkill.ArePrerequisitesMet)
                            lvi.ForeColor = Color.LightSlateGray;

                        // Checks if this entry is partially trained
                        bool level = (entry.Level == entry.CharacterSkill.Level + 1);
                        if (Settings.UI.PlanWindow.HighlightPartialSkills)
                        {
                            bool partiallyTrained = (entry.CharacterSkill.FractionCompleted > 0 && entry.CharacterSkill.FractionCompleted < 1);
                            if (level && partiallyTrained)
                                lvi.ForeColor = Color.Green;
                        }

                        HighlightQueuedSkills(lvi, entry);

                        // Checks if this entry is currently training (even if it's paused)
                        if (entry.CharacterSkill.IsTraining && level)
                        {
                            lvi.BackColor = Color.LightSteelBlue;
                            lvi.ForeColor = Color.Black;
                        }

                        // Checks whether this entry will be blocked
                        string blockingEntry = String.Empty;
                        if (Settings.UI.PlanWindow.HighlightConflicts)
                        {
                            bool isBlocked = Scheduler.SkillIsBlockedAt(entry.EndTime, out blockingEntry);
                            if (isBlocked)
                            {
                                lvi.ForeColor = Color.Red;
                                lvi.BackColor = Color.LightGray;
                            }
                        }

                        // Update every column
                        lvi.UseItemStyleForSubItems = (m_pluggable == null);
                        for (int columnIndex = 0; columnIndex < lvSkills.Columns.Count; columnIndex++)
                        {
                            // Regular columns (not pluggable-dependent)
                            if (lvSkills.Columns[columnIndex].Tag != null)
                            {
                                var columnSettings = (PlanColumnSettings)lvSkills.Columns[columnIndex].Tag;

                                lvi.SubItems[columnIndex].BackColor = lvi.BackColor;
                                lvi.SubItems[columnIndex].ForeColor = lvi.ForeColor;
                                lvi.SubItems[columnIndex].Text = GetColumnTextForItem(entry, columnSettings.Column, blockingEntry, nfi);
                            }
                            // Training time differences
                            else
                            {
                                TimeSpan timeDifference;
                                string result = String.Empty;
                                if (entry.OldTrainingTime < entry.TrainingTime)
                                {
                                    result = "+";
                                    timeDifference = entry.TrainingTime - entry.OldTrainingTime;
                                    lvi.SubItems[columnIndex].BackColor = lvi.BackColor;
                                    lvi.SubItems[columnIndex].ForeColor = Color.DarkRed;
                                }
                                else if (entry.OldTrainingTime > entry.TrainingTime)
                                {
                                    result = "-";
                                    timeDifference = entry.OldTrainingTime - entry.TrainingTime;
                                    lvi.SubItems[columnIndex].BackColor = lvi.BackColor;
                                    lvi.SubItems[columnIndex].ForeColor = Color.DarkGreen;
                                }
                                else
                                {
                                    timeDifference = TimeSpan.Zero;
                                    lvi.SubItems[columnIndex].BackColor = lvi.BackColor;
                                    lvi.SubItems[columnIndex].ForeColor = lvi.ForeColor;
                                }

                                result += timeDifference.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas);
                                lvi.SubItems[columnIndex].Text = result;
                            }
                        }
                    }
                    // The item represents a remapping point
                    else
                    {
                        var point = (RemappingPoint)lvi.Tag;
                        for (int columnIndex = 0; columnIndex < lvSkills.Columns.Count; columnIndex++)
                        {
                            var columnSettings = (PlanColumnSettings)lvSkills.Columns[columnIndex].Tag;

                            lvi.SubItems[columnIndex].Text = String.Empty;
                            lvi.SubItems[columnIndex].BackColor = m_remappingBackColor;
                            lvi.SubItems[columnIndex].ForeColor = m_remappingForeColor;

                            // We display the text in the SkillName column for better visibility
                            if (columnSettings != null && columnSettings.Column == PlanColumn.SkillName)
                                lvi.SubItems[columnIndex].Text = (m_areRemappingPointsActive ? point.ToString() : "Remapping (ignored)");
                        }
                    }
                }
            }
            finally
            {
                lvSkills.EndUpdate();
                UpdateStatusBar();
            }
        }
Example #36
0
        /// <summary>
        /// Gets a string representation of the attribute.
        /// </summary>
        /// <param name="attrib">The attribute.</param>
        /// <param name="oldScratchpad">The old scratchpad.</param>
        /// <param name="newScratchpad">The new scratchpad.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">
        /// oldScratchpad
        /// or
        /// newScratchpad
        /// </exception>
        public static string GetStringForAttribute(EveAttribute attrib, CharacterScratchpad oldScratchpad,
            CharacterScratchpad newScratchpad)
        {
            oldScratchpad.ThrowIfNull(nameof(oldScratchpad));

            newScratchpad.ThrowIfNull(nameof(newScratchpad));

            Int64 bonusDifference = newScratchpad[attrib].Base - oldScratchpad[attrib].Base;

            if (bonusDifference == 0)
                return newScratchpad[attrib].ToString("%N (0) = %e = (%B + %r + %i)");

            return newScratchpad[attrib].ToString(bonusDifference > 0
                ? $"%N (+{bonusDifference}) = %e = (%B + %r + %i)"
                : $"%N ({bonusDifference}) = %e = (%B + %r + %i)");
        }
Example #37
0
        /// <summary>
        /// Will set the provided character scratchpad's base attributes as the target values to remap.
        /// </summary>
        /// <param name="newScratchpad">The scratchpad with the target base values to assign to this point</param>
        /// <param name="oldScratchpad">The scratchpad before we remapped</param>
        internal void SetBaseAttributes(CharacterScratchpad newScratchpad, CharacterScratchpad oldScratchpad)
        {
            // Update the status
            this.m_status = PointStatus.UpToDate;

            // Initialize the string
            StringBuilder builder = new StringBuilder();

            // Scroll through attributes
            for (int i = 0; i < 5; i++)
            {
                // Compute the new base attribute
                EveAttribute attrib = (EveAttribute)i;
                m_attributes[i] = newScratchpad[attrib].Base;

                // Update description
                builder.AppendLine().Append(GetStringForAttribute(attrib, oldScratchpad, newScratchpad));
            }

            // Return the final string
            this.m_description = builder.ToString();
        }
Example #38
0
        /// <summary>
        /// Checks for pluggable.
        /// </summary>
        private void CheckForPluggable()
        {
            // When there is a pluggable (implants calculator or attributes optimizer)
            // This one provides us the scratchpad to update training times
            m_areRemappingPointsActive = true;
            if (m_pluggable != null)
            {
                bool areRemappingPointsActive;
                m_pluggable.UpdateStatistics(DisplayPlan, out areRemappingPointsActive);
                m_areRemappingPointsActive = areRemappingPointsActive;
            }
            else
            {
                CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);
                if (m_plan.ChosenImplantSet != null)
                    scratchpad = scratchpad.After(m_plan.ChosenImplantSet);

                DisplayPlan.UpdateStatistics(scratchpad, true, true);
            }
        }
Example #39
0
        /// <summary>
        /// Sends a mail alert for a skill completion
        /// </summary>
        /// <param name="queueList">Current Skill Queue</param>
        /// <param name="skill">Skill that has just completed</param>
        /// <param name="character">Character affected</param>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        public static void SendSkillCompletionMail(IList<QueuedSkill> queueList, QueuedSkill skill, Character character)
        {
            s_isTestMail = false;

            queueList.ThrowIfNull(nameof(queueList));

            skill.ThrowIfNull(nameof(skill));

            CCPCharacter ccpCharacter = character as CCPCharacter;

            // Current character isn't a CCP character, so can't have a Queue.
            if (ccpCharacter == null)
                return;

            string skillLevelText = $"{skill.SkillName} {Skill.GetRomanFromInt(skill.Level)}";
            string subjectText = $"{character.Name} has finished training {skillLevelText}.";

            // Message's first line
            StringBuilder body = new StringBuilder();
            body
                .AppendLine(subjectText)
                .AppendLine();

            // Next skills in queue
            if (queueList[0] != null)
            {
                string plural = queueList.Count > 1 ? "s" : String.Empty;
                body.AppendLine($"Next skill{plural} in queue:");

                foreach (QueuedSkill qskill in queueList)
                {
                    body.AppendLine($"- {qskill}");
                }
                body.AppendLine();
            }
            else
                body
                    .AppendLine("Character is not training.")
                    .AppendLine();

            // Skill queue less than a day
            if (ccpCharacter.SkillQueue.LessThanWarningThreshold)
            {
                TimeSpan skillQueueEndTime = ccpCharacter.SkillQueue.EndTime.Subtract(DateTime.UtcNow);
                TimeSpan timeLeft = SkillQueue.WarningThresholdTimeSpan.Subtract(skillQueueEndTime);

                // Skill queue empty?
                if (timeLeft > SkillQueue.WarningThresholdTimeSpan)
                    body.AppendLine("Skill queue is empty.");
                else
                {
                    string timeLeftText = skillQueueEndTime < TimeSpan.FromMinutes(1)
                        ? skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas)
                        : skillQueueEndTime.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas, false);

                    body.AppendLine($"Queue ends in {timeLeftText}.");
                }
            }

            // Short format (also for SMS)
            if (Settings.Notifications.UseEmailShortFormat)
            {
                SendMail(Settings.Notifications,
                    $"[STC] {character.Name} :: {skillLevelText}",
                    body.ToString());

                return;
            }

            // Long format
            if (character.Plans.Count > 0)
            {
                body.AppendLine("Next skills listed in plans:")
                    .AppendLine();
            }

            foreach (Plan plan in character.Plans)
            {
                if (plan.Count <= 0)
                    continue;

                // Print plan name
                CharacterScratchpad scratchpad = new CharacterScratchpad(character);
                body.AppendLine($"{plan.Name}:");

                // Scroll through entries
                int i = 0;
                int minDays = 1;
                foreach (PlanEntry entry in plan)
                {
                    TimeSpan trainTime = scratchpad.GetTrainingTime(entry.Skill, entry.Level,
                        TrainingOrigin.FromPreviousLevelOrCurrent);

                    // Only print the first three skills, and the very long skills
                    // (first limit is one day, then we add skills duration)
                    if (++i > 3 && trainTime.Days <= minDays)
                        continue;

                    if (i > 3)
                    {
                        // Print long message once
                        if (minDays == 1)
                            body.AppendLine().Append($"Longer skills from {plan.Name}:").AppendLine();

                        minDays = trainTime.Days + minDays;
                    }
                    body.Append($"\t{entry}");

                    // Notes
                    if (!string.IsNullOrEmpty(entry.Notes))
                        body.Append($" ({entry.Notes})");

                    // Training time
                    body
                        .Append(trainTime.Days > 0 ? $" - {trainTime.Days}d, {trainTime}" : $" - {trainTime}")
                        .AppendLine();
                }
                body.AppendLine();
            }

            SendMail(Settings.Notifications, subjectText, body.ToString());
        }
        /// <summary>
        /// Updates the controls with the values from the current remapping point.
        /// </summary>
        /// <param name="point"></param>
        public void UpdateValuesFrom(RemappingPoint point)
        {
            // Creates a scratchpad with the base values from the provided point.
            var scratchpad = new CharacterScratchpad(m_character.After(m_plan.ChosenImplantSet));
            for (int i = 0; i < 5; i++)
            {
                scratchpad[(EveAttribute)i].Base = point[(EveAttribute)i];
            }

            var remapping = new AttributesOptimizer.RemappingResult(m_remapping, scratchpad);
            remapping.Update();

            // Update the controls
            UpdateControls(m_character, m_plan, remapping, m_description);

            // Fires the event
            if (AttributeChanged != null)
                AttributeChanged(this, remapping);
        }
Example #41
0
        /// <summary>
        /// Exports the character's selected skills as plan.
        /// </summary>
        /// <param name="character">The character.</param>
        /// <param name="selectedSkills">The selected skills.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException"></exception>
        public static async Task ExportCharacterSkillsAsPlanAsync(Character character, IEnumerable<Skill> selectedSkills = null)
        {
            character.ThrowIfNull(nameof(character));

            // Create a character without any skill
            CharacterScratchpad scratchpad = new CharacterScratchpad(character);
            scratchpad.ClearSkills();

            // Create a new plan
            Plan plan = new Plan(scratchpad) { Name = "Skills Plan" };

            IEnumerable<Skill> skills = selectedSkills ?? character.Skills.Where(skill => skill.IsPublic);

            // Add all trained skill levels that the character has trained so far
            foreach (Skill skill in skills)
            {
                plan.PlanTo(skill, skill.Level);
            }

            await ExportPlanAsync(plan, character);
        }
        /// <summary>
        /// Updates controls on the form.
        /// </summary>
        /// <param name="remapping">An <see cref="RemappingResult"/> object</param>
        /// <param name="remappingList">List of remappings</param>
        private void UpdateForm(RemappingResult remapping, ICollection<RemappingResult> remappingList)
        {
            // Update the attributes
            if (remapping != null)
            {
                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                UpdateForRemapping(remapping);
            }
            else
                UpdateForRemappingList(remappingList);

            // Update the plan order's column
            if ((remapping != null) || (remappingList.Count != 0))
                m_planEditor.ShowWithPluggable(this);

            // Hide the throbber and the waiting message
            panelWait.Hide();
        }
        /// <summary>
        /// Recalculating plan and summary page after change of a <see cref="AttributesOptimizerControl"/>.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="AttributeChangedEventArgs"/> instance containing the event data.</param>
        private void AttributesOptimizationControl_AttributeChanged(object sender, AttributeChangedEventArgs e)
        {
            AttributesOptimizerControl control = (AttributesOptimizerControl)sender;

            if (m_strategy == AttributeOptimizationStrategy.RemappingPoints)
            {
                m_remappingDictionary[control] = e.Remapping;
                UpdateSummaryInformation(m_remappingDictionary.Values);
            }

            m_statisticsScratchpad = e.Remapping.BestScratchpad.Clone();
            m_remapping = e.Remapping;

            // Update the plan order's column
            m_planEditor.ShowWithPluggable(this);
        }
Example #44
0
        /// <summary>
        /// Autonomously updates the status bar with the plan's training time.
        /// </summary>
        internal void UpdateStatusBar()
        {
            // Training time
            CharacterScratchpad scratchpad;
            if (m_plan.ChosenImplantSet != null)
            {
                scratchpad = m_plan.Character.After(m_plan.ChosenImplantSet);
            }
            else
            {
                scratchpad = new CharacterScratchpad(Character);
            }

            TimeSpan totalTime = planEditor.DisplayPlan.GetTotalTime(scratchpad, true);

            UpdateSkillStatusLabel(false, m_plan.Count, m_plan.UniqueSkillsCount);
            UpdateTimeStatusLabel(m_plan.Count, totalTime);
            UpdateCostStatusLabel(false, m_plan.TotalBooksCost, m_plan.NotKnownSkillBooksCost);
        }
Example #45
0
        /// <summary>
        /// Updates the pie chart display
        /// </summary>
        private void UpdatePieChart()
        {
            // Prevents updating before OnLoad() completed.
            if (planSelector.SelectedIndex < 0) return;

            int groupCount = StaticSkills.AllGroups.Count();
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);

            // Retrieve the selected Plan
            Plan plan = null;
            if (planSelector.SelectedIndex > 0)
            {
                plan = m_character.Plans[planSelector.SelectedIndex - 1];

                // Updates the scratchpad
                foreach (var entry in plan) scratchpad.Train(entry);
            }

            // Get group to index map and groups list
            List<SkillGroup> groups = new List<SkillGroup>();
            Dictionary<StaticSkillGroup, int> indices = new Dictionary<StaticSkillGroup, int>();
            foreach (var group in StaticSkills.AllGroups)
            {
                indices[group] = groups.Count;
                groups.Add(m_character.SkillGroups[group.Name]);
            }

            // Get start SP, before plan
            decimal[] srcSkillPoints = new decimal[groupCount];
            foreach(var skillGroup in groups)
            {
                int groupIndex = indices[skillGroup.StaticData];
                srcSkillPoints[groupIndex] = skillGroup.TotalSP;
            }

            // Get target SP and skills count, after plan
            int[] skillCounts = new int[groupCount];
            decimal[] targetSkillPoints = new decimal[groupCount];
            foreach (StaticSkill skill in StaticSkills.AllSkills)
            {
                int sp = scratchpad.GetSkillPoints(skill);
                int groupIndex = indices[skill.Group];

                targetSkillPoints[groupIndex] += sp;
                if (sp != 0) skillCounts[groupIndex]++;
            }

            // Get groups names and descriptions
            string[] names = new string[groupCount];
            string[] descriptions = new string[groupCount];
            for(int i=0; i<srcSkillPoints.Length; i++)
            {
                names[i] = groups[i].Name;
                descriptions[i] = groups[i].Name;

                decimal srcSP = srcSkillPoints[i];
                decimal destSP = targetSkillPoints[i];

                StringBuilder description = new StringBuilder();
                description.AppendFormat(CultureConstants.DefaultCulture, "{0} ({1} skills, {2:#,###} skillpoints", names[i], skillCounts[i], srcSP);
                if (srcSP != destSP)
                {
                    description.AppendFormat(CultureConstants.DefaultCulture, " / {0:#,###} after plan completion", destSP);
                }
                description.Append(")");
                descriptions[i] = description.ToString();
            }

            // Merge minor groups
            if (mergeMinorCheck.Checked)
            {
                Merge(ref targetSkillPoints, ref names, ref descriptions);
            }

            // Compute the slices displacements
            int tinyGroups = 0;
            float[] slicesDiscplacements = new float[targetSkillPoints.Length];
            for(int i=0; i < targetSkillPoints.Length; i++)
            {
                slicesDiscplacements[i] = (targetSkillPoints[i] < 100000) ? 0.06F + (0.008F * ++tinyGroups) : 0.05F;
            }

            // Assign and sort
            skillPieChartControl.Values = targetSkillPoints;
            skillPieChartControl.Texts = names;
            skillPieChartControl.ToolTips = descriptions;
            skillPieChartControl.SliceRelativeDisplacements = slicesDiscplacements;
            skillPieChartControl.OrderSlices(sortBySizeCheck.Checked);
        }
        /// <summary>
        /// Updates the form controls to reflect the status of the Plan specified by the Plan property.
        /// </summary>
        private void UpdatePlanStatus()
        {
            // Compute the skills to add
            m_skillsToAdd.Clear();
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);
            Character character = m_character as Character;
            foreach (var obj in m_objects)
            {
                scratchpad.Train(obj.Prerequisites.Where(x => character.Skills[x.Skill].Level < x.Level));
            }
            m_skillsToAdd.AddRange(scratchpad.TrainedSkills);

            // All skills already trained ?
            if (m_skillsToAdd.Count == 0)
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible = true;
                PlanedLabel.Text = "All skills already trained.";
                TrainTimeLabel.Visible = false;
            }
            // Are skills already planned ?
            else if (m_plan.AreSkillsPlanned(m_skillsToAdd))
            {
                AddToPlanButton.Enabled = false;
                PlanedLabel.Visible = true;
                PlanedLabel.Text = "All skills already trained or planned.";
                TrainTimeLabel.Visible = false;
            }
            // There is at least one untrained or non-planned skill
            else
            {
                AddToPlanButton.Enabled = true;
                PlanedLabel.Text = String.Empty;
                PlanedLabel.Visible = false;
                TrainTimeLabel.Visible = true;

                // Compute training time
                TimeSpan trainingTime = m_character.GetTrainingTimeToMultipleSkills(m_skillsToAdd);
                TrainTimeLabel.Text = trainingTime.ToDescriptiveText(
                    DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
            }
        }
        /// <summary>
        /// Update the plan status : training time, skills already trained, etc
        /// </summary>
        private void UpdatePlanningControls()
        {
            btnPlan.Visible = m_plan != null;
            lblTrainTime.Visible = TrainingTimeLabel.Visible = m_character != null;

            if (m_character == null)
                return;

            btnPlan.Enabled = false;

            if (!m_prerequisites.Any())
                return;

            // Are all the prerequisites trained ?
            if (m_prerequisites.All(x => m_character.GetSkillLevel(x.Skill) >= x.Level))
            {
                lblPlanned.Show();
                lblPlanned.Text = @"All skills already trained.";
                lblTrainTime.Hide();
                return;
            }

            if (m_plan == null)
            {
                lblPlanned.Show();
                lblPlanned.Text = @"Some skills need training.";
                lblTrainTime.Hide();
                return;
            }

            // Are all the prerequisites planned ?
            if (m_plan.AreSkillsPlanned(m_prerequisites.Where(x => m_character.Skills[x.Skill.ID].Level < x.Level)))
            {
                lblPlanned.Show();
                lblPlanned.Text = @"All skills already trained or planned.";
                lblTrainTime.Hide();
                return;
            }

            // Compute the training time
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);
            foreach (PlanEntry entry in m_plan)
            {
                scratchpad.Train(entry);
            }

            TimeSpan startTime = scratchpad.TrainingTime;
            foreach (StaticSkillLevel prereq in m_prerequisites)
            {
                scratchpad.Train(prereq);
            }

            TimeSpan trainingTime = scratchpad.TrainingTime.Subtract(startTime);

            // Update the labels
            lblTrainTime.Text = trainingTime.ToDescriptiveText(
                DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
            lblTrainTime.Show();
            lblPlanned.Text = String.Empty;
            lblPlanned.Hide();
            btnPlan.Enabled = true;
        }
Example #48
0
        /// <summary>
        /// Updates the pie chart display
        /// </summary>
        private void UpdatePieChart()
        {
            // Prevents updating before OnLoad() completed.
            if (planSelector.SelectedIndex < 0)
            {
                return;
            }

            int groupCount = StaticSkills.AllGroups.Count();
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_character);

            // Retrieve the selected Plan
            if (planSelector.SelectedIndex > 0)
            {
                Plan plan = m_character.Plans[planSelector.SelectedIndex - 1];

                // Updates the scratchpad
                foreach (PlanEntry entry in plan)
                {
                    scratchpad.Train(entry);
                }
            }


            // Get group to index map and groups list
            List <SkillGroup> groups = new List <SkillGroup>();
            Dictionary <StaticSkillGroup, int> indices = new Dictionary <StaticSkillGroup, int>();

            foreach (StaticSkillGroup group in StaticSkills.AllGroups)
            {
                indices[group] = groups.Count;
                groups.Add(m_character.SkillGroups[group.ID]);
            }

            // Get start SP, before plan
            decimal[] srcSkillPoints = new decimal[groupCount];
            foreach (SkillGroup skillGroup in groups)
            {
                int groupIndex = indices[skillGroup.StaticData];
                srcSkillPoints[groupIndex] = skillGroup.TotalSP;
            }

            // Get target SP and skills count, after plan
            int[]     skillCounts       = new int[groupCount];
            decimal[] targetSkillPoints = new decimal[groupCount];
            foreach (StaticSkill skill in StaticSkills.AllSkills)
            {
                Int64 sp         = scratchpad.GetSkillPoints(skill);
                int   groupIndex = indices[skill.Group];

                targetSkillPoints[groupIndex] += sp;
                if (sp != 0)
                {
                    skillCounts[groupIndex]++;
                }
            }

            // Get groups names and descriptions
            string[] names        = new string[groupCount];
            string[] descriptions = new string[groupCount];
            for (int i = 0; i < srcSkillPoints.Length; i++)
            {
                names[i]        = groups[i].Name;
                descriptions[i] = groups[i].Name;

                decimal srcSP  = srcSkillPoints[i];
                decimal destSP = targetSkillPoints[i];

                StringBuilder description = new StringBuilder();
                description.Append($"{names[i]} ({skillCounts[i]} skills, {srcSP:N0} skillpoints");
                if (srcSP != destSP)
                {
                    description.Append($" / {destSP:N0} after plan completion");
                }

                description.Append(")");
                descriptions[i] = description.ToString();
            }

            // Merge minor groups
            if (mergeMinorCheck.Checked)
            {
                Merge(ref targetSkillPoints, ref names, ref descriptions);
            }

            // Compute the slices displacements
            int tinyGroups = 0;

            float[] slicesDiscplacements = new float[targetSkillPoints.Length];
            for (int i = 0; i < targetSkillPoints.Length; i++)
            {
                slicesDiscplacements[i] = targetSkillPoints[i] < 100000 ? 0.06F + 0.008F * ++tinyGroups : 0.05F;
            }

            // Assign and sort
            skillPieChartControl.Values(targetSkillPoints);
            skillPieChartControl.Texts(names);
            skillPieChartControl.ToolTips(descriptions);
            skillPieChartControl.SliceRelativeDisplacements(slicesDiscplacements);
            skillPieChartControl.OrderSlices(sortBySizeCheck.Checked);
        }
Example #49
0
        /// <summary>
        /// Sends a mail alert for a skill completion
        /// </summary>
        /// <param name="queueList">Current Skill Queue</param>
        /// <param name="skill">Skill that has just completed</param>
        /// <param name="character">Character affected</param>
        /// <returns></returns>
		public static bool SendSkillCompletionMail(IList<QueuedSkill> queueList, QueuedSkill skill, Character character)
		{
            CCPCharacter ccpCharacter = character as CCPCharacter;

            // Current character isn't a CCP character, so can't have a Queue.
            if (ccpCharacter == null)
                return false;
            
            string charName = character.Name;
            string skillName = skill.SkillName;
            string skillLevelString = Skill.GetRomanForInt(skill.Level);

            var skillQueueEndTime = ccpCharacter.SkillQueue.EndTime;
            bool freeTime = skillQueueEndTime < DateTime.UtcNow.AddHours(24);
            TimeSpan timeLeft = DateTime.UtcNow.AddHours(24).Subtract(skillQueueEndTime);
            string timeLeftText = timeLeft.ToDescriptiveText(DescriptiveTextOptions.IncludeCommas, false);

            // Message's first line
            StringBuilder body = new StringBuilder();
            body.AppendFormat(CultureConstants.DefaultCulture, "{0} has finished training {1} {2}.{3}{3}", charName, skillName, skillLevelString, Environment.NewLine);
            
            // Next skills in queue
            if (queueList[0] != null)
            {
                body.AppendFormat(CultureConstants.DefaultCulture, "Next skill{0} in queue:{1}", (queueList.Count > 1 ? "s" : String.Empty), Environment.NewLine);
                foreach (var qskill in queueList)
                {
                    body.AppendFormat(CultureConstants.DefaultCulture, "- {0}{1}", qskill, Environment.NewLine);
                }
                body.AppendLine();
            }
            else
            {
                body.AppendFormat(CultureConstants.DefaultCulture, "Character is not training.{0}{0}", Environment.NewLine);
            }

            // Free room in skill queue
            if (freeTime)
                body.AppendFormat(CultureConstants.DefaultCulture, "There is also {0} free room in skill queue.{1}", timeLeftText, Environment.NewLine);

            // Short format (also for SMS)
            if (Settings.Notifications.UseEmailShortFormat)
            {
                return SendMail(Settings.Notifications, String.Format(CultureConstants.DefaultCulture, "[STC] {0} :: {1} {2}", charName, skillName, skillLevelString), body.ToString());
            }

            // Long format
            if (character.Plans.Count > 0) body.AppendFormat(CultureConstants.DefaultCulture, "Next skills listed in plans:{0}{0}", Environment.NewLine);

            foreach (var plan in character.Plans)
			{
				if (plan.Count > 0)
				{
                    // Print plan name
                    CharacterScratchpad scratchpad = new CharacterScratchpad(character);
                    body.AppendFormat(CultureConstants.DefaultCulture, "{0}:{1}", plan.Name, Environment.NewLine);

                    // Scroll through entries
					int i = 0;
					int minDays = 1;
					foreach (PlanEntry entry in plan)
					{
						TimeSpan trainTime = scratchpad.GetTrainingTime(entry.Skill, entry.Level, TrainingOrigin.FromPreviousLevelOrCurrent);

						// Only print the first three skills, and the very long skills
                        // (first limit is one day, then we add skills duration)
						if (++i <= 3 || trainTime.Days > minDays)
						{
							if (i > 3)
							{
								// Print long message once
								if (minDays == 1)
								{
                                    body.AppendFormat(CultureConstants.DefaultCulture, "{1}Longer skills from {0}:{1}", plan.Name, Environment.NewLine);
								}

								minDays = trainTime.Days + minDays;
							}
                            body.AppendFormat(CultureConstants.DefaultCulture, "\t{0}", entry);

                            // Notes
							if (entry.Notes != null && entry.Notes.Length > 0)
							{
                                body.AppendFormat(CultureConstants.DefaultCulture, " ({0})", entry.Notes);
							}

                            // Training time
							if (trainTime.Days > 0)
							{
                                body.AppendFormat(CultureConstants.DefaultCulture, " - {0}d, {1}", trainTime.Days, trainTime);
							}
							else
							{
                                body.AppendFormat(CultureConstants.DefaultCulture, " - {0}", trainTime);
							}

							body.AppendLine();
						}
					}
					body.AppendLine();
				}
			}

            string subject = String.Format(CultureConstants.DefaultCulture, "{0} has finished training {1} {2}", charName, skillName, skillLevelString);
			return SendMail(Settings.Notifications, subject, body.ToString());
		}
        /// <summary>
        /// Updates controls on the form.
        /// </summary>
        /// <param name="remapping">An <see cref="AttributesOptimizer.Remapping"/> object</param>
        /// <param name="remappingList">List of remappings</param>
        private void UpdateForm(AttributesOptimizer.RemappingResult remapping, List<AttributesOptimizer.RemappingResult> remappingList)
        {
            // If the thread has been canceled, we stop right now to prevent an exception
            if (m_thread == null)
                return;

            // Hide the throbber and the waiting message
            this.throbber.State = ThrobberState.Stopped;
            this.panelWait.Visible = false;

            this.tabControl.Controls.Clear();

            // Update the attributes
            if (remapping != null)
            {
                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                UpdateForRemapping(remapping);
            }
            else
            {
                UpdateForRemappingList(remappingList);
            }

            // Update the plan order's column
            if (m_planEditor != null && (remapping != null || remappingList.Count != 0))
                this.m_planEditor.ShowWithPluggable(this);
        }
        /// <summary>
        /// Update the plan status : training time, skills already trained, etc
        /// </summary>
        private void UpdatePlanningControls()
        {
            // Are all the prerequisites trained ?
            if (m_prerequisites.All(x => m_character.GetSkillLevel(x.Skill) >= x.Level))
            {
                btnPlan.Enabled = false;
                lblPlanned.Visible = true;
                lblPlanned.Text = "All skills already trained.";
                lblTrainTime.Visible = false;
                return;
            }

            // Are all the prerequisites planned ?
            if (m_plan.AreSkillsPlanned(m_prerequisites.Where(x => m_character.Skills[x.Skill].Level < x.Level)))
            {
                btnPlan.Enabled = false;
                lblPlanned.Visible = true;
                lblPlanned.Text = "All skills already trained or planned.";
                lblTrainTime.Visible = false;
                return;
            }

            // Compute the training time
            var scratchpad = new CharacterScratchpad(m_character);
            foreach (var entry in m_plan)
            {
                scratchpad.Train(entry);
            }

            var startTime = scratchpad.TrainingTime;
            foreach (var prereq in m_prerequisites)
            {
                scratchpad.Train(prereq);
            }

            var trainingTime = scratchpad.TrainingTime.Subtract(startTime);

            // update the labels
            btnPlan.Enabled = true;
            lblPlanned.Text = String.Empty;
            lblPlanned.Visible = false;
            lblTrainTime.Visible = true;
            lblTrainTime.Text = trainingTime.ToDescriptiveText(
                DescriptiveTextOptions.IncludeCommas | DescriptiveTextOptions.SpaceText);
        }
        /// <summary>
        /// Racalculating plan and summary page after change of a <see cref="AttributesOptimizationControl"/>.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="remapping"></param>
        void AttributesOptimizationControl_AttributeChanged(AttributesOptimizationControl control, AttributesOptimizer.RemappingResult remapping)
        {
            // Update the plan order's column
            if (m_planEditor != null)
            {
                if (m_strategy == Strategy.RemappingPoints)
                {
                    m_remappingDictionary[control] = remapping;
                    UpdateSummaryInformation(m_remappingDictionary.Values);
                }

                m_statisticsScratchpad = remapping.BestScratchpad.Clone();
                this.m_planEditor.ShowWithPluggable(this);
                m_remapping = remapping;
            }
        }
Example #53
0
        /// <summary>
        /// Creates a scratchpad with the new implants values.
        /// </summary>
        /// <returns></returns>
        private CharacterScratchpad CreateModifiedScratchpad()
        {
            // Creates a scratchpad with new implants
            m_characterScratchpad = m_character.After(m_set);
            CharacterScratchpad scratchpad = new CharacterScratchpad(m_characterScratchpad);

            scratchpad.Memory.ImplantBonus += (int)nudMemory.Value - m_characterScratchpad.Memory.EffectiveValue;
            scratchpad.Charisma.ImplantBonus += (int)nudCharisma.Value - m_characterScratchpad.Charisma.EffectiveValue;
            scratchpad.Intelligence.ImplantBonus += (int)nudIntelligence.Value - m_characterScratchpad.Intelligence.EffectiveValue;
            scratchpad.Perception.ImplantBonus += (int)nudPerception.Value - m_characterScratchpad.Perception.EffectiveValue;
            scratchpad.Willpower.ImplantBonus += (int)nudWillpower.Value - m_characterScratchpad.Willpower.EffectiveValue;

            return scratchpad;
        }
Example #54
0
        /// <summary>
        /// Gets a string representation of the attribute
        /// </summary>
        /// <param name="attrib"></param>
        /// <param name="oldScratchpad"></param>
        /// <param name="newScratchpad"></param>
        /// <returns></returns>
        public static string GetStringForAttribute(EveAttribute attrib, CharacterScratchpad oldScratchpad, CharacterScratchpad newScratchpad)
        {
            int bonusDifference = newScratchpad[attrib].Base - oldScratchpad[attrib].Base;

            if (bonusDifference == 0)
            {
                return newScratchpad[attrib].ToString("%N (0) = %e = (%B + %r + %i)");
            }
            else if (bonusDifference > 0)
            {
                return newScratchpad[attrib].ToString(String.Format("%N (+{0}) = %e = (%B + %r + %i)", bonusDifference));
            }
            else
            {
                return newScratchpad[attrib].ToString(String.Format("%N ({0}) = %e = (%B + %r + %i)", bonusDifference));
            }
        }