// services/state-manager.js - Central state management import { Utils } from '../utils.js'; export const StateManager = { // Session data sessionId: Utils.generateSessionId(), // User profile profile: { ageGroup: '', gender: '', roles: [], participantId: '' }, // Consent consentGranted: false, // Language currentLang: (() => { const browserLang = navigator.language.split('-')[0]; const defaultLang = ['en', 'fr'].includes(browserLang) ? browserLang : 'en'; return localStorage.getItem('preferredLang') || defaultLang; })(), // Chat data - stores messages and conversation IDs for each model modelChats: { "skills_wiki": { messages: [], conversation_id: Utils.generateConversationId() }, // "qwen": { // messages: [], // conversation_id: Utils.generateConversationId() // }, "openai": { messages: [], conversation_id: Utils.generateConversationId() }, "google-conservative": { messages: [], conversation_id: Utils.generateConversationId() }, "google-creative": { messages: [], conversation_id: Utils.generateConversationId() }, "fake": { messages: [], conversation_id: Utils.generateConversationId() } }, // File upload state sessionFiles: [], // Font size fontSize: 1, // 1rem = browser default /** * Update user profile * @param {Object} profileData - Profile data object */ updateProfile(profileData) { this.profile = { ...this.profile, ...profileData }; }, /** * Set consent status * @param {boolean} granted - Whether consent is granted */ setConsent(granted) { this.consentGranted = granted; }, /** * Set current language and save to localStorage * @param {string} lang - Language code ('en' or 'fr') */ setLanguage(lang) { this.currentLang = lang; localStorage.setItem('preferredLang', lang); }, /** * Add a message to the current model's chat * @param {string} modelType - The model type * @param {Object} message - Message object with role, content, and kgCO2eq */ addMessage(modelType, message) { this.modelChats[modelType].messages.push(message); }, /** * Get messages for a specific model * @param {string} modelType - The model type * @returns {Array} Array of messages */ getMessages(modelType) { return this.modelChats[modelType].messages; }, /** * Get conversation ID for a specific model * @param {string} modelType - The model type * @returns {string} Conversation ID */ getConversationId(modelType) { return this.modelChats[modelType].conversation_id; }, /** * Clear conversation for a specific model * @param {string} modelType - The model type */ clearConversation(modelType) { this.modelChats[modelType].messages = []; this.modelChats[modelType].conversation_id = Utils.generateConversationId(); }, /** * Add file to session * @param {File} file - File object */ addFile(file) { this.sessionFiles.push(file); }, /** * Remove file from session * @param {File} file - File object to remove */ removeFile(file) { this.sessionFiles = this.sessionFiles.filter(f => f !== file); }, /** * Get all session files * @returns {Array} Array of files */ getFiles() { return this.sessionFiles; }, /** * Set font size * @param {number} size - Font size in rem */ setFontSize(size) { this.fontSize = size; }, /** * Get total carbon emissions for a specific model type * @param {string} modelType - The model type (e.g., 'skills_wiki', 'openai') * @returns {number} Total kgCO2eq for this model */ getTotalEmissions(modelType) { const chat = this.modelChats[modelType]; if (!chat || !chat.messages) return 0; return chat.messages.reduce((total, message) => { return total + (message.gwpKgcoeq || 0); }, 0); }, /** * Get total water consumption for a specific model type * @param {string} modelType - The model type (e.g., 'skills_wiki', 'openai') * @returns {number} Total L for this model */ getTotalWater(modelType) { const chat = this.modelChats[modelType]; if (!chat || !chat.messages) return 0; return chat.messages.reduce((total, message) => { return total + (message.waterL || 0); }, 0); }, /** * Get total electricity consumption for a specific model type * @param {string} modelType - The model type (e.g., 'skills_wiki', 'openai') * @returns {number} Total kWh for this model */ getTotalElectricity(modelType) { const chat = this.modelChats[modelType]; if (!chat || !chat.messages) return 0; return chat.messages.reduce((total, message) => { return total + (message.electricityKWh || 0); }, 0); }, /** * Get total carbon emissions across all models * @returns {number} Total kgCO2eq across all models */ getAllEmissions() { return Object.keys(this.modelChats).reduce((total, modelType) => { return total + this.getTotalEmissions(modelType); }, 0); }, /** * Get total carbon emissions across all models * @returns {number} Total kgCO2eq across all models */ getAllWater() { return Object.keys(this.modelChats).reduce((total, modelType) => { return total + this.getTotalWater(modelType); }, 0); }, /** * Get total carbon emissions across all models * @returns {number} Total kgCO2eq across all models */ getAllElectricity() { return Object.keys(this.modelChats).reduce((total, modelType) => { return total + this.getTotalElectricity(modelType); }, 0); }, /** * Get emissions breakdown by model * @returns {Object} Object with model types as keys and emissions as values */ getEmissionsBreakdown() { const breakdown = {}; Object.keys(this.modelChats).forEach(modelType => { breakdown[modelType] = this.getTotalEmissions(modelType); }); return breakdown; }, };