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 { cleanObject, serializeAntenna, serializeTiming } from '../serializers';
8import { enqueueFullSync, enqueueGranularSync } from '../syncQueue';
9import { Antenna, AssetActions, ScenarioStore } from '../types';
10import { buildScenarioJson } from './backendSlice';
12export const createAssetSlice: StateCreator<
14 [['zustand/immer', never]],
20 const id = generateSimId('Waveform');
21 state.waveforms.push({
24 name: `Waveform ${state.waveforms.length + 1}`,
28 // libfers has no granular add API for Waveforms — full sync is required.
29 void enqueueFullSync(() => buildScenarioJson(get()));
33 const id = generateSimId('Timing');
37 name: `Timing ${state.timings.length + 1}`,
41 // libfers has no granular add API for Timings — full sync is required.
42 void enqueueFullSync(() => buildScenarioJson(get()));
46 const id = generateSimId('Antenna');
50 name: `Antenna ${state.antennas.length + 1}`,
54 // libfers has no granular add API for Antennas — full sync is required.
55 void enqueueFullSync(() => buildScenarioJson(get()));
57 addNoiseEntry: (timingId) => {
60 const timing = state.timings.find((t) => t.id === timingId);
62 timing.noiseEntries.push({
63 id: generateSimId('Timing'),
72 const timing = get().timings.find((t) => t.id === timingId);
74 void enqueueGranularSync(
77 JSON.stringify(cleanObject(serializeTiming(timing)))
82 removeNoiseEntry: (timingId, entryId) => {
85 const timing = state.timings.find((t) => t.id === timingId);
87 const index = timing.noiseEntries.findIndex(
88 (e) => e.id === entryId
91 timing.noiseEntries.splice(index, 1);
98 const timing = get().timings.find((t) => t.id === timingId);
100 void enqueueGranularSync(
103 JSON.stringify(cleanObject(serializeTiming(timing)))
108 setAntennaPattern: (antennaId, newPattern) => {
111 const index = state.antennas.findIndex((a) => a.id === antennaId);
112 if (index === -1) return;
113 delete state.antennaPreviewErrors[antennaId];
115 const oldAntenna = state.antennas[index];
116 const baseAntenna = {
118 type: oldAntenna.type,
119 name: oldAntenna.name,
120 efficiency: oldAntenna.efficiency,
121 meshScale: oldAntenna.meshScale,
122 design_frequency: oldAntenna.design_frequency,
125 let newAntennaState: Antenna;
127 switch (newPattern) {
131 pattern: 'isotropic',
168 state.antennas[index] = newAntennaState;
169 state.isDirty = true;
173 const antenna = get().antennas.find((a) => a.id === antennaId);
175 void enqueueGranularSync(
178 JSON.stringify(cleanObject(serializeAntenna(antenna)))