help me create MUI form for user input/select OneClassSvm_param, HealthScore_param, and send back to @api.route('/train', methods=['POST'])
frontend
// frontend/src/components/Training.jsx
import React, { useState, useEffect, useContext } from 'react';
import axios from 'axios'; // Import Axios
import { Typography, Button, Paper, Box, Grid, Checkbox, FormControlLabel } from '@mui/material';

import { AppContext } from './AppContext';
import SectionBar from './SectionBar';
import NavigationButton from './NavigationButton';

const Training = ({ darkMode }) => {
    const { sharedState, setSharedState, updateSharedState, mergeSharedState } = useContext(AppContext);
    const [running, setRunning] = useState(false); // State to store the selected job type
    const [trainingMessage, setTrainingMessage] = useState('');
    
    const [selectedHealthScoreLabel, setSelectedHealthScoreLabel] = useState(null); // State to store the selected label
    const [selectedHealthScoreLabelArray, setSelectedHealthScoreLabelArray] = useState([]); // State to store the selected labels in an array
    const [selectAll, setSelectAll] = useState(false); // State to track "select all" checkbox status

    // Destructure values from sharedState
    const { 
        windowValue,
        labelColumn, 
        columns, 
        featureData, 
        codeLabelMapping,
        jobType, 
        framework, 
        modelOption,
    } = sharedState;






    // Function to generate random data for Feature 1 and Feature 2
    function generateRandomData(numPoints) {
        const data = [];

        for (let i = 0; i < numPoints; i++) {
            const feature1 = Math.random() * 100; // Random value between 0 and 100
            const feature2 = Math.random() * 100; // Random value between 0 and 100
            const label = Math.random() < 0.5 ? "A" : "B"; // Randomly select label "A" or "B"

            data.push({
                feature1: parseFloat(feature1.toFixed(2)), // Optional: round to 2 decimal places
                feature2: parseFloat(feature2.toFixed(2)), // Optional: round to 2 decimal places
                label: label // Add the label
            });
        }

        return data;
    }

    // Generate 100 random data points
    const randomData = generateRandomData(100);

    // Handle button click to set the selected label
    const handleLabelClick = (label) => {
        // Update local state with selected label
        setSelectedHealthScoreLabel(label);
        
        // Update sharedState with the selected label
        updateSharedState({ selectedHealthScoreLabel: label });
    };

    // Handle button click to toggle selection of a label
    const handleLabelsClick = (label) => {
        // Check if the label is already in the array
        const isSelected = selectedHealthScoreLabelArray.includes(label);

        // If it's selected, remove it from the array; otherwise, add it
        const updatedLabels = isSelected
            ? selectedHealthScoreLabelArray.filter(item => item !== label)
            : [...selectedHealthScoreLabelArray, label];

        // Update local state with the updated array
        setSelectedHealthScoreLabelArray(updatedLabels);
        
        // Update sharedState with the updated array
        updateSharedState({ selectedHealthScoreLabelArray: updatedLabels });
    };

    // Function to handle "select all" checkbox change
    const handleSelectAllChange = (event) => {
        const isChecked = event.target.checked;
        setSelectAll(isChecked);
        if (isChecked) {
            // Select all labels
            setSelectedHealthScoreLabelArray(Object.values(codeLabelMapping));
        } else {
            // Deselect all labels
            setSelectedHealthScoreLabelArray([]);
        }
    };

    const handleTrain = async () => {
        setRunning(true);
        setTrainingMessage('');
        
        try {
            const response = await axios.post('http://localhost:5000/api/train', {
                labelColumn: sharedState.labelColumn,
                columns: sharedState.columns,
                featureData: sharedState.featureData,
                codeLabelMapping: sharedState.codeLabelMapping, 
                jobType: sharedState.jobType,
                framework: sharedState.framework,
                modelOption: sharedState.modelOption,
                selectedHealthScoreLabelArray: sharedState.selectedHealthScoreLabelArray,
            });
            setTrainingMessage(response.data.message);
        } catch (error) {
            console.error("Error during training:", error);
            setTrainingMessage('Error during training, please try again.');
        } finally {
            setRunning(false);
        }
    };

    const validate = () => {
        const { value } = sharedState;
        // Check if value is not null, undefined, or an empty string
        return !!value; // This will return true if value has a truthy value
    };

    return (
        <div style={{ padding: '20px'}}>
            <SectionBar title="訓練" />

            <Paper elevation={3} style={{ padding: '20px', marginTop: '20px' }}>
                {/* Only show the buttons if jobType is "healthScore" */}
                {jobType === "healthScore" && codeLabelMapping && (
                    <div>
                        <Typography variant="h5">
                            健康分數
                        </Typography>
                        <Typography variant="h6" gutterBottom>
                            選擇欲監控的類別
                        </Typography>

                        <Box style={{ display: 'flex', flexWrap: 'wrap', marginTop: '20px' }}>
                            {Object.entries(codeLabelMapping).map(([key, label]) => {
                                // Function to calculate the width based on label length
                                const calculateButtonWidth = (label) => {
                                    const labelLength = label.length; // Get the length of the label text
                                    const minWidth = 100; // Minimum width for the button
                                    const extraWidth = labelLength * 8; // Add extra width for each character (adjust the multiplier as needed)
                                    return minWidth + extraWidth; // Return the total width
                                };
                                const buttonWidth = calculateButtonWidth(label);

                                return (
                                    <Button
                                        key={key}
                                        variant="outlined"
                                        style={{
                                            margin: '10px',
                                            minWidth: '100px', // Minimum width to prevent shrinking
                                            width: selectedHealthScoreLabelArray.includes(label) ? `${buttonWidth + 20}px` : `${buttonWidth}px`, // Set dynamic width
                                            height: '50px', // Increased height
                                            fontSize: '18px', // Font size
                                            whiteSpace: 'nowrap', // Prevent text wrapping to a new line
                                            textOverflow: 'ellipsis', // Add ellipsis if text overflows
                                            overflow: 'hidden', // Hide any overflow text
                                            border: selectedHealthScoreLabelArray.includes(label) ? '2px solid blue' : '1px solid #ccc',
                                            transition: 'all 0.3s',
                                        }}
                                        onClick={() => handleLabelsClick(label)}
                                    >
                                        {label}
                                    </Button>
                                );
                            })}
                        </Box>
                        <FormControlLabel
                            control={<Checkbox checked={selectAll} onChange={handleSelectAllChange} />}
                            label="Select All (綜合訓練)"
                            style={{ marginBottom: '20px' }}
                        />
                    </div>
                )}

                {/* Example of using the sharedState values */}

                <Box sx={{ padding: 2 }}>
                    <Grid container spacing={2}>
                        <Grid item xs={12}>
                            <Typography variant="h6">Selected Job Type: <strong>{sharedState.jobType}</strong></Typography>
                        </Grid>
                        <Grid item xs={12}>
                            <Typography variant="h6">Framework: <strong>{sharedState.framework}</strong></Typography>
                        </Grid>
                        <Grid item xs={12}>
                            <Typography variant="h6">Model Option: <strong>{sharedState.modelOption}</strong></Typography>
                        </Grid>
                        <Grid item xs={12}>
                            <Typography variant="h6">Label Name: <strong>{sharedState.labelColumn}</strong></Typography>
                        </Grid>
                        <Grid item xs={12}>
                            <Typography variant="h6">Columns: 
                                <Box sx={{ maxHeight: 100, overflow: 'auto', fontFamily: 'monospace', fontSize: '0.875rem' }}>
                                {sharedState.columns?.join(', ')}
                                </Box>
                            </Typography>
                        </Grid>
                        <Grid item xs={12}>
                            <Typography variant="h6">Feature Data: 
                                <Box sx={{ maxHeight: 150, overflow: 'auto', fontFamily: 'monospace', fontSize: '0.875rem' }}>
                                {JSON.stringify(sharedState.featureData, null, 2)}
                                </Box>
                            </Typography>
                        </Grid>
                    </Grid>
                </Box>

                <Button 
                    variant="contained" 
                    color="primary" 
                    onClick={handleTrain} 
                    disabled={running}
                    style={{ marginTop: '20px' }}
                >
                    {running ? 'Training...' : 'Start Training'}
                </Button>

                {trainingMessage && <Typography variant="body1" style={{ marginTop: '20px' }}>{trainingMessage}</Typography>}
            </Paper>


            <NavigationButton nextRoute="/edge" validate={validate} style={{ marginTop: '20px' }}>
                    Next
            </NavigationButton>
        </div>
    );
};

export default Training;


backend
@api.route('/train', methods=['POST'])
def train_model():
    # access the models directory
    MODELS_DIR = current_app.config['MODELS_DIR']
    try:
        # Get data from the request
        label_column = request.json.get('labelColumn')
        columns = request.json.get('columns')
        feature_data = request.json.get('featureData')
        codeLabelMapping = request.json.get('codeLabelMapping')
        job_type = request.json.get('jobType')
        framework = request.json.get('framework')
        model_option = request.json.get('modelOption')
        selectedHealthScoreLabelArray = request.json.get('selectedHealthScoreLabelArray')

        # Check if label_column is None
        if job_type in ['regression', 'classification', 'timeSeriesForecasting'] and label_column is None:
            return jsonify({'message': 'Error: For supervised learning, label_column cannot be None.'}), 400

        # Convert feature_data to a DataFrame
        df = pd.DataFrame(feature_data, columns=columns)

        # Filter data based on selected labels if label_column and labels are provided
        if label_column and selectedHealthScoreLabelArray:
            if label_column not in df.columns:
                return jsonify({'message': f'Label column "{label_column}" not found in data.'}), 400
            # Filter the DataFrame to only include selected labels
            df = df[df[label_column].isin(selectedHealthScoreLabelArray)]
            if df.empty:
                return jsonify({'message': 'No data left after filtering with the selected labels.'}), 400

        # Exclude the label column from features
        if label_column and label_column in df.columns:
            feature_columns = [col for col in df.columns if col != label_column]
        else:
            feature_columns = df.columns.tolist()

        # Prepare the feature matrix X
        X = df[feature_columns].values

        # Get today's date
        today_date = datetime.now().strftime('%Y-%m-%d')
        # Create the model filename
        model_filename = f'{model_option}_model_{today_date}.pkl'

        if framework == "sklearn":
            
            if job_type == "healthScore":
                # Perform the scaler and PCA to reduce dimensionality to 2
                scaler = MinMaxScaler()  # This scales the data between 0 and 1
                pca = PCA(n_components=2)  # Reduces dimensionality to 2

                # Create a pipeline that first scales and then applies PCA
                pca_pipeline = Pipeline(steps=[
                    ('scaler', scaler),
                    ('pca', pca)
                ])

                # Fit and transform the feature data using the pipeline
                X_pca = pca_pipeline.fit_transform(X)

                # Parameters for One-Class SVM
                OneClassSvm_param = {
                    'kernel': 'rbf',   # You can adjust these parameters as needed
                    'gamma': 'auto',
                    'nu': 0.05
                }

                # HealthScore parameters
                HealthScore_param = {
                    'low_score': 75,     # Minimum health score
                    'high_score': 95,  # Maximum health score
                    'n_levels': 15      # Number of levels for mapping
                }

                # Fit One-Class SVM
                model_one_class_svm = OneClassSVM(
                    kernel=OneClassSvm_param['kernel'],
                    gamma=OneClassSvm_param['gamma'],
                    nu=OneClassSvm_param['nu']
                ).fit(X_pca)

                # Generate a mesh grid for decision function visualization (optional)
                xx_boundary = [X_pca[:, 0].min() - 1, X_pca[:, 0].max() + 1]
                yy_boundary = [X_pca[:, 1].min() - 1, X_pca[:, 1].max() + 1]
                xx, yy = np.meshgrid(
                    np.linspace(xx_boundary[0], xx_boundary[1], 500),
                    np.linspace(yy_boundary[0], yy_boundary[1], 500)
                )
                grid = np.c_[xx.ravel(), yy.ravel()]

                # Compute decision function scores
                z = model_one_class_svm.decision_function(grid)
                z = z.reshape(xx.shape)

                # Prepare levels from the decision function scores
                n_levels = HealthScore_param['n_levels']
                levels = np.linspace(z.min(), 0, n_levels)

                # Map levels to health scores
                low_score = HealthScore_param['low_score']
                high_score = HealthScore_param['high_score']
                health_scores = np.linspace(low_score, high_score, n_levels)

                # Fit Linear Regression to map decision function levels to health scores
                model_health_score = LinearRegression(fit_intercept=True).fit(
                    levels[:, np.newaxis], health_scores
                )

                # Save the models to disk
                models_dir = 'models'  # Directory to save models
                # os.makedirs(models_dir, exist_ok=True)
                models_dir = MODELS_DIR
                pca_filename = os.path.join(models_dir, f'{model_option}_pca_{today_date}.joblib')
                svm_filename = os.path.join(models_dir, f'{model_option}_oneclasssvm_{today_date}.joblib')
                linearreg_filename = os.path.join(models_dir, f'{model_option}_linearregression_{today_date}.joblib')
                
                joblib.dump(pca_pipeline, pca_filename)
                joblib.dump(model_one_class_svm, svm_filename)
                joblib.dump(model_health_score, linearreg_filename)

                return jsonify({'message': 'Training completed successfully for health score.'}), 200

            else:
                return jsonify({'message': f'Job type {job_type} not supported with framework {framework}.'}), 400