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); }
/// <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); } }
/// <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); }
/// <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; }
/// <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); }
/// <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; } }
/// <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(); } }
/// <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; } }
/// <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; }
/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); } } }
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; } }
public ExtendedSrsEntry(SrsEntry entry, bool forceLoad) { Reference = entry; if (!forceLoad) { SrsLevelStore.Instance.IssueWhenLoaded(OnSrsLevelsLoaded); } else { OnSrsLevelsLoaded(); } }
/// <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); }
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); }
/// <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; }
/// <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)); } } } }
/// <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) }); }
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."); } }
/// <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); }
/// <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); }
/// <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; } }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
public ExtendedSrsEntry(SrsEntry entry) : this(entry, false) { Reference = entry; SrsLevelStore.Instance.IssueWhenLoaded(OnSrsLevelsLoaded); }