DEV Community

Cover image for If our tables could predict the future?
Vigneshwaralingam
Vigneshwaralingam

Posted on

If our tables could predict the future?

I recently attended an webinar hosted by Syncfusion that opened my eyes to the power of integrating AI into standard UI components. As a developer, we are used to displaying dynamic data in tables.But what if our tables could predict the future?

In this post, I’ll share how I built a "Predictive Student Grade Tracker" using the Syncfusion React Data Grid and Azure OpenAI.

The Use Case: Imagine a college dashboard where a professor sees a list of students with their GPAs for Year 1, Year 2, and Year 3. Instead of manually predict thier future marks, we want the application to automatically predict the Year 4 CGPA based on their past performance.


import { loadCultureFiles } from '../common/culture-loader';

import { Grid, Toolbar, Page, QueryCellInfoEventArgs } from '@syncfusion/ej2-grids';
import { Button } from '@syncfusion/ej2/buttons';

import { predictiveData, predictive } from './data-source';

/**
 * Predictive Data Entry
 */


    loadCultureFiles();
    Grid.Inject(Page, Toolbar);

    let grid: Grid = new Grid({
        dataSource: predictiveData,
        toolbar: [{ template: `<button id='calculate_Grade'>Calculate Grade</button>` }],
        queryCellInfo: CustomizeCell,
        columns: [
            { field: 'StudentID', isPrimaryKey: true, headerText: 'Student ID', textAlign: 'Right', width: 100 },
            { field: 'StudentName', headerText: 'Student Name', width: 100 },
            { field: 'FirstYearGPA', textAlign: 'Center', headerText: 'First Year GPA', width: 100 },
            { field: 'SecondYearGPA', headerText: 'Second Year GPA', headerTextAlign: 'Center', textAlign: 'Center', width: 100 },
            { field: 'ThirdYearGPA', headerText: 'Third Year GPA', headerTextAlign: 'Center', textAlign: 'Center', width: 100 },
            { field: 'FinalYearGPA', headerText: 'Final Year GPA', visible: false, headerTextAlign: 'Center', textAlign: 'Center', width: 100 },
            { field: 'TotalGPA', headerText: 'Total GPA', visible: false, headerTextAlign: 'Center', textAlign: 'Center', width: 100 },
            { field: 'TotalGrade', headerText: 'Total Grade', visible: false, headerTextAlign: 'Center', textAlign: 'Center', width: 100 },
        ],
        enableHover: false,
        created: created
    });
    grid.appendTo('#Grid');

    function created() {
        let button = document.getElementById('calculate_Grade') as HTMLButtonElement;
        button.onclick = CalculateGrade;
        new Button({ isPrimary: true }, '#calculate_Grade');
    }

    function CalculateGrade() {
        grid.showSpinner();
        ExecutePrompt();
    }

    function delay(ms: number) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    }

    function ExecutePrompt() {
        const prompt: string = 'Final year GPA column should updated based on GPA of FirstYearGPA, SecondYearGPA and ThirdYearGPA columns. Total GPA should update based on average of all years GPA. Total Grade update based on total GPA. Updated the grade based on following details, 0 - 2.5 = F, 2.6 - 2.9 = C, 3.0 - 3.4 = B, 3.5 - 3.9 = B+, 4.0 - 4.4 = A, 4.5 - 5 = A+. average value decimal should not exceed 1 digit.';
        const gridReportJson: string = JSON.stringify(grid.dataSource);
        const userInput: string = generatePrompt(gridReportJson, prompt);
        let aiOutput: any = (window as any).getAzureChatAIRequest({ messages: [{ role: 'user', content: userInput }] });
        aiOutput.then((result: any) => {
            result = result.replace('```

json', '').replace('

```', '');
            const generatedData: predictive[] = JSON.parse(result);
            grid.hideSpinner();
            if (generatedData.length) {
                grid.showColumns(['Final Year GPA', 'Total GPA', 'Total Grade']);
                updateRows(generatedData);
            }
        });
    }

    async function updateRows(generatedData: predictive[]) {
        await delay(300);
        for (let i: number = 0; i < generatedData.length; i++) {
            const item = generatedData[i];
            grid.setRowData(item.StudentID, item);
            await delay(300);
        }
    }

    function CustomizeCell(args: QueryCellInfoEventArgs) {
        if (args.column!.field === 'FinalYearGPA' || args.column!.field === 'TotalGPA') {
            if ((args.data as predictive).FinalYearGPA! > 0) {
                args.cell!.classList.add('e-PredictiveColumn');
            }
            else if ((args.data as predictive).TotalGPA! > 0) {
                args.cell!.classList.add('e-PredictiveColumn');
            }
        }
        if (args.column!.field === 'TotalGrade') {
            if ((args.data as predictive).TotalGPA! <= 2.5) {
                args.cell!.classList.add('e-inactivecolor');
            }
            else if ((args.data as predictive).TotalGPA! >= 4.5) {
                args.cell!.classList.add('e-activecolor');
            }
            else if ((args.data as predictive).TotalGPA! > 0) {
                args.cell!.classList.add('e-PredictiveColumn');
            }
        }
    }

    function generatePrompt(data: string, userInput: string): string {
        return `Given the following datasource are bounded in the Grid table\n\n${data}.\n Return the newly prepared datasource based on following user query:  ${userInput}\n\nGenerate an output in JSON format only and Should not include any additional information or contents in response`;
    }    

}
Enter fullscreen mode Exit fullscreen mode
  1. 1. First, the code creates a standard Syncfusion Data Grid with columns for:Student ID, Name 1st, 2nd, and 3rd Year GPA 2.Inside the created() function, it adds a button called "Calculate Grade" to the toolbar. 3.When a user clicks this button, it triggers the CalculateGrade() function. 4.ExecutePrompt(): here we tell the prompt and give the datasource to predict.

It takes the current rows from the grid (grid.dataSource) and converts them into a text format (JSON).

It sends both the Data and the Prompt to Azure OpenAI (getAzureChatAIRequest).
5.Once the AI finishes thinking and send the data

The final output is a dynamic data, the 4th column is generated entirely by AI.

github link:-https://github.com/syncfusion/smart-ai-samples/tree/master/typescript

demo:[]-https://ej2.syncfusion.com/demos/#/bootstrap5/ai-grid/predictive-entry.html

Top comments (0)