Critical Stability & Performance fixes. Excessive Log Set button gone on QIuck Log screen

This commit is contained in:
AG
2025-12-06 08:58:44 +02:00
parent 27afacee3f
commit 1c3e15516c
35 changed files with 48 additions and 26 deletions

View File

@@ -0,0 +1,127 @@
import { WorkoutSession, UserProfile, WorkoutPlan } from '../types';
import { api } from './api';
import { generateId } from '../utils/uuid';
interface FitnessChatOptions {
history: WorkoutSession[];
userProfile?: UserProfile;
plans?: WorkoutPlan[];
lang?: 'en' | 'ru';
sessionId?: string;
}
export const createFitnessChat = (
history: WorkoutSession[],
lang: 'en' | 'ru' = 'ru',
userProfile?: UserProfile,
plans?: WorkoutPlan[]
): any => {
// Generate a unique session ID for this chat instance
const sessionId = generateId();
// Summarize workout history
const workoutSummary = history.slice(0, 20).map(s => ({
date: new Date(s.startTime).toLocaleDateString(lang === 'ru' ? 'ru-RU' : 'en-US'),
userWeight: s.userBodyWeight,
planName: s.planName,
exercises: s.sets.map(set => {
const parts = [];
parts.push(set.exerciseName);
if (set.weight) parts.push(`${set.weight}${lang === 'ru' ? 'кг' : 'kg'}`);
if (set.reps) parts.push(`${set.reps}${lang === 'ru' ? 'повт' : 'reps'}`);
if (set.distanceMeters) parts.push(`${set.distanceMeters}${lang === 'ru' ? 'м' : 'm'}`);
if (set.durationSeconds) parts.push(`${set.durationSeconds}${lang === 'ru' ? 'сек' : 's'}`);
return parts.join(' ');
}).join(', ')
}));
// Calculate personal records
const exerciseRecords = new Map<string, { maxWeight?: number; maxReps?: number; maxDistance?: number }>();
history.forEach(session => {
session.sets.forEach(set => {
const current = exerciseRecords.get(set.exerciseName) || {};
exerciseRecords.set(set.exerciseName, {
maxWeight: Math.max(current.maxWeight || 0, set.weight || 0),
maxReps: Math.max(current.maxReps || 0, set.reps || 0),
maxDistance: Math.max(current.maxDistance || 0, set.distanceMeters || 0)
});
});
});
const personalRecords = Array.from(exerciseRecords.entries()).map(([name, records]) => ({
exercise: name,
...records
}));
// Build comprehensive system instruction
const systemInstruction = lang === 'ru' ? `
Ты — опытный и поддерживающий фитнес-тренер AI Coach.
Твоя задача — анализировать тренировки пользователя и давать краткие, полезные советы на русском языке.
ДАННЫЕ ПОЛЬЗОВАТЕЛЯ:
${userProfile ? `
- Вес: ${userProfile.weight || 'не указан'} кг
- Рост: ${userProfile.height || 'не указан'} см
- Пол: ${userProfile.gender || 'не указан'}
` : 'Профиль не заполнен'}
ТРЕНИРОВОЧНЫЕ ПЛАНЫ:
${plans && plans.length > 0 ? JSON.stringify(plans.map(p => ({ name: p.name, exercises: p.steps.map(s => s.exerciseName) }))) : 'Нет активных планов'}
ИСТОРИЯ ТРЕНИРОВОК (последние 20):
${JSON.stringify(workoutSummary, null, 2)}
ЛИЧНЫЕ РЕКОРДЫ:
${JSON.stringify(personalRecords, null, 2)}
ИНСТРУКЦИИ:
- Используй эти данные для анализа прогресса и ответов на вопросы
- Учитывай вес пользователя при анализе упражнений с собственным весом
- Будь конкретным и ссылайся на реальные данные из истории
- Отвечай емко, мотивирующе
- Если данных недостаточно для ответа, честно скажи об этом
` : `
You are an experienced and supportive fitness coach called AI Coach.
Your task is to analyze the user's workouts and provide concise, helpful advice in English.
USER PROFILE:
${userProfile ? `
- Weight: ${userProfile.weight || 'not specified'} kg
- Height: ${userProfile.height || 'not specified'} cm
- Gender: ${userProfile.gender || 'not specified'}
` : 'Profile not filled'}
WORKOUT PLANS:
${plans && plans.length > 0 ? JSON.stringify(plans.map(p => ({ name: p.name, exercises: p.steps.map(s => s.exerciseName) }))) : 'No active plans'}
WORKOUT HISTORY (last 20 sessions):
${JSON.stringify(workoutSummary, null, 2)}
PERSONAL RECORDS:
${JSON.stringify(personalRecords, null, 2)}
INSTRUCTIONS:
- Use this data to analyze progress and answer questions
- Consider user's weight when analyzing bodyweight exercises
- Be specific and reference actual data from the history
- Answer concisely and motivationally
- If there's insufficient data to answer, be honest about it
- ALWAYS answer in the language the user speaks to you
`;
return {
sendMessage: async (userMessage: string) => {
const res = await api.post('/ai/chat', {
systemInstruction,
userMessage,
sessionId
});
return {
text: res.response,
response: {
text: () => res.response
}
};
}
};
};