Ejemplo n.º 1
0
 /// <summary>
 /// Background task work method.
 /// </summary>
 private void DoPrepareSvg(object sender, DoWorkEventArgs e)
 {
     // Lock to allow only one of these operations at a time.
     lock (_updateLock)
     {
         KanjiDao dao = new KanjiDao();
         // Get the kanji strokes.
         KanjiStrokes strokes = dao.GetKanjiStrokes(_kanjiEntity.DbKanji.ID);
         if (strokes != null && strokes.FramesSvg.Length > 0)
         {
             // If the strokes was successfuly retrieved, we have to read the compressed SVG contained inside.
             SharpVectors.Renderers.Wpf.WpfDrawingSettings settings = new SharpVectors.Renderers.Wpf.WpfDrawingSettings();
             using (FileSvgReader r = new FileSvgReader(settings))
             {
                 // Unzip the stream and remove instances of "px" that are problematic for SharpVectors.
                 string svgString = StringCompressionHelper.Unzip(strokes.FramesSvg);
                 svgString    = svgString.Replace("px", string.Empty);
                 StrokesCount = Regex.Matches(svgString, "<circle").Count;
                 using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(svgString)))
                 {
                     // Then read the stream to a DrawingGroup.
                     // We are forced to do this operation on the UI thread because DrawingGroups must
                     // be always manipulated by the same thread.
                     DispatcherHelper.Invoke(() =>
                     {
                         StrokesDrawingGroup = r.Read(stream);
                         SetCurrentStroke(1);
                     });
                 }
             }
         }
     }
 }
 /// <summary>
 /// Background task work method.
 /// </summary>
 private void DoPrepareSvg(object sender, DoWorkEventArgs e)
 {
     // Lock to allow only one of these operations at a time.
     lock (_updateLock)
     {
         KanjiDao dao = new KanjiDao();
         // Get the kanji strokes.
         KanjiStrokes strokes = dao.GetKanjiStrokes(_kanjiEntity.DbKanji.ID);
         if (strokes != null && strokes.FramesSvg.Length > 0)
         {
             // If the strokes was successfuly retrieved, we have to read the compressed SVG contained inside.
             string svgString = StringCompressionHelper.Unzip(strokes.FramesSvg);
             StrokesCount = Regex.Matches(svgString, "<circle").Count;
             DispatcherHelper.Invoke(() =>
             {
                 StrokesImage = new Avalonia.Svg.Skia.SvgImage
                 {
                     Source = new SvgSource {
                         Picture = new SKSvg().FromSvg(svgString)
                     }
                 };
                 SetCurrentStroke(1);
             });
         }
     }
 }
        /// <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;
            var vocabDao = new VocabDao();
            var kanjiDao = new KanjiDao();

            vocabDao.OpenMassTransaction();

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

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

            vocabDao.CloseMassTransaction();

            // 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);
        }
Ejemplo n.º 4
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);
        }
        /// <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);
        }
Ejemplo n.º 6
0
 public KanjiBusiness()
 {
     _kanjiDao = new KanjiDao();
 }
Ejemplo n.º 7
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);
                HashSet <char>  countedKanji = entries.Select(e => e.AssociatedKanji)
                                               .Where(k => !string.IsNullOrEmpty(k))
                                               .Select(k => k[0]).ToHashSet();
                HashSet <char>  kanjiAdded     = new HashSet <char>();
                HashSet <char>  kanjiJustAdded = new HashSet <char>();
                List <SrsEntry> kanjiToAdd     = new List <SrsEntry>();
                List <SrsEntry> vocabToAdd     = new List <SrsEntry>();
                List <SrsEntry> vocabNext      = new List <SrsEntry>();
                KanjiDao        kanjiDao       = new KanjiDao();
                while (pickList.Any() || kanjiToAdd.Any() || vocabToAdd.Any() || vocabNext.Any())
                {
                    SrsEntry next = null;
                    if (kanjiToAdd.Any())
                    {
                        next = kanjiToAdd[0];
                        kanjiToAdd.RemoveAt(0);
                    }
                    else if (vocabToAdd.Any())
                    {
                        next = vocabToAdd[0];
                        vocabToAdd.RemoveAt(0);
                    }
                    else if (pickList.Any())
                    {
                        // Pick an item and remove it.
                        int nextIndex = SpreadMode == ImportSpreadTimingMode.ListOrder ? 0 : _random.Next(pickList.Count);
                        next = pickList[nextIndex];
                        pickList.RemoveAt(nextIndex);
                        if (KanjiOrdered)
                        {
                            if (!string.IsNullOrEmpty(next.AssociatedVocab))
                            {
                                bool skip = false;
                                foreach (var kanji in next.AssociatedVocab.Where(c => c > '\u4e00' && c < '\u9fff' && !kanjiAdded.Contains(c)))
                                {
                                    if (!countedKanji.Contains(kanji))
                                    {
                                        kanjiAdded.Add(kanji);
                                    }
                                    else
                                    {
                                        if (kanjiToAdd.All(k => k.AssociatedKanji[0] != kanji))
                                        {
                                            int index = pickList.FindIndex(k => !string.IsNullOrEmpty(k.AssociatedKanji) && k.AssociatedKanji[0] == kanji);
                                            if (index >= 0)
                                            {
                                                kanjiToAdd.Add(pickList[index]);
                                                pickList.RemoveAt(index);
                                            }
                                        }
                                        skip = true;
                                    }
                                }
                                if (skip || next.AssociatedVocab.Any(c => c > '\u4e00' && c < '\u9fff' && kanjiJustAdded.Contains(c)))
                                {
                                    vocabNext.Add(next);
                                    continue;
                                }
                            }
                        }
                    }

                    if (next != null)
                    {
                        // add kanji to set
                        if (!string.IsNullOrEmpty(next.AssociatedKanji))
                        {
                            kanjiAdded.Add(next.AssociatedKanji[0]);
                            kanjiJustAdded.Add(next.AssociatedKanji[0]);
                        }

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

                    // Increment i and add a day to the delay if i reaches the spread value.
                    if (++i >= SpreadAmountPerInterval || next == null)
                    {
                        i      = 0;
                        delay += TimeSpan.FromDays(SpreadInterval);

                        if (KanjiOrdered)
                        {
                            kanjiJustAdded.Clear();
                            // add vocab to queue once all kanji have been added
                            vocabToAdd.AddRange(vocabNext.Where(v => !v.AssociatedVocab.Any(c => c > '\u4e00' && c < '\u9fff' && !kanjiAdded.Contains(c))));
                            vocabNext.RemoveAll(v => !v.AssociatedVocab.Any(c => c > '\u4e00' && c < '\u9fff' && !kanjiAdded.Contains(c)));
                        }
                    }
                }
            }
            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);
                }
            }
        }
Ejemplo n.º 8
0
 public FilteredKanjiIterator(KanjiFilter filter)
     : base(filter)
 {
     _kanjiDao = new KanjiDao();
 }