using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Windows; namespace AxCopilot.Services; public static class QuoteService { private record FamousQuote(string Text, string Author); private record MovieQuote(string Text, string Movie, int Year, string? Character, long? Audience); private static readonly Lazy _motivational = new Lazy(LoadMotivational); private static readonly Lazy _famous = new Lazy(LoadFamous); private static readonly Lazy _displaySemi = new Lazy(() => LoadSimple("display_semiconductor.json")); private static readonly Lazy _itAi = new Lazy(() => LoadSimple("it_ai.json")); private static readonly Lazy _science = new Lazy(() => LoadSimple("science.json")); private static readonly Lazy _history = new Lazy(() => LoadSimple("history.json")); private static readonly Lazy _english = new Lazy(() => LoadSimple("english.json")); private static readonly Lazy _movies = new Lazy(LoadMovies); private static readonly Lazy> _todayEvents = new Lazy>(LoadTodayEvents); public static readonly (string Key, string Label, Func Count)[] Categories = new(string, string, Func)[9] { ("motivational", "격려 문구", () => _motivational.Value.Length), ("famous", "유명 명언", () => _famous.Value.Length), ("display_semiconductor", "디스플레이/반도체 상식", () => _displaySemi.Value.Length), ("it_ai", "IT, AI 기술", () => _itAi.Value.Length), ("science", "일반 과학", () => _science.Value.Length), ("history", "역사", () => _history.Value.Length), ("english", "생활영어", () => _english.Value.Length), ("movies", "드라마/영화 명대사", () => _movies.Value.Length), ("today_events", "오늘의 역사/기념일", () => GetTodayEventCount()) }; private static Dictionary? _greetingsCache; private static DateTime _greetingsCacheTime; public static int TotalCount => _motivational.Value.Length + _famous.Value.Length + _displaySemi.Value.Length + _itAi.Value.Length + _science.Value.Length + _history.Value.Length + _english.Value.Length + _movies.Value.Length; private static string[] LoadMotivational() { try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/motivational.json"); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream == null) { return Array.Empty(); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return JsonSerializer.Deserialize(streamReader.ReadToEnd()) ?? Array.Empty(); } catch (Exception ex) { LogService.Warn("격려 문구 로드 실패: " + ex.Message); return Array.Empty(); } } private static FamousQuote[] LoadFamous() { try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/famous.json"); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream == null) { return Array.Empty(); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return JsonSerializer.Deserialize(streamReader.ReadToEnd(), options) ?? Array.Empty(); } catch (Exception ex) { LogService.Warn("명언 로드 실패: " + ex.Message); return Array.Empty(); } } private static string[] LoadSimple(string fileName) { try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/" + fileName); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream == null) { return Array.Empty(); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return JsonSerializer.Deserialize(streamReader.ReadToEnd()) ?? Array.Empty(); } catch (Exception ex) { LogService.Warn(fileName + " 로드 실패: " + ex.Message); return Array.Empty(); } } private static MovieQuote[] LoadMovies() { try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/movies.json"); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream == null) { return Array.Empty(); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return JsonSerializer.Deserialize(streamReader.ReadToEnd(), options) ?? Array.Empty(); } catch { return Array.Empty(); } } private static Dictionary LoadTodayEvents() { try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/today_events.json"); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream == null) { return new Dictionary(); } using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return JsonSerializer.Deserialize>(streamReader.ReadToEnd()) ?? new Dictionary(); } catch { return new Dictionary(); } } public static (string Text, string? Author) GetRandom(IEnumerable? enabledCategories = null) { HashSet hashSet = enabledCategories?.ToHashSet(StringComparer.OrdinalIgnoreCase) ?? new HashSet { "motivational" }; string timeGreeting = GetTimeGreeting(); if (hashSet.Contains("today_events")) { string key = DateTime.Now.ToString("MM-dd"); if (_todayEvents.Value.TryGetValue(key, out string[] value) && value.Length != 0) { string text = value[Random.Shared.Next(value.Length)]; return (Text: timeGreeting + text, Author: "오늘의 역사"); } } List<(string, string)> list = new List<(string, string)>(); if (hashSet.Contains("motivational")) { string[] value2 = _motivational.Value; foreach (string item in value2) { list.Add((item, null)); } } if (hashSet.Contains("famous")) { FamousQuote[] value3 = _famous.Value; foreach (FamousQuote famousQuote in value3) { list.Add((famousQuote.Text, famousQuote.Author)); } } if (hashSet.Contains("display_semiconductor")) { string[] value4 = _displaySemi.Value; foreach (string item2 in value4) { list.Add((item2, "디스플레이/반도체")); } } if (hashSet.Contains("it_ai")) { string[] value5 = _itAi.Value; foreach (string item3 in value5) { list.Add((item3, "IT/AI")); } } if (hashSet.Contains("science")) { string[] value6 = _science.Value; foreach (string item4 in value6) { list.Add((item4, "과학")); } } if (hashSet.Contains("history")) { string[] value7 = _history.Value; foreach (string item5 in value7) { list.Add((item5, "역사")); } } if (hashSet.Contains("english")) { string[] value8 = _english.Value; foreach (string item6 in value8) { list.Add((item6, "생활영어")); } } if (hashSet.Contains("movies")) { MovieQuote[] value9 = _movies.Value; foreach (MovieQuote movieQuote in value9) { string value10 = ((movieQuote.Audience >= 10000000) ? " \ud83e\udd47" : ((movieQuote.Audience >= 7000000) ? " \ud83e\udd48" : ((movieQuote.Audience >= 5000000) ? " \ud83e\udd49" : ""))); string item7 = $"《{movieQuote.Movie}》({movieQuote.Year}){((movieQuote.Character != null) ? (" — " + movieQuote.Character) : "")}{value10}"; list.Add(("\"" + movieQuote.Text + "\"", item7)); } } if (list.Count == 0) { return (Text: timeGreeting + "오늘도 열심히 해주셔서 고맙습니다!", Author: null); } var (text2, item8) = list[Random.Shared.Next(list.Count)]; return (Text: timeGreeting + text2, Author: item8); } private static string GetTimeGreeting() { int hour = DateTime.Now.Hour; string key; if (hour < 9) { key = "morning"; } else if (hour >= 12 && hour < 15) { key = "lunch"; } else { if (hour < 18) { return ""; } key = "evening"; } Dictionary dictionary = LoadGreetings(); if (dictionary.TryGetValue(key, out var value) && value.Length != 0) { return value[Random.Shared.Next(value.Length)] + "\n\n"; } return ""; } private static Dictionary LoadGreetings() { if (_greetingsCache != null && (DateTime.Now - _greetingsCacheTime).TotalMinutes < 5.0) { return _greetingsCache; } JsonSerializerOptions options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; try { string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "Quotes", "greetings.json"); if (File.Exists(path)) { string json = File.ReadAllText(path, Encoding.UTF8); Dictionary dictionary = JsonSerializer.Deserialize>(json, options); if (dictionary != null) { _greetingsCache = dictionary; _greetingsCacheTime = DateTime.Now; return dictionary; } } } catch (Exception ex) { LogService.Warn("외부 인사문구 로드 실패: " + ex.Message); } try { Uri uriResource = new Uri("pack://application:,,,/Assets/Quotes/greetings.json"); Stream stream = Application.GetResourceStream(uriResource)?.Stream; if (stream != null) { using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); Dictionary dictionary2 = JsonSerializer.Deserialize>(streamReader.ReadToEnd(), options); if (dictionary2 != null) { _greetingsCache = dictionary2; _greetingsCacheTime = DateTime.Now; return dictionary2; } } } catch (Exception ex2) { LogService.Warn("내장 인사문구 로드 실패: " + ex2.Message); } return _greetingsCache = new Dictionary(); } private static int GetTodayEventCount() { return _todayEvents.Value.Values.Sum((string[] v) => v.Length); } public static int GetTodayMatchCount() { string key = DateTime.Now.ToString("MM-dd"); string[] value; return _todayEvents.Value.TryGetValue(key, out value) ? value.Length : 0; } }