DCSOlympus/frontend/react/src/sessiondata.ts
2024-12-19 15:43:27 +01:00

198 lines
7.5 KiB
TypeScript

import { LatLng } from "leaflet";
import { AudioSink } from "./audio/audiosink";
import { FileSource } from "./audio/filesource";
import { RadioSink } from "./audio/radiosink";
import { UnitSink } from "./audio/unitsink";
import { OlympusState } from "./constants/constants";
import {
AudioSinksChangedEvent,
AudioSourcesChangedEvent,
CoalitionAreasChangedEvent,
HotgroupsChangedEvent,
SessionDataChangedEvent,
SessionDataLoadedEvent,
SessionDataSavedEvent,
} from "./events";
import { SessionData } from "./interfaces";
import { CoalitionCircle } from "./map/coalitionarea/coalitioncircle";
import { CoalitionPolygon } from "./map/coalitionarea/coalitionpolygon";
import { getApp } from "./olympusapp";
export class SessionDataManager {
#sessionData: SessionData = {};
#sessionHash: string = "";
#saveSessionDataTimeout: number | null = null;
constructor() {
SessionDataLoadedEvent.on(() => {
/* Wait for all the loading to be completed before enabling session data saving */
window.setTimeout(() => {
AudioSinksChangedEvent.on((audioSinks) => {
if (getApp().getAudioManager().isRunning()) {
this.#sessionData.radios = audioSinks
.filter((sink) => sink instanceof RadioSink)
.map((radioSink) => {
return {
frequency: radioSink.getFrequency(),
modulation: radioSink.getModulation(),
pan: radioSink.getPan(),
};
});
this.#sessionData.unitSinks = audioSinks
.filter((sink) => sink instanceof UnitSink)
.map((unitSink) => {
return {
ID: unitSink.getUnit().ID,
};
});
this.#sessionData.connections = [];
let counter = 0;
let sources = getApp().getAudioManager().getSources();
let sinks = getApp().getAudioManager().getSinks();
sources.forEach((source, idx) => {
counter++;
source.getConnectedTo().forEach((sink) => {
if (sinks.indexOf(sink as AudioSink) !== undefined) {
this.#sessionData.connections?.push([idx, sinks.indexOf(sink as AudioSink)]);
}
});
});
this.#saveSessionData();
}
});
AudioSourcesChangedEvent.on((audioSources) => {
if (getApp().getAudioManager().isRunning()) {
this.#sessionData.fileSources = audioSources
.filter((sink) => sink instanceof FileSource)
.map((fileSource) => {
return { filename: fileSource.getFilename(), volume: fileSource.getVolume() };
});
this.#sessionData.connections = [];
let counter = 0;
let sources = getApp().getAudioManager().getSources();
let sinks = getApp().getAudioManager().getSinks();
sources.forEach((source, idx) => {
counter++;
source.getConnectedTo().forEach((sink) => {
if (sinks.indexOf(sink as AudioSink) !== undefined) {
this.#sessionData.connections?.push([idx, sinks.indexOf(sink as AudioSink)]);
}
});
});
this.#saveSessionData();
}
});
CoalitionAreasChangedEvent.on(() => {
this.#sessionData.coalitionAreas = [];
getApp()
.getCoalitionAreasManager()
.getAreas()
.forEach((area) => {
if (area instanceof CoalitionCircle) {
this.#sessionData.coalitionAreas?.push({
type: "circle",
latlng: { lat: area.getLatLng().lat, lng: area.getLatLng().lng },
coalition: area.getCoalition(),
label: area.getLabelText(),
radius: area.getRadius(),
});
} else if (area instanceof CoalitionPolygon) {
this.#sessionData.coalitionAreas?.push({
type: "polygon",
latlngs: (area.getLatLngs()[0] as LatLng[]).map((latlng) => {
return { lat: latlng.lat, lng: latlng.lng };
}),
coalition: area.getCoalition(),
label: area.getLabelText(),
});
}
});
this.#saveSessionData();
});
HotgroupsChangedEvent.on((hotgroups) => {
this.#sessionData.hotgroups = {};
Object.keys(hotgroups).forEach((hotgroup) => {
(this.#sessionData.hotgroups as { [key: string]: number[] })[hotgroup] = hotgroups[hotgroup].map((unit) => unit.ID);
});
this.#saveSessionData();
});
}, 200);
});
}
loadSessionData(sessionHash?: string) {
if (getApp().getState() === OlympusState.SERVER) return;
if (sessionHash) this.#sessionHash = sessionHash;
if (this.#sessionHash === undefined) {
console.error("Trying to load session data but no session hash provided");
return;
}
const requestOptions = {
method: "PUT", // Specify the request method
headers: { "Content-Type": "application/json" }, // Specify the content type
body: JSON.stringify({ sessionHash }), // Send the data in JSON format
};
fetch(`./resources/sessiondata/load/${getApp().getServerManager().getUsername()}`, requestOptions)
.then((response) => {
if (response.status === 200) {
console.log(`Session data for profile ${getApp().getServerManager().getUsername()} and session hash ${sessionHash} loaded correctly`);
return response.json();
} else {
getApp().addInfoMessage("No session data found for this profile");
throw new Error("No session data found for this profile");
}
}) // Parse the response as JSON
.then((sessionData) => {
this.#sessionData = sessionData;
console.log(this.#sessionData);
SessionDataLoadedEvent.dispatch(this.#sessionData);
})
.catch((error) => console.error(error)); // Handle errors
}
getSessionData() {
return this.#sessionData;
}
#saveSessionData() {
if (getApp().getState() === OlympusState.SERVER) return;
SessionDataChangedEvent.dispatch(this.#sessionData);
if (this.#saveSessionDataTimeout) window.clearTimeout(this.#saveSessionDataTimeout);
this.#saveSessionDataTimeout = window.setTimeout(() => {
const requestOptions = {
method: "PUT", // Specify the request method
headers: { "Content-Type": "application/json" }, // Specify the content type
body: JSON.stringify({ sessionHash: this.#sessionHash, sessionData: this.#sessionData }), // Send the data in JSON format
};
fetch(`./resources/sessiondata/save/${getApp().getServerManager().getUsername()}`, requestOptions)
.then((response) => {
if (response.status === 200) {
console.log(`Session data for profile ${getApp().getServerManager().getUsername()} and session hash ${this.#sessionHash} saved correctly`);
console.log(this.#sessionData);
SessionDataSavedEvent.dispatch(this.#sessionData);
} else {
getApp().addInfoMessage("Error loading session data");
throw new Error("Error loading session data");
}
}) // Parse the response as JSON
.catch((error) => console.error(error)); // Handle errors
this.#saveSessionDataTimeout = null;
}, 1000);
}
}