LenovoLegionToolkit

Форк
0
267 строк · 11.3 Кб
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Threading.Tasks;
5
using LenovoLegionToolkit.Lib.Extensions;
6
using LenovoLegionToolkit.Lib.Settings;
7
using LenovoLegionToolkit.Lib.SoftwareDisabler;
8
using LenovoLegionToolkit.Lib.Utils;
9

10
namespace LenovoLegionToolkit.Lib.Controllers.GodMode;
11

12
public abstract class AbstractGodModeController : IGodModeController
13
{
14
    private readonly GodModeSettings _settings;
15

16
    protected readonly VantageDisabler VantageDisabler;
17
    protected readonly LegionZoneDisabler LegionZoneDisabler;
18

19
    public event EventHandler<Guid>? PresetChanged;
20

21
    protected AbstractGodModeController(GodModeSettings settings, VantageDisabler vantageDisabler, LegionZoneDisabler legionZoneDisabler)
22
    {
23
        _settings = settings ?? throw new ArgumentNullException(nameof(settings));
24
        VantageDisabler = vantageDisabler ?? throw new ArgumentNullException(nameof(vantageDisabler));
25
        LegionZoneDisabler = legionZoneDisabler ?? throw new ArgumentNullException(nameof(legionZoneDisabler));
26
    }
27

28
    public abstract Task<bool> NeedsVantageDisabledAsync();
29

30
    public abstract Task<bool> NeedsLegionZoneDisabledAsync();
31

32
    public Task<Guid> GetActivePresetIdAsync() => Task.FromResult(_settings.Store.ActivePresetId);
33

34
    public Task<string?> GetActivePresetNameAsync()
35
    {
36
        var store = _settings.Store;
37
        var name = store.Presets
38
            .Where(p => p.Key == store.ActivePresetId)
39
            .Select(p => p.Value.Name)
40
            .FirstOrDefault();
41
        return Task.FromResult(name);
42
    }
43

44
    public async Task<GodModeState> GetStateAsync()
45
    {
46
        if (Log.Instance.IsTraceEnabled)
47
            Log.Instance.Trace($"Getting state...");
48

49
        var store = _settings.Store;
50
        var defaultState = await GetDefaultStateAsync().ConfigureAwait(false);
51

52
        if (!IsValidStore(store))
53
        {
54
            if (Log.Instance.IsTraceEnabled)
55
                Log.Instance.Trace($"Loading default state...");
56

57
            var id = Guid.NewGuid();
58
            return new GodModeState
59
            {
60
                ActivePresetId = id,
61
                Presets = new Dictionary<Guid, GodModePreset> { { id, defaultState } }.AsReadOnlyDictionary()
62
            };
63
        }
64

65
        if (Log.Instance.IsTraceEnabled)
66
            Log.Instance.Trace($"Loading state from store...");
67

68
        return await LoadStateFromStoreAsync(store, defaultState).ConfigureAwait(false);
69
    }
70

71
    public Task SetStateAsync(GodModeState state)
72
    {
73
        if (Log.Instance.IsTraceEnabled)
74
            Log.Instance.Trace($"Settings state: {state}");
75

76
        var activePresetId = state.ActivePresetId;
77
        var presets = new Dictionary<Guid, GodModeSettings.GodModeSettingsStore.Preset>();
78

79
        foreach (var (id, preset) in state.Presets)
80
        {
81
            presets.Add(id, new()
82
            {
83
                Name = preset.Name,
84
                CPULongTermPowerLimit = preset.CPULongTermPowerLimit,
85
                CPUShortTermPowerLimit = preset.CPUShortTermPowerLimit,
86
                CPUPeakPowerLimit = preset.CPUPeakPowerLimit,
87
                CPUCrossLoadingPowerLimit = preset.CPUCrossLoadingPowerLimit,
88
                CPUPL1Tau = preset.CPUPL1Tau,
89
                APUsPPTPowerLimit = preset.APUsPPTPowerLimit,
90
                CPUTemperatureLimit = preset.CPUTemperatureLimit,
91
                GPUPowerBoost = preset.GPUPowerBoost,
92
                GPUConfigurableTGP = preset.GPUConfigurableTGP,
93
                GPUTemperatureLimit = preset.GPUTemperatureLimit,
94
                GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline = preset.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline,
95
                GPUToCPUDynamicBoost = preset.GPUToCPUDynamicBoost,
96
                FanTable = preset.FanTableInfo?.Table,
97
                FanFullSpeed = preset.FanFullSpeed,
98
                MinValueOffset = preset.MinValueOffset,
99
                MaxValueOffset = preset.MaxValueOffset,
100
            });
101
        }
102

103
        _settings.Store.ActivePresetId = activePresetId;
104
        _settings.Store.Presets = presets;
105
        _settings.SynchronizeStore();
106

107
        if (Log.Instance.IsTraceEnabled)
108
            Log.Instance.Trace($"State saved.");
109

110
        return Task.CompletedTask;
111
    }
112

113
    public abstract Task ApplyStateAsync();
114

115
    public Task<FanTable> GetDefaultFanTableAsync()
116
    {
117
        var fanTable = new FanTable(new ushort[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
118
        return Task.FromResult(fanTable);
119
    }
120

121
    public abstract Task<FanTable> GetMinimumFanTableAsync();
122

123
    public abstract Task<Dictionary<PowerModeState, GodModeDefaults>> GetDefaultsInOtherPowerModesAsync();
124

125
    public abstract Task RestoreDefaultsInOtherPowerModeAsync(PowerModeState state);
126

127
    protected abstract Task<GodModePreset> GetDefaultStateAsync();
128

129
    protected void RaisePresetChanged(Guid presetId) => PresetChanged?.Invoke(this, presetId);
130

131
    protected async Task<(Guid, GodModeSettings.GodModeSettingsStore.Preset)> GetActivePresetAsync()
132
    {
133
        if (!IsValidStore(_settings.Store))
134
        {
135
            if (Log.Instance.IsTraceEnabled)
136
                Log.Instance.Trace($"Invalid store, generating default one.");
137

138
            var state = await GetStateAsync().ConfigureAwait(false);
139
            await SetStateAsync(state).ConfigureAwait(false);
140
        }
141

142
        var activePresetId = _settings.Store.ActivePresetId;
143
        var presets = _settings.Store.Presets;
144

145
        if (presets.TryGetValue(activePresetId, out var activePreset))
146
            return (activePresetId, activePreset);
147

148
        throw new InvalidOperationException($"Preset with ID {activePresetId} not found.");
149
    }
150

151
    protected async Task<bool> IsValidFanTableAsync(FanTable fanTable)
152
    {
153
        var minimumFanTable = await GetMinimumFanTableAsync().ConfigureAwait(false);
154
        var minimum = minimumFanTable.GetTable();
155
        return fanTable.GetTable().Where((t, i) => t < minimum[i] || t > 10u).IsEmpty();
156
    }
157

158
    private static bool IsValidStore(GodModeSettings.GodModeSettingsStore store) => store.Presets.Any() && store.Presets.ContainsKey(store.ActivePresetId);
159

160
    private async Task<GodModeState> LoadStateFromStoreAsync(GodModeSettings.GodModeSettingsStore store, GodModePreset defaultState)
161
    {
162
        var states = new Dictionary<Guid, GodModePreset>();
163

164
        foreach (var (id, preset) in store.Presets)
165
        {
166
            states.Add(id, new GodModePreset
167
            {
168
                Name = preset.Name,
169
                CPULongTermPowerLimit = CreateStepperValue(defaultState.CPULongTermPowerLimit, preset.CPULongTermPowerLimit, preset.MinValueOffset, preset.MaxValueOffset),
170
                CPUShortTermPowerLimit = CreateStepperValue(defaultState.CPUShortTermPowerLimit, preset.CPUShortTermPowerLimit, preset.MinValueOffset, preset.MaxValueOffset),
171
                CPUPeakPowerLimit = CreateStepperValue(defaultState.CPUPeakPowerLimit, preset.CPUPeakPowerLimit, preset.MinValueOffset, preset.MaxValueOffset),
172
                CPUCrossLoadingPowerLimit = CreateStepperValue(defaultState.CPUCrossLoadingPowerLimit, preset.CPUCrossLoadingPowerLimit, preset.MinValueOffset, preset.MaxValueOffset),
173
                CPUPL1Tau = CreateStepperValue(defaultState.CPUPL1Tau, preset.CPUPL1Tau, preset.MinValueOffset, preset.MaxValueOffset),
174
                APUsPPTPowerLimit = CreateStepperValue(defaultState.APUsPPTPowerLimit, preset.APUsPPTPowerLimit, preset.MinValueOffset, preset.MaxValueOffset),
175
                CPUTemperatureLimit = CreateStepperValue(defaultState.CPUTemperatureLimit, preset.CPUTemperatureLimit, preset.MinValueOffset, preset.MaxValueOffset),
176
                GPUPowerBoost = CreateStepperValue(defaultState.GPUPowerBoost, preset.GPUPowerBoost, preset.MinValueOffset, preset.MaxValueOffset),
177
                GPUConfigurableTGP = CreateStepperValue(defaultState.GPUConfigurableTGP, preset.GPUConfigurableTGP, preset.MinValueOffset, preset.MaxValueOffset),
178
                GPUTemperatureLimit = CreateStepperValue(defaultState.GPUTemperatureLimit, preset.GPUTemperatureLimit, preset.MinValueOffset, preset.MaxValueOffset),
179
                GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline = CreateStepperValue(defaultState.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline,
180
                    preset.GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline,
181
                    preset.MinValueOffset,
182
                    preset.MaxValueOffset),
183
                GPUToCPUDynamicBoost = CreateStepperValue(defaultState.GPUToCPUDynamicBoost, preset.GPUToCPUDynamicBoost),
184
                FanTableInfo = await GetFanTableInfoAsync(preset, defaultState.FanTableInfo?.Data).ConfigureAwait(false),
185
                FanFullSpeed = preset.FanFullSpeed,
186
                MinValueOffset = preset.MinValueOffset ?? defaultState.MinValueOffset,
187
                MaxValueOffset = preset.MaxValueOffset ?? defaultState.MaxValueOffset
188
            });
189
        }
190

191
        return new GodModeState
192
        {
193
            ActivePresetId = store.ActivePresetId,
194
            Presets = states.AsReadOnlyDictionary()
195
        };
196
    }
197

198
    private static StepperValue? CreateStepperValue(StepperValue? state, StepperValue? store = null, int? minValueOffset = 0, int? maxValueOffset = 0)
199
    {
200
        if (state is not { } stateValue)
201
            return null;
202

203
        if (stateValue.Steps.Length > 0)
204
        {
205
            var value = store?.Value ?? stateValue.Value;
206
            var steps = stateValue.Steps;
207
            var defaultValue = stateValue.DefaultValue;
208

209
            if (!steps.Contains(value))
210
            {
211
                var valueTemp = value;
212
                value = steps.MinBy(v => Math.Abs((long)v - valueTemp));
213
            }
214

215
            return new(value, 0, 0, 0, steps, defaultValue);
216
        }
217

218
        if (stateValue.Step > 0)
219
        {
220
            var value = store?.Value ?? stateValue.Value;
221
            var min = Math.Max(0, stateValue.Min + (minValueOffset ?? 0));
222
            var max = stateValue.Max + (maxValueOffset ?? 0);
223
            var step = stateValue.Step;
224
            var defaultValue = stateValue.DefaultValue;
225

226
            value = MathExtensions.RoundNearest(value, step);
227

228
            if (value < min || value > max)
229
                value = defaultValue ?? Math.Clamp(value, min, max);
230

231
            return new(value, min, max, step, Array.Empty<int>(), defaultValue);
232
        }
233

234
        return null;
235
    }
236

237
    private async Task<FanTableInfo?> GetFanTableInfoAsync(GodModeSettings.GodModeSettingsStore.Preset preset, FanTableData[]? fanTableData)
238
    {
239
        if (Log.Instance.IsTraceEnabled)
240
            Log.Instance.Trace($"Getting fan table info...");
241

242
        if (fanTableData is null)
243
        {
244
            if (Log.Instance.IsTraceEnabled)
245
                Log.Instance.Trace($"Fan table data is null");
246
            return null;
247
        }
248

249
        if (Log.Instance.IsTraceEnabled)
250
            Log.Instance.Trace($"Fan table data retrieved: {fanTableData}");
251

252
        var fanTable = preset.FanTable ?? await GetDefaultFanTableAsync().ConfigureAwait(false);
253

254
        if (Log.Instance.IsTraceEnabled)
255
            Log.Instance.Trace($"Fan table retrieved: {fanTable}");
256

257
        if (!await IsValidFanTableAsync(fanTable).ConfigureAwait(false))
258
        {
259
            if (Log.Instance.IsTraceEnabled)
260
                Log.Instance.Trace($"Fan table invalid, replacing with default...");
261

262
            fanTable = await GetDefaultFanTableAsync().ConfigureAwait(false);
263
        }
264

265
        return new FanTableInfo(fanTableData, fanTable);
266
    }
267
}
268

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.