コード例 #1
0
        public override bool OnNextStep()
        {
            List <SrsEntry> newEntries = new List <SrsEntry>();

            foreach (WkItem wkItem in Result.Items)
            {
                SrsEntry entry = new SrsEntry();
                if (wkItem.IsKanji)
                {
                    entry.AssociatedKanji = wkItem.KanjiReading;
                }
                else
                {
                    entry.AssociatedVocab = wkItem.KanjiReading;
                }

                entry.CurrentGrade   = wkItem.SrsLevel;
                entry.MeaningNote    = wkItem.MeaningNote;
                entry.Meanings       = wkItem.Meanings;
                entry.NextAnswerDate = wkItem.NextReviewDate;
                entry.ReadingNote    = wkItem.ReadingNote;
                entry.Readings       = wkItem.Readings;
                entry.SuspensionDate = _parent.IsStartEnabled ? (DateTime?)null : DateTime.Now;
                entry.Tags           = _parent.Tags.Replace(WkImportViewModel.LevelSpecialString, wkItem.WkLevel.ToString());
                newEntries.Add(entry);
            }

            _parent.NewEntries = newEntries;
            _parent.ApplyTiming();

            return(true);
        }
コード例 #2
0
        /// <summary>
        /// Command callback.
        /// Called to directly add the calling vocab to the SRS.
        /// </summary>
        /// <param name="vocab">Calling vocab.</param>
        private void OnQuickAddToSrs(ExtendedVocab vocab)
        {
            SrsEntry entry = new SrsEntry();

            entry.LoadFromVocab(vocab.DbVocab);
            entry.Tags = Kanji.Interface.Properties.Settings.Default.LastSrsTagsValue;

            SrsLevel startLevel = SrsLevelStore.Instance.GetLevelByValue(0);

            if (startLevel != null)
            {
                entry.NextAnswerDate = DateTime.Now + startLevel.Delay;
            }

            // Sets some properties
            entry.CreationDate = DateTime.UtcNow;

            try
            {
                // Add the entity to the database.
                new SrsEntryDao().Add(entry);
                vocab.SrsEntry = new ExtendedSrsEntry(entry);
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(
                    NavigationActor.Instance.ActiveWindow,
                    string.Format("An error occured: {0}", ex.Message),
                    "Quick add error",
                    System.Windows.MessageBoxButton.OK,
                    System.Windows.MessageBoxImage.Error);

                LogHelper.GetLogger("Quick add").Error("An error occured during quick add.", ex);
            }
        }
コード例 #3
0
        /// <summary>
        /// Builds a question group for the given SRS entry.
        /// </summary>
        /// <param name="reference">Target SRS entry.</param>
        public SrsQuestionGroup(SrsEntry reference)
        {
            Reference = reference;

            Questions = new List <SrsQuestion>();
            if (!string.IsNullOrWhiteSpace(reference.Meanings))
            {
                Questions.Add(new SrsQuestion()
                {
                    Question    = SrsQuestionEnum.Meaning,
                    ParentGroup = this
                });
            }

            if (!string.IsNullOrWhiteSpace(reference.Readings))
            {
                Questions.Add(new SrsQuestion()
                {
                    Question    = SrsQuestionEnum.Reading,
                    ParentGroup = this
                });
            }

            Audio = new VocabAudio(Reference);
        }
コード例 #4
0
        /// <summary>
        /// Loads properties from the given kanji entity.
        /// </summary>
        /// <param name="se">Target SRS entry.</param>
        /// <param name="k">Kanji to load.</param>
        public static void LoadFromKanji(this SrsEntry se, KanjiEntity k)
        {
            // Compute the meaning string.
            string meaningString = string.Empty;

            foreach (KanjiMeaning km in k.Meanings)
            {
                meaningString += MultiValueFieldHelper.ReplaceSeparator(km.Meaning) + MultiValueFieldHelper.ValueSeparator;
            }
            meaningString = meaningString.Trim(
                new char[] { MultiValueFieldHelper.ValueSeparator });
            meaningString = MultiValueFieldHelper.Expand(meaningString);

            // Compute the reading string.
            string readingString = (k.OnYomi
                                    + MultiValueFieldHelper.ValueSeparator)
                                   + k.KunYomi;

            readingString = MultiValueFieldHelper.Expand(readingString
                                                         .Trim(new char[] { MultiValueFieldHelper.ValueSeparator }));

            // Set values.
            se.Meanings        = meaningString;
            se.Readings        = readingString;
            se.AssociatedKanji = k.Character;
        }
コード例 #5
0
        /// <summary>
        /// Before going to the next step, read all items!
        /// </summary>
        public override bool OnNextStep()
        {
            // Initialize fields
            _parent.NewEntries = new List <SrsEntry>();
            StringBuilder log = new StringBuilder();

            log.AppendLine(string.Format("Starting import with {0} line(s).", _parent.CsvLines.Count));
            int i = 0;

            // Browse CSV lines!
            foreach (List <string> row in _parent.CsvLines)
            {
                log.AppendFormat("l{0}: ", ++i);
                // Attempt to read the entry.
                SrsEntry entry = ReadEntry(row, log);
                log.AppendLine();

                // Add the entry to the parent's list if not null.
                if (entry != null)
                {
                    _parent.NewEntries.Add(entry);
                }
            }

            // All items have been added.
            // Apply the timing preferences for items that do not have a review date.
            _parent.ApplyTiming();

            // Pray for the plural
            log.AppendLine(string.Format("Finished with {0} new entries.", _parent.NewEntries.Count));

            // Set the import log. We're good.
            _parent.ImportLog = log.ToString();
            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Loads properties from the given vocab entity.
        /// </summary>
        /// <param name="se">Target SRS entry.</param>
        /// <param name="v">Vocab to load.</param>
        public static void LoadFromVocab(this SrsEntry se, VocabEntity v)
        {
            // Compute the meaning string.
            string meaningString = string.Empty;

            foreach (VocabMeaning vm in v.Meanings)
            {
                meaningString += MultiValueFieldHelper.ReplaceSeparator(vm.Meaning)
                                 .Replace(" ;", MultiValueFieldHelper.ValueSeparator.ToString())
                                 + MultiValueFieldHelper.ValueSeparator;
            }
            meaningString = meaningString.Trim(
                new char[] { MultiValueFieldHelper.ValueSeparator });
            meaningString = MultiValueFieldHelper.Trim(meaningString);
            meaningString = MultiValueFieldHelper.Expand(meaningString);

            // Set values.
            se.Meanings        = meaningString;
            se.Readings        = v.KanaWriting;
            se.AssociatedVocab = v.KanjiWriting;

            if (string.IsNullOrEmpty(se.AssociatedVocab))
            {
                se.AssociatedVocab = v.KanaWriting;
            }
        }
コード例 #7
0
        /// <summary>
        /// Displays the SRS item edition window to allow the
        /// user to add a new kanji or vocab item to the SRS.
        /// </summary>
        /// <param name="isKanji">True to add a kanji item.
        /// False to add a vocab item.</param>
        private void AddSrsItem(bool isKanji)
        {
            // Prepare the new entry.
            SrsEntry entry = new SrsEntry();

            if (isKanji)
            {
                entry.AssociatedKanji = string.Empty;
            }
            else
            {
                entry.AssociatedVocab = string.Empty;
            }

            // Show the modal entry edition window.
            EditSrsEntryWindow wnd = new EditSrsEntryWindow(entry);

            wnd.ShowDialog(NavigationActor.Instance.MainWindow);

            // When it is closed, get the result.
            ExtendedSrsEntry result = wnd.Result;

            if (wnd.IsSaved && result != null)
            {
                // The new element was added.
                // Refresh the dashboard.
                SrsBusiness.Instance.UpdateReviewInfoAsync();
            }
        }
コード例 #8
0
        /// <summary>
        /// Command callback.
        /// Called to open the SRS item edition window to add the
        /// calling vocab to the SRS.
        /// </summary>
        /// <param name="vocab">Calling vocab.</param>
        private void OnAddToSrs(ExtendedVocab vocab)
        {
            // Prepare the new entry.
            SrsEntry entry = new SrsEntry();

            entry.LoadFromVocab(vocab.DbVocab);

            // Show the modal entry edition window.
            EditSrsEntryWindow wnd = new EditSrsEntryWindow(entry);

            wnd.ShowDialog();

            // When it is closed, get the result.
            ExtendedSrsEntry result = wnd.Result;

            if (wnd.IsSaved && result != null &&
                ((!string.IsNullOrEmpty(vocab.DbVocab.KanjiWriting) &&
                  result.AssociatedVocab == vocab.DbVocab.KanjiWriting) ||
                 (string.IsNullOrEmpty(vocab.DbVocab.KanjiWriting) &&
                  result.AssociatedVocab == vocab.DbVocab.KanaWriting)))
            {
                // The result exists and is still associated with this kanji.
                // We can use it in this ViewModel.
                vocab.SrsEntry = result;
            }
        }
コード例 #9
0
 /// <summary>
 /// Builds a new SRS entry editing window designed to add a new
 /// pre-created SRS entry, or to edit an existing SRS entry.
 /// </summary>
 /// <param name="entity">SRS entry to load in the window.</param>
 public EditSrsEntryWindow(SrsEntry entity)
 {
     InitializeComponent();
     InitializeViewModel(entity);
     NavigationActor.Instance.ActiveWindow = this;
     Owner = NavigationActor.Instance.MainWindow;
     WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
 }
コード例 #10
0
        /// <summary>
        /// Applies the given value to the given field of the given entries.
        /// </summary>
        /// <param name="entities">Entries to edit.</param>
        /// <param name="fieldName">Name of the field to set.</param>
        /// <param name="value">Value to set for all entities.</param>
        /// <returns>Number of entities edited.</returns>
        private long BulkEditStringField(IEnumerable <SrsEntry> entities,
                                         string fieldName, string value)
        {
            if (!entities.Any())
            {
                return(0);
            }

            DaoConnection connection = null;
            long          result     = -1;

            try
            {
                connection = DaoConnection.Open(DaoConnectionEnum.SrsDatabase);

                int i = 0;
                result = 0;
                while (i < entities.Count())
                {
                    List <DaoParameter> parameters = new List <DaoParameter>();
                    string inStatement             = string.Empty;
                    int    nMax = Math.Min(entities.Count(), i + BulkBatchCount);

                    for (int n = i; n < nMax; n++)
                    {
                        SrsEntry entry     = entities.ElementAt(n);
                        string   paramName = "@p" + entry.ID;
                        inStatement += paramName + ",";
                        parameters.Add(new DaoParameter(paramName, entry.ID));
                    }
                    inStatement = inStatement.TrimEnd(new char[] { ',' });

                    // Add the "value" parameter.
                    parameters.Add(new DaoParameter("@Value", value));

                    // Add the "LastUpdateDate" parameter.
                    parameters.Add(new DaoParameter("@LastUpdateDate", DateTime.UtcNow.Ticks));

                    // Execute the query.
                    result += connection.ExecuteNonQuery("UPDATE " + SqlHelper.Table_SrsEntry
                                                         + " SET " + fieldName + "=@Value, " + SqlHelper.Field_SrsEntry_LastUpdateDate
                                                         + "=@LastUpdateDate " + "WHERE " + SqlHelper.Field_SrsEntry_Id
                                                         + " IN (" + inStatement + ")",
                                                         parameters.ToArray());

                    i = nMax;
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(result);
        }
コード例 #11
0
        /// <summary>
        /// Updates the given entry.
        /// </summary>
        /// <param name="entry">Entry to update.</param>
        private void UpdateEntry(SrsEntry entry)
        {
            _currentTransactionCount++;
            BackgroundWorker worker = new BackgroundWorker();

            worker.DoWork             += DoUpdateEntry;
            worker.RunWorkerCompleted += DoneUpdateEntry;
            worker.RunWorkerAsync(entry);
        }
コード例 #12
0
        /// <summary>
        /// Reads an SRS item from a field row using the parameters of the view model.
        /// </summary>
        /// <param name="row">Row to read.</param>
        /// <param name="log">Log under the form of a stringbuilder to inform the user about how everything goes.</param>
        /// <returns>The SRS item read if successful. A null value otherwise.</returns>
        private SrsEntry ReadEntry(List <string> row, StringBuilder log)
        {
            try
            {
                SrsEntry entry        = new SrsEntry();
                string   kanjiReading = row[_kanjiReadingColumn];
                if (string.IsNullOrEmpty(kanjiReading))
                {
                    log.AppendFormat("Empty kanji reading. Skipping.");
                    return(null);
                }

                // Figure out item type.
                CsvItemType itemType = ReadItemType(row);
                if (itemType == CsvItemType.Kanji ||
                    (itemType == CsvItemType.Unspecified &&
                     (_noTypeBehavior == CsvImportNoTypeBehavior.AllKanji ||
                      (_noTypeBehavior == CsvImportNoTypeBehavior.Auto && kanjiReading.Length == 1))))
                {
                    // Three solutions to set as kanji:
                    // 1. Item is manually specified as kanji in source data.
                    // 2. Item is not specified and no type behavior is set to AllKanji.
                    // 3. Item is not specified and no type behavior is set to Auto and the length of kanjiReading is exactly 1.
                    entry.AssociatedKanji = kanjiReading;
                    log.AppendFormat("Kanji: \"{0}\". ", kanjiReading);
                }
                else
                {
                    // All other cases will lead to vocab.
                    entry.AssociatedVocab = kanjiReading;
                    log.AppendFormat("Vocab: \"{0}\". ", kanjiReading);
                }

                // Find readings.
                entry.Readings = ReadAcceptedReadings(row);

                // Find meanings.
                entry.Meanings = ReadAcceptedMeanings(row);

                // Find all optional info.
                entry.MeaningNote    = ReadMeaningNotes(row);
                entry.ReadingNote    = ReadReadingNotes(row);
                entry.Tags           = ReadTags(row);
                entry.CurrentGrade   = ReadStartLevel(row);
                entry.NextAnswerDate = ReadNextReviewDate(row);

                log.Append("OK.");
                return(entry);
            }
            catch (Exception ex)
            {
                log.AppendFormat("Unknown error: \"{0}\". Skipping.", ex.Message);
            }

            return(null);
        }
コード例 #13
0
        /// <summary>
        /// Background task work method.
        /// Updates the given SRS item.
        /// </summary>
        private void DoUpdateEntry(object sender, DoWorkEventArgs e)
        {
            SrsEntry entry = (SrsEntry)e.Argument;

            if (!_srsEntryDao.Update(entry))
            {
                LogHelper.GetLogger(this.GetType().Name).WarnFormat(
                    "The review update for the SRS entry \"{0}\" ({1}) failed.",
                    entry.AssociatedKanji ?? entry.AssociatedVocab, entry.ID);
            }
        }
コード例 #14
0
        /// <summary>
        /// Applies the timing to the given entries.
        /// </summary>
        /// <param name="entries">Entries to reschedule.</param>
        public void ApplyTiming(List <SrsEntry> entries)
        {
            if (TimingMode == ImportTimingMode.Spread)
            {
                int             i        = 0;
                TimeSpan        delay    = TimeSpan.Zero;
                List <SrsEntry> pickList = new List <SrsEntry>(entries);
                while (pickList.Any())
                {
                    // Pick an item and remove it.
                    int      nextIndex = SpreadMode == ImportSpreadTimingMode.ListOrder ? 0 : _random.Next(pickList.Count);
                    SrsEntry next      = pickList[nextIndex];
                    pickList.RemoveAt(nextIndex);

                    // Apply spread
                    next.NextAnswerDate = DateTime.Now + delay;

                    // Increment i and add a day to the delay if i reaches the spread value.
                    if (++i >= SpreadAmountPerDay)
                    {
                        i      = 0;
                        delay += TimeSpan.FromHours(24);
                    }
                }
            }
            else if (TimingMode == ImportTimingMode.Immediate)
            {
                foreach (SrsEntry entry in entries)
                {
                    entry.NextAnswerDate = DateTime.Now;
                }
            }
            else if (TimingMode == ImportTimingMode.Never)
            {
                foreach (SrsEntry entry in entries)
                {
                    entry.NextAnswerDate = null;
                }
            }
            else if (TimingMode == ImportTimingMode.Fixed)
            {
                foreach (SrsEntry entry in entries)
                {
                    entry.NextAnswerDate = FixedDate;
                }
            }
            else if (TimingMode == ImportTimingMode.UseSrsLevel)
            {
                foreach (SrsEntry entry in entries)
                {
                    entry.NextAnswerDate = SrsLevelStore.Instance.GetNextReviewDate(entry.CurrentGrade);
                }
            }
        }
コード例 #15
0
        public VocabAudio(SrsEntry entry)
        {
            KanjiReading = entry.AssociatedVocab;
            KanaReading  = MultiValueFieldHelper.Trim(entry.Readings)
                           .Split(MultiValueFieldHelper.ValueSeparator)
                           .FirstOrDefault();

            if (string.IsNullOrWhiteSpace(KanaReading) || string.IsNullOrWhiteSpace(KanjiReading))
            {
                State = VocabAudioState.Unavailable;
            }
        }
コード例 #16
0
        public ExtendedSrsEntry(SrsEntry entry, bool forceLoad)
        {
            Reference = entry;

            if (!forceLoad)
            {
                SrsLevelStore.Instance.IssueWhenLoaded(OnSrsLevelsLoaded);
            }
            else
            {
                OnSrsLevelsLoaded();
            }
        }
コード例 #17
0
        /// <summary>
        /// Removes all the given entities from the database.
        /// </summary>
        /// <param name="entities">Entities to delete.</param>
        /// <returns>Number of items successfuly deleted.</returns>
        public long BulkDelete(IEnumerable <SrsEntry> entities)
        {
            if (!entities.Any())
            {
                return(0);
            }

            DaoConnection connection = null;
            long          result     = -1;

            try
            {
                connection = DaoConnection.Open(DaoConnectionEnum.SrsDatabase);

                int i = 0;
                result = 0;
                while (i < entities.Count())
                {
                    List <DaoParameter> parameters = new List <DaoParameter>();
                    string inStatement             = string.Empty;

                    int nMax = Math.Min(entities.Count(), i + BulkBatchCount);

                    for (int n = i; n < nMax; n++)
                    {
                        SrsEntry entry     = entities.ElementAt(n);
                        string   paramName = "@p" + entry.ID;
                        inStatement += paramName + ",";
                        parameters.Add(new DaoParameter(paramName, entry.ID));
                    }
                    inStatement = inStatement.TrimEnd(new char[] { ',' });

                    // Execute the query.
                    result += connection.ExecuteNonQuery("DELETE FROM " + SqlHelper.Table_SrsEntry
                                                         + " WHERE " + SqlHelper.Field_SrsEntry_Id + " IN (" + inStatement + ")",
                                                         parameters.ToArray());
                    i = nMax;
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(result);
        }
コード例 #18
0
        private ImportResult DoConvert(SrsEntry e)
        {
            ImportResult r = new ImportResult();

            r.Type         = string.IsNullOrEmpty(e.AssociatedKanji) ? "V" : "K";
            r.Item         = string.IsNullOrEmpty(e.AssociatedKanji) ? e.AssociatedVocab : e.AssociatedKanji;
            r.Level        = e.CurrentGrade.ToString();
            r.MeaningNotes = e.MeaningNote;
            r.Meanings     = e.Meanings;
            r.ReadingNotes = e.ReadingNote;
            r.Readings     = e.Readings;
            r.Tags         = e.Tags;
            r.Date         = e.NextAnswerDate.HasValue ? e.NextAnswerDate.ToString() : string.Empty;
            return(r);
        }
コード例 #19
0
        /// <summary>
        /// Initializes the ViewModel.
        /// </summary>
        private void InitializeViewModel(SrsEntry entity)
        {
            SrsEntryViewModel vm;

            if (entity == null)
            {
                vm = new SrsEntryViewModel();
            }
            else
            {
                vm = new SrsEntryViewModel(entity);
            }

            vm.FinishedEditing += OnFinishedEditing;
            DataContext         = vm;
        }
コード例 #20
0
 /// <summary>
 /// Attempts to fill the batch to its maximal capacity.
 /// </summary>
 private void FillCurrentBatch()
 {
     lock (_batchLock)
     {
         int remaining = BatchMaxSize - _currentBatch.Count;
         while (remaining-- > 0 && _isEntryAvailable)
         {
             SrsEntry next = _iterator.GetNext(1).FirstOrDefault();
             if (next == null)
             {
                 _isEntryAvailable = false;
             }
             else
             {
                 _currentBatch.Add(ProcessEntry(next));
             }
         }
     }
 }
コード例 #21
0
 /// <summary>
 /// Builds and returns a clone of this instance.
 /// </summary>
 /// <returns>Clone of this instance.</returns>
 public static SrsEntry Clone(this SrsEntry se)
 {
     return(new SrsEntry()
     {
         AssociatedKanji = se.AssociatedKanji,
         AssociatedVocab = se.AssociatedVocab,
         CreationDate = se.CreationDate,
         CurrentGrade = se.CurrentGrade,
         FailureCount = se.FailureCount,
         ID = se.ID,
         SuspensionDate = se.SuspensionDate,
         MeaningNote = se.MeaningNote,
         Meanings = MultiValueFieldHelper.Expand(se.Meanings),
         NextAnswerDate = se.NextAnswerDate,
         ReadingNote = se.ReadingNote,
         Readings = MultiValueFieldHelper.Expand(se.Readings),
         SuccessCount = se.SuccessCount,
         Tags = MultiValueFieldHelper.Expand(se.Tags)
     });
 }
コード例 #22
0
 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 {
     if (value is SrsEntry)
     {
         SrsEntry e = (SrsEntry)value;
         return(DoConvert(e));
     }
     else if (value is IEnumerable <SrsEntry> )
     {
         List <ImportResult> r = new List <ImportResult>();
         foreach (SrsEntry e in (IEnumerable <SrsEntry>)value)
         {
             r.Add(DoConvert(e));
         }
         return(r);
     }
     else
     {
         throw new ArgumentException("Value must be an SrsEntry.");
     }
 }
コード例 #23
0
        /// <summary>
        /// Gets a similar item (same kanji reading and type) if found.
        /// </summary>
        /// <param name="entry">Reference entry.</param>
        /// <returns>The first matching item if found. Null otherwise.</returns>
        public SrsEntry GetSimilarItem(SrsEntry entry)
        {
            SrsEntry      r          = null;
            DaoConnection connection = null;

            try
            {
                connection = DaoConnection.Open(DaoConnectionEnum.SrsDatabase);

                List <DaoParameter> parameters = new List <DaoParameter>();
                string request = "SELECT * FROM " + SqlHelper.Table_SrsEntry + " se WHERE se.";
                if (!string.IsNullOrEmpty(entry.AssociatedKanji))
                {
                    request += SqlHelper.Field_SrsEntry_AssociatedKanji;
                    parameters.Add(new DaoParameter("@kr", entry.AssociatedKanji));
                }
                else
                {
                    request += SqlHelper.Field_SrsEntry_AssociatedVocab;
                    parameters.Add(new DaoParameter("@kr", entry.AssociatedVocab));
                }
                request += "=@kr";

                NameValueCollection result = connection.Query(request, parameters.ToArray()).FirstOrDefault();
                if (result != null)
                {
                    SrsEntryBuilder builder = new SrsEntryBuilder();
                    r = builder.BuildEntity(result, null);
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(r);
        }
コード例 #24
0
        /// <summary>
        /// Builds a ViewModel aimed at editing an existing SrsEntry,
        /// or adding a pre-composed SrsEntry.
        /// </summary>
        /// <param name="entity">Entity to edit.</param>
        public SrsEntryViewModel(SrsEntry entity)
        {
            // Initialize fields.
            _entry = new ExtendedSrsEntry(entity);
            _originalNextReviewDate = entity.NextAnswerDate;
            _originalLevelValue     = entity.CurrentGrade;
            _associatedKanjiString  = Entry.AssociatedKanji;
            _associatedVocabString  = Entry.AssociatedVocab;
            _srsEntryDao            = new SrsEntryDao();
            _kanjiDao = new KanjiDao();
            _vocabDao = new VocabDao();
            if (IsNew)
            {
                Entry.Tags = Properties.Settings.Default.LastSrsTagsValue;
            }

            // Create the relay commands.
            SubmitCommand               = new RelayCommand(OnSubmit);
            CancelCommand               = new RelayCommand(OnCancel);
            SrsProgressResetCommand     = new RelayCommand(OnSrsProgressReset);
            ApplyAssociatedKanjiCommand = new RelayCommand(OnApplyAssociatedKanji);
            ApplyAssociatedVocabCommand = new RelayCommand(OnApplyAssociatedVocab);
            ToggleSuspendCommand        = new RelayCommand(OnToggleSuspend);
            DeleteCommand               = new RelayCommand(OnDelete);
            ToggleDateEditCommand       = new RelayCommand(OnToggleDateEdit);
            DateToNowCommand            = new RelayCommand(OnDateToNow);
            DateToNeverCommand          = new RelayCommand(OnDateToNever);

            // Get the associated kanji or vocab.
            GetAssociatedKanji();
            GetAssociatedVocab();

            // Initialize the VM.
            _isFirstSrsLevelSelect             = true;
            SrsLevelPickerVm                   = new SrsLevelPickerViewModel();
            SrsLevelPickerVm.SrsLevelSelected += OnSrsLevelSelected;
            SrsLevelPickerVm.Initialize(_entry.CurrentGrade);
        }
コード例 #25
0
        /// <summary>
        /// Called when the AddToSrsCommand is fired.
        /// Opens the SRS entry window.
        /// </summary>
        private void OnAddToSrs()
        {
            // Prepare the new entry.
            SrsEntry entry = new SrsEntry();

            entry.LoadFromKanji(_kanjiEntity.DbKanji);

            // Show the modal entry edition window.
            EditSrsEntryWindow wnd = new EditSrsEntryWindow(entry);

            wnd.ShowDialog();

            // When it is closed, get the result.
            ExtendedSrsEntry result = wnd.Result;

            if (wnd.IsSaved && result != null &&
                result.AssociatedKanji == _kanjiEntity.DbKanji.Character)
            {
                // The result exists and is still associated with this kanji.
                // We can use it in this ViewModel.
                SrsEntry = result;
            }
        }
コード例 #26
0
        /// <summary>
        /// Command callback.
        /// Called to directly add the calling vocab to the SRS.
        /// </summary>
        /// <param name="vocab">Calling vocab.</param>
        private async void OnQuickAddToSrs(ExtendedVocab vocab)
        {
            SrsEntry entry = new SrsEntry();

            entry.LoadFromVocab(vocab.DbVocab);
            entry.Tags = Kanji.Interface.Properties.Settings.Default.LastSrsTagsValue;

            SrsLevel startLevel = SrsLevelStore.Instance.GetLevelByValue(0);

            if (startLevel != null)
            {
                entry.NextAnswerDate = DateTime.Now + startLevel.Delay;
            }

            // Sets some properties
            entry.CreationDate = DateTime.UtcNow;

            try
            {
                // Add the entity to the database.
                new SrsEntryDao().Add(entry);
                vocab.SrsEntry = new ExtendedSrsEntry(entry);
            }
            catch (Exception ex)
            {
                await MessageBoxManager.GetMessageBoxStandardWindow(new MessageBoxStandardParams
                {
                    ContentTitle      = "Quick add error",
                    ContentMessage    = $"An error occurred: {ex.Message}",
                    Icon              = Icon.Error,
                    ButtonDefinitions = ButtonEnum.Ok,
                }).ShowDialog(NavigationActor.Instance.MainWindow);

                LogHelper.GetLogger("Quick add").Error("An error occured during quick add.", ex);
            }
        }
コード例 #27
0
        /// <summary>
        /// Removes the entity from the database.
        /// </summary>
        /// <param name="entity">Entity to delete.</param>
        /// <returns>True if the operation was successful. False otherwise.</returns>
        public bool Delete(SrsEntry entity)
        {
            DaoConnection connection = null;
            bool          result     = false;

            try
            {
                connection = DaoConnection.Open(DaoConnectionEnum.SrsDatabase);

                // Execute the query.
                result = connection.ExecuteNonQuery("DELETE FROM " + SqlHelper.Table_SrsEntry
                                                    + " WHERE " + SqlHelper.Field_SrsEntry_Id + "=@Id",
                                                    new DaoParameter("@Id", entity.ID)) == 1;
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(result);
        }
コード例 #28
0
        /// <summary>
        /// Updates the given SRS entry.
        /// </summary>
        /// <param name="entity">Entity to update.</param>
        /// <returns>True if the operation was sucessful. False otherwise.</returns>
        public bool Update(SrsEntry entity)
        {
            DaoConnection connection = null;
            bool          result     = false;

            try
            {
                connection = DaoConnection.Open(DaoConnectionEnum.SrsDatabase);

                // Create a parameter list and two string builders that will
                // be used to put the SQL request together.
                List <DaoParameter> parameters      = new List <DaoParameter>();
                StringBuilder       sqlQueryBuilder = new StringBuilder(
                    "UPDATE " + SqlHelper.Table_SrsEntry + " SET ");

                // NextAnswerDate
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_NextAnswerDate + "=");
                if (entity.NextAnswerDate == null)
                {
                    sqlQueryBuilder.Append("null");
                }
                else
                {
                    sqlQueryBuilder.Append("@NextAnswerDate");
                    parameters.Add(new DaoParameter(
                                       "@NextAnswerDate", entity.NextAnswerDate.Value.ToUniversalTime().Ticks));
                }
                sqlQueryBuilder.Append(",");

                // Meanings
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_Meanings + "=@Meanings,");
                parameters.Add(new DaoParameter("@Meanings",
                                                MultiValueFieldHelper.Trim(entity.Meanings ?? string.Empty)));

                // Readings
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_Readings + "=@Readings,");
                parameters.Add(new DaoParameter("@Readings",
                                                MultiValueFieldHelper.Trim(entity.Readings ?? string.Empty)));

                // CurrentGrade
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_CurrentGrade + "=@CurrentGrade,");
                parameters.Add(new DaoParameter("@CurrentGrade", entity.CurrentGrade));

                // FailureCount
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_FailureCount + "=@FailureCount,");
                parameters.Add(new DaoParameter("@FailureCount", entity.FailureCount));

                // SuccessCount
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_SuccessCount + "=@SuccessCount,");
                parameters.Add(new DaoParameter("@SuccessCount", entity.SuccessCount));

                // SuspensionDate
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_SuspensionDate + "=");
                if (entity.SuspensionDate == null)
                {
                    sqlQueryBuilder.Append("null");
                }
                else
                {
                    sqlQueryBuilder.Append("@SuspensionDate");
                    parameters.Add(new DaoParameter(
                                       "@SuspensionDate", entity.SuspensionDate.Value.ToUniversalTime().Ticks));
                }
                sqlQueryBuilder.Append(",");

                // AssociatedVocab
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_AssociatedVocab
                                       + "=@AssociatedVocab,");
                parameters.Add(new DaoParameter(
                                   "@AssociatedVocab", entity.AssociatedVocab));

                // AssociatedKanji
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_AssociatedKanji
                                       + "=@AssociatedKanji,");
                parameters.Add(new DaoParameter(
                                   "@AssociatedKanji", entity.AssociatedKanji));

                // MeaningNote
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_MeaningNote
                                       + "=@MeaningNote,");
                parameters.Add(new DaoParameter(
                                   "@MeaningNote", entity.MeaningNote));

                // ReadingNote
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_ReadingNote
                                       + "=@ReadingNote,");
                parameters.Add(new DaoParameter(
                                   "@ReadingNote", entity.ReadingNote));

                // ServerId
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_ServerId
                                       + "=@ServerId,");
                parameters.Add(new DaoParameter(
                                   "@ServerId", entity.ServerId));

                // IsDeleted
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_IsDeleted
                                       + "=@IsDeleted,");
                parameters.Add(new DaoParameter(
                                   "@IsDeleted", entity.IsDeleted));

                // LastUpdateDate
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_LastUpdateDate
                                       + "=@LastUpdateDate,");
                parameters.Add(new DaoParameter(
                                   "@LastUpdateDate", DateTime.UtcNow.Ticks));

                // Tags
                sqlQueryBuilder.Append(SqlHelper.Field_SrsEntry_Tags + "=@Tags");
                parameters.Add(new DaoParameter(
                                   "@Tags", MultiValueFieldHelper.Trim(entity.Tags)));

                // We are done with the string builders.

                // Bring the query pieces together.
                string finalQuery =
                    sqlQueryBuilder.ToString() + " WHERE "
                    + SqlHelper.Field_SrsEntry_Id + "=@Id";
                parameters.Add(new DaoParameter("@Id", entity.ID));

                // Execute the query.
                result = connection.ExecuteNonQuery(finalQuery, parameters.ToArray()) == 1;
            }
            catch (Exception ex)
            {
                LogHelper.GetLogger(this.GetType().Name).Error(
                    "An error occured during SRS item update.", ex);
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(result);
        }
コード例 #29
0
        /// <summary>
        /// Reads an SRS item from a field row using the parameters of the view model.
        /// </summary>
        /// <param name="row">Row to read.</param>
        /// <param name="log">Log under the form of a stringbuilder to inform the user about how everything goes.</param>
        /// <returns>The SRS item read if successful. A null value otherwise.</returns>
        private SrsEntry ReadEntry(List <string> row, VocabDao vocabDao, KanjiDao kanjiDao, StringBuilder log)
        {
            try
            {
                SrsEntry entry        = new SrsEntry();
                string   kanjiReading = row[_kanjiReadingColumn];
                if (string.IsNullOrEmpty(kanjiReading))
                {
                    log.AppendFormat("Empty kanji reading. Skipping.");
                    return(null);
                }

                // Figure out item type.
                CsvItemType itemType = ReadItemType(row);
                if (itemType == CsvItemType.Kanji ||
                    (itemType == CsvItemType.Unspecified &&
                     (_noTypeBehavior == CsvImportNoTypeBehavior.AllKanji ||
                      (_noTypeBehavior == CsvImportNoTypeBehavior.Auto && kanjiReading.Length == 1))))
                {
                    // Three solutions to set as kanji:
                    // 1. Item is manually specified as kanji in source data.
                    // 2. Item is not specified and no type behavior is set to AllKanji.
                    // 3. Item is not specified and no type behavior is set to Auto and the length of kanjiReading is exactly 1.
                    entry.AssociatedKanji = kanjiReading;
                    log.AppendFormat("Kanji: \"{0}\". ", kanjiReading);
                    itemType = CsvItemType.Kanji;
                }
                else
                {
                    // All other cases will lead to vocab.
                    entry.AssociatedVocab = kanjiReading;
                    log.AppendFormat("Vocab: \"{0}\". ", kanjiReading);
                    itemType = CsvItemType.Vocab;
                }

                string readings = ReadAcceptedReadings(row);

                long?sequenceNumber = ReadSequenceNumber(row);

                if (ReadingAutofill || MeaningAutofill)
                {
                    switch (itemType)
                    {
                    case CsvItemType.Kanji:
                        var kanji = kanjiDao.GetFirstMatchingKanji(kanjiReading);
                        if (kanji == null)
                        {
                            log.Append("Can't find kanji in database. Skipping.");
                            return(null);
                        }
                        entry.LoadFromKanji(kanji);
                        break;

                    case CsvItemType.Vocab:
                        var vocabs = string.IsNullOrEmpty(readings) ? vocabDao.GetMatchingVocab(kanjiReading)
                                        : vocabDao.GetVocabByReadings(kanjiReading, readings);
                        if (sequenceNumber.HasValue)
                        {
                            vocabs = vocabs.Where(v => v.Seq == sequenceNumber);
                        }
                        var vocab = vocabs.FirstOrDefault();
                        if (vocab == null)
                        {
                            log.Append("Can't find vocab in database. Skipping.");
                            return(null);
                        }
                        entry.LoadFromVocab(vocab);
                        entry.AssociatedVocab = kanjiReading;
                        entry.Readings        = default(string);
                        break;
                    }
                }

                // Find readings.
                if (!ReadingAutofill || !string.IsNullOrEmpty(readings))
                {
                    entry.Readings = readings;
                }
                if (itemType == CsvItemType.Kanji && string.IsNullOrEmpty(entry.Readings))
                {
                    log.Append("Empty readings. Skipping.");
                    return(null);
                }

                // Find meanings.
                string meanings = ReadAcceptedMeanings(row);
                if (!MeaningAutofill || !string.IsNullOrEmpty(meanings))
                {
                    entry.Meanings = meanings;
                }
                if (string.IsNullOrEmpty(entry.Meanings))
                {
                    log.Append("Empty meanings. Skipping.");
                    return(null);
                }

                // Find all optional info.
                entry.MeaningNote    = ReadMeaningNotes(row);
                entry.ReadingNote    = ReadReadingNotes(row);
                entry.Tags           = ReadTags(row);
                entry.CurrentGrade   = ReadStartLevel(row);
                entry.NextAnswerDate = ReadNextReviewDate(row);

                log.Append("OK.");
                return(entry);
            }
            catch (Exception ex)
            {
                log.AppendFormat("Unknown error: \"{0}\". Skipping.", ex.Message);
            }

            return(null);
        }
コード例 #30
0
 public ExtendedSrsEntry(SrsEntry entry)
     : this(entry, false)
 {
     Reference = entry;
     SrsLevelStore.Instance.IssueWhenLoaded(OnSrsLevelsLoaded);
 }