Repository navigation
Expand file tree
/
Copy pathRecentCache.cs
More file actions
101 lines (91 loc) · 2.74 KB
/
Copy pathRecentCache.cs
File metadata and controls
101 lines (91 loc) · 2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using System.IO;
using System.Text.Json;
namespace ZeroWubiLens;
internal sealed class RecentEntry
{
public string Char { get; set; } = "";
public string FullCode { get; set; } = "";
public List<string> SimpleCodes { get; set; } = new();
public DateTime LastSeen { get; set; }
public int Count { get; set; }
}
/// <summary>
/// Lightweight LRU-ish cache of recently looked-up characters, persisted to
/// Cache/recent.json. Statistics are recorded silently (never prompts the user).
/// </summary>
internal sealed class RecentCache
{
private readonly int _max;
private readonly Dictionary<string, RecentEntry> _entries = new();
private readonly object _lock = new();
public RecentCache(int max)
{
_max = Math.Max(10, max);
Load();
}
public void Record(WubiLookupResult result)
{
lock (_lock)
{
if (!_entries.TryGetValue(result.Char, out var e))
{
e = new RecentEntry { Char = result.Char };
_entries[result.Char] = e;
}
e.FullCode = result.FullCode;
e.SimpleCodes = result.SimpleCodes.ToList();
e.LastSeen = DateTime.Now;
e.Count++;
Trim();
Save();
}
}
public RecentEntry? Get(string ch)
{
lock (_lock)
return _entries.TryGetValue(ch, out var e) ? e : null;
}
private void Trim()
{
if (_entries.Count <= _max) return;
var drop = _entries.Values
.OrderBy(e => e.LastSeen)
.Take(_entries.Count - _max)
.Select(e => e.Char)
.ToList();
foreach (var k in drop)
_entries.Remove(k);
}
private void Load()
{
try
{
if (!File.Exists(AppPaths.RecentCacheFile)) return;
var json = File.ReadAllText(AppPaths.RecentCacheFile);
var list = JsonSerializer.Deserialize<List<RecentEntry>>(json);
if (list is null) return;
foreach (var e in list)
if (!string.IsNullOrEmpty(e.Char))
_entries[e.Char] = e;
}
catch (Exception ex)
{
AppPaths.Log($"[RecentCache] load failed: {ex.Message}");
}
}
private void Save()
{
try
{
AppPaths.EnsureCache();
var list = _entries.Values.OrderByDescending(e => e.LastSeen).ToList();
var json = JsonSerializer.Serialize(list,
new JsonSerializerOptions { WriteIndented = false });
File.WriteAllText(AppPaths.RecentCacheFile, json);
}
catch (Exception ex)
{
AppPaths.Log($"[RecentCache] save failed: {ex.Message}");
}
}
}