<commit_before>﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;

namespace MangaReader
{
    class History
    {
        /// <summary>
        /// Указатель блокировки истории.
        /// </summary>
        private static readonly object HistoryLock = new object();

        /// <summary>
        /// Ссылка на файл лога.
        /// </summary>
        private static readonly string HistoryPath = Settings.WorkFolder + @".\history";

        /// <summary>
        /// История.
        /// </summary>
        private static List<MangaHistory> Historis = Serializer<List<MangaHistory>>.Load(HistoryPath);

        /// <summary>
        /// Добавление записи в историю.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        public static void Add(string message)
        {
            if (Historis.Any(l => l.Url == message))
                return;

            lock (HistoryLock)
                Historis.Add(new MangaHistory(message));
        }

        /// <summary>
        /// Сохранить историю локально.
        /// </summary>
        public static void Save()
        {
            Serializer<List<MangaHistory>>.Save(HistoryPath, Historis);
        }

        /// <summary>
        /// Сконвертировать в новый формат.
        /// </summary>
        public static void Convert()
        {
            if (Historis != null)
                return;

            var serializedStrings = Serializer<List<string>>.Load(HistoryPath);
            var isStringList = serializedStrings != null;

            var serializedMangaHistoris = Serializer<List<MangaHistory>>.Load(HistoryPath);
            var isMangaHistory = serializedMangaHistoris != null;


            var strings = File.Exists(HistoryPath) ? new List<string>(File.ReadAllLines(HistoryPath)) : new List<string>();

            if (!isMangaHistory && !isStringList)
                Historis = MangaHistory.CreateHistories(strings);
            if (!isMangaHistory && isStringList)
                Historis = MangaHistory.CreateHistories(serializedStrings);
            if (isMangaHistory && !isStringList)
                Historis = serializedMangaHistoris;

            Save();
        }

        /// <summary>
        /// Получить историю.
        /// </summary>
        /// <param name="subString">Подстрока, по которой будет получена история. Например, название манги.</param>
        /// <returns>Перечисление сообщений из истории.</returns>
        public static IEnumerable<MangaHistory> Get(string subString = "")
        {
            return string.IsNullOrWhiteSpace(subString) ? Historis : Historis.Where(l => l.MangaUrl.Contains(subString));
        }

        public History()
        {
            throw new Exception("U shell not pass.");
        }
    }
}<commit_msg>Потоконезависимость истории. Покрыла все обнаруженные исключения.<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace MangaReader
{
    class History
    {
        /// <summary>
        /// Указатель блокировки истории.
        /// </summary>
        private static readonly object HistoryLock = new object();

        /// <summary>
        /// Ссылка на файл лога.
        /// </summary>
        private static readonly string HistoryPath = Settings.WorkFolder + @".\history";

        /// <summary>
        /// История.
        /// </summary>
        private static List<MangaHistory> Historis = Serializer<List<MangaHistory>>.Load(HistoryPath);

        /// <summary>
        /// Добавление записи в историю.
        /// </summary>
        /// <param name="message">Сообщение.</param>
        public static void Add(string message)
        {
            lock (HistoryLock)
            {
                if (Historis.Any(l => l.Url == message))
                    return;

                Historis.Add(new MangaHistory(message));
            }
        }

        /// <summary>
        /// Сохранить историю локально.
        /// </summary>
        public static void Save()
        {
            lock (HistoryLock)
                Serializer<List<MangaHistory>>.Save(HistoryPath, Historis);
        }

        /// <summary>
        /// Сконвертировать в новый формат.
        /// </summary>
        public static void Convert()
        {
            if (Historis != null)
                return;

            var serializedStrings = Serializer<List<string>>.Load(HistoryPath);
            var isStringList = serializedStrings != null;

            var serializedMangaHistoris = Serializer<List<MangaHistory>>.Load(HistoryPath);
            var isMangaHistory = serializedMangaHistoris != null;


            var strings = File.Exists(HistoryPath) ? new List<string>(File.ReadAllLines(HistoryPath)) : new List<string>();

            if (!isMangaHistory && !isStringList)
                Historis = MangaHistory.CreateHistories(strings);
            if (!isMangaHistory && isStringList)
                Historis = MangaHistory.CreateHistories(serializedStrings);
            if (isMangaHistory && !isStringList)
                Historis = serializedMangaHistoris;

            Save();
        }

        /// <summary>
        /// Получить историю.
        /// </summary>
        /// <param name="subString">Подстрока, по которой будет получена история. Например, название манги.</param>
        /// <returns>Перечисление сообщений из истории.</returns>
        public static IEnumerable<MangaHistory> Get(string subString = "")
        {
            lock (HistoryLock)
                return string.IsNullOrWhiteSpace(subString) ?
                    Historis : 
                    Historis.Where(l => l.MangaUrl.Contains(subString)).ToList();
        }

        public History()
        {
            throw new Exception("U shell not pass.");
        }
    }
}
{'fraction_non_alphanumeric': 0.11651313544865234, 'fraction_numerical': 0.0, 'mean_word_length': 1.803921568627451, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5425770', 'n_tokens_mistral': 1609, 'n_tokens_neox': 1636, 'n_words': 341}