1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2025-present FERS Contributors (see AUTHORS.md).
4import { StateCreator } from 'zustand';
5import { defaultAntenna, defaultTiming, defaultWaveform } from '../defaults';
6import { generateSimId } from '../idUtils';
7import { createUniqueScenarioName } from '../nameUtils';
8import { cleanObject, serializeAntenna, serializeTiming } from '../serializers';
10 enqueueFullSyncDetached,
11 enqueueGranularSyncDetached,
13import { Antenna, AssetActions, ScenarioStore } from '../types';
14import { buildScenarioJson } from './backendSlice';
16export const createAssetSlice: StateCreator<
18 [['zustand/immer', never]],
24 const id = generateSimId('Waveform');
25 state.waveforms.push({
28 name: createUniqueScenarioName(
30 `Waveform ${state.waveforms.length + 1}`
35 // libfers has no granular add API for Waveforms — full sync is required.
36 enqueueFullSyncDetached(() => buildScenarioJson(get()));
40 const id = generateSimId('Timing');
44 name: createUniqueScenarioName(
46 `Timing ${state.timings.length + 1}`
51 // libfers has no granular add API for Timings — full sync is required.
52 enqueueFullSyncDetached(() => buildScenarioJson(get()));
56 const id = generateSimId('Antenna');
60 name: createUniqueScenarioName(
62 `Antenna ${state.antennas.length + 1}`
67 // libfers has no granular add API for Antennas — full sync is required.
68 enqueueFullSyncDetached(() => buildScenarioJson(get()));
70 addNoiseEntry: (timingId) => {
73 const timing = state.timings.find((t) => t.id === timingId);
75 timing.noiseEntries.push({
76 id: generateSimId('Timing'),
85 const timing = get().timings.find((t) => t.id === timingId);
87 enqueueGranularSyncDetached(
90 JSON.stringify(cleanObject(serializeTiming(timing)))
95 removeNoiseEntry: (timingId, entryId) => {
98 const timing = state.timings.find((t) => t.id === timingId);
100 const index = timing.noiseEntries.findIndex(
101 (e) => e.id === entryId
104 timing.noiseEntries.splice(index, 1);
105 state.isDirty = true;
111 const timing = get().timings.find((t) => t.id === timingId);
113 enqueueGranularSyncDetached(
116 JSON.stringify(cleanObject(serializeTiming(timing)))
121 setAntennaPattern: (antennaId, newPattern) => {
124 const index = state.antennas.findIndex((a) => a.id === antennaId);
125 if (index === -1) return;
126 delete state.antennaPreviewErrors[antennaId];
128 const oldAntenna = state.antennas[index];
129 const baseAntenna = {
131 type: oldAntenna.type,
132 name: oldAntenna.name,
133 efficiency: oldAntenna.efficiency,
134 meshScale: oldAntenna.meshScale,
135 design_frequency: oldAntenna.design_frequency,
138 let newAntennaState: Antenna;
140 switch (newPattern) {
144 pattern: 'isotropic',
181 state.antennas[index] = newAntennaState;
182 state.isDirty = true;
186 const antenna = get().antennas.find((a) => a.id === antennaId);
188 enqueueGranularSyncDetached(
191 JSON.stringify(cleanObject(serializeAntenna(antenna)))