wangzhibo
2026-05-09 53418655c061ac26f66058253f39200aced1ab1d
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using BoardApp.Config;
 
namespace BoardApp.Services;
 
public sealed class ScenarioService
{
    private readonly BoardConfigLoader _cfg;
 
    public ScenarioService(BoardConfigLoader cfg)
    {
        _cfg = cfg;
    }
 
    public sealed record HomeScenario(string Id, string Name, string Image);
    public sealed record HomeCategory(string Id, string Name, List<HomeScenario> Scenarios);
 
    public enum ScenarioSource
    {
        System,
        User
    }
 
    public static string ToScenarioKey(ScenarioSource source, string scenarioId)
        => (source == ScenarioSource.System ? "s:" : "u:") + scenarioId;
 
    public sealed record ScenarioKeyParts(ScenarioSource Source, string ScenarioId);
 
    public static ScenarioKeyParts ParseScenarioKey(string input)
    {
        var raw = (input ?? "").Trim();
        if (raw.StartsWith("s:")) return new ScenarioKeyParts(ScenarioSource.System, raw[2..]);
        if (raw.StartsWith("u:")) return new ScenarioKeyParts(ScenarioSource.User, raw[2..]);
        return new ScenarioKeyParts(ScenarioSource.System, raw);
    }
 
    private Dictionary<string, PageDef> PageMap()
    {
        var cfg = _cfg.LoadPagesConfig();
        var map = new Dictionary<string, PageDef>(StringComparer.Ordinal);
        foreach (var p in cfg.Pages)
        {
            map[p.Id] = p;
        }
        return map;
    }
 
    public List<HomeCategory> LoadHomeCatalogForUser(string username)
    {
        var pagesById = PageMap();
        var sys = _cfg.LoadSystemScenariosConfig();
        var users = _cfg.LoadUserScenariosConfig();
        users.Users.TryGetValue(username, out var u);
        var userScenarios = u?.Scenarios ?? new List<UserScenario>();
 
        var sysCats = sys.Categories.Select(c => new HomeCategory(
            c.Id,
            c.Name,
            (c.Scenarios ?? new List<SystemScenario>())
                .Select(s => new HomeScenario(ToScenarioKey(ScenarioSource.System, s.Id), s.Name, s.Image))
                .ToList()
        )).ToList();
 
        var my = new HomeCategory(
            "my",
            "我的场景",
            userScenarios.Select(s =>
            {
                var img = s.Image;
                if (string.IsNullOrWhiteSpace(img))
                {
                    var first = s.Pages.FirstOrDefault();
                    if (first is not null && pagesById.TryGetValue(first.PageId, out var pd))
                    {
                        img = pd.Image;
                    }
                }
                return new HomeScenario(ToScenarioKey(ScenarioSource.User, s.Id), s.Name, img ?? "");
            }).ToList()
        );
 
        return my.Scenarios.Count > 0 ? new List<HomeCategory> { my }.Concat(sysCats).ToList() : sysCats;
    }
 
    public Dictionary<string, string> BuildScenarioImageMapForUser(string username)
    {
        var map = new Dictionary<string, string>(StringComparer.Ordinal);
        var cats = LoadHomeCatalogForUser(username);
        foreach (var c in cats)
        {
            foreach (var s in c.Scenarios)
            {
                map[s.Id] = s.Image;
            }
        }
        return map;
    }
 
    public sealed record ScenarioPage(string Id, string Title, string BoardUrl, int Staytime);
    public sealed record Scenario(string Id, string Name, string Image, List<ScenarioPage> Pages);
 
    public sealed record ResolvedScenario(ScenarioSource Source, Scenario Scenario);
 
    private static List<ScenarioPage> ExpandPages(IEnumerable<ScenarioPageRef> refs, Dictionary<string, PageDef> pagesById)
    {
        var list = new List<ScenarioPage>();
        foreach (var r in refs)
        {
            if (r is null) continue;
            if (!pagesById.TryGetValue(r.PageId, out var def)) continue;
            list.Add(new ScenarioPage(def.Id, def.Title, def.BoardUrl, r.Staytime));
        }
        return list;
    }
 
    public ResolvedScenario? ResolveScenarioForUser(string username, string scenarioKey)
    {
        var pagesById = PageMap();
        var key = ParseScenarioKey(scenarioKey);
 
        if (key.Source == ScenarioSource.System)
        {
            var sys = _cfg.LoadSystemScenariosConfig();
            foreach (var cat in sys.Categories)
            {
                foreach (var sc in cat.Scenarios)
                {
                    if (!string.Equals(sc.Id, key.ScenarioId, StringComparison.Ordinal)) continue;
                    var pages = ExpandPages(sc.Pages, pagesById);
                    return new ResolvedScenario(
                        ScenarioSource.System,
                        new Scenario(ToScenarioKey(ScenarioSource.System, sc.Id), sc.Name, sc.Image, pages)
                    );
                }
            }
            return null;
        }
 
        var users = _cfg.LoadUserScenariosConfig();
        if (!users.Users.TryGetValue(username, out var u)) return null;
        var mine = u.Scenarios ?? new List<UserScenario>();
        var usc = mine.FirstOrDefault(x => string.Equals(x.Id, key.ScenarioId, StringComparison.Ordinal));
        if (usc is null) return null;
        var upages = ExpandPages(usc.Pages, pagesById);
        return new ResolvedScenario(
            ScenarioSource.User,
            new Scenario(ToScenarioKey(ScenarioSource.User, usc.Id), usc.Name, usc.Image, upages)
        );
    }
}