0
\$\begingroup\$

I've got a working code that transforms data from a MySQL database.

Currently, it's inefficient because it uses about loops, which you'll see at the bottom.

I get an array of objects from a database query. The rows look like this:

[
  {
    userId: 1,
    WorkoutId: 1,
    workoutTitle: 'Hustler',
    workoutDescription: 'Goes to jail a lot',
    exerciseId: 1,
    exerciseTitle: 'Forward Implementation Executive',
    exerciseDescription: 'directional',
    SetId: 1,
    setDate: 2021-07-05T23:00:00.000Z,
    restTime: 60,
    reps: 12,
    duration: 0,
    weight: 10
  },
DUPLICATE for more^^^^
]

The desired output looks like:

[
    {
        "date": "5-Jul",
        "reps": "up",
        "duration": "same",
        "weight": "up",
        "setDetails": [
            {
                "weight": 10,
                "reps": 12,
                "duration": 0
            }
        ]
    }
]

You'll notice some of the queried data is omitted from the final result; you can assume it's not needed/relevant to the question.

The objective is to:

  • Group the data by the date property.
  • Do comparisons between the weight, reps, duration properties that are grouped. (objects within setDetails)
  • Append the comparison result to the grouped object. (GROUPED BY DATE)

Current code:

async function service(provider, token, exerciseId) {
    // Some validation
 
    const res = await GetTableAnalyticsTwo(id, exerciseId);
    const data = res[0];

    if (data.length < 1) {
        return {message: "We can't provide you with Analytics until you've recorded the workout."}
    }
    
    let analytics = {}
    
    data.map((exercise) => {
        const {setDate, weight, reps, duration} = exercise;
        const date = setDate.toISOString().substring(0, 10);
        const dateExists = analytics[date];
        
        if (dateExists) {
            let arr = analytics[date].setDetails;
            arr.push({
                weight,
                reps,
                duration
            });
        } else if (!dateExists) {
            analytics[date] = {
                setDetails: [{
                    weight,
                    reps,
                    duration
                }]  
            }
        }
    });

    Object.entries(analytics).forEach(([key, values]) => {
        let avgWeight = 0;
        let totalDuration = 0;
        let totalReps = 0;
        let length = values.setDetails.length;
        
        values.setDetails.forEach((sets) => {
            const {weight, reps, duration} = sets;
            avgWeight += weight;
            totalDuration += duration;
            totalReps += reps;

        });
        
        avgWeight /= length;

        analytics[key].avgWeight = avgWeight;
        analytics[key].totalDuration = totalDuration;
        analytics[key].totalReps = totalReps;
    });

    let response = [];

    let prevReps = 0, prevDuration = 0, prevWeight = 0;
    Object.entries(analytics).forEach(([date, exercises]) => {
        const {avgWeight, totalDuration, totalReps, setDetails} = exercises;
        let reps, duration, weight;

        prevReps < totalReps ? reps = "up" : reps = "down";
        prevDuration < totalDuration ? duration = "up" : duration = "down";
        prevWeight < avgWeight ? weight = "up" : weight = "down";

        if (prevReps === totalReps) {
            reps = "same";
        }
        if (prevDuration === totalDuration) {
            duration = "same";
        }
        if (prevWeight === avgWeight) {
            weight = "same";
        }
        
        const setDate = new Date(date);
        const month = toMonthString(date);

        const exercise = {
            date: setDate.getDate() + "-" + month,
            reps,
            duration,
            weight,
            setDetails
        }
        response.push(exercise);
        
        prevReps = totalReps;
        prevDuration = totalDuration;
        prevWeight = avgWeight;
    });
    
    return response;
}
\$\endgroup\$
6
  • \$\begingroup\$ Since you're using MySQL, is there a good reason you can't have the database do the aggregation and comparison? That's what they are good for, after all, and you won't have to transfer quite so much data into JavaScript environment. \$\endgroup\$ Apr 22, 2022 at 12:25
  • 1
    \$\begingroup\$ Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Please check that I haven't misrepresented your code, and correct it if I have. \$\endgroup\$ Apr 22, 2022 at 12:25
  • \$\begingroup\$ @TobySpeight I am not aware of anyway of aggregating or comparing data on MySQL. Would totally solve this issue. Currently I query all the required fields and it joins about 10 tables. Is there a resource you can point me to for examples? \$\endgroup\$
    – Tony
    Apr 22, 2022 at 12:54
  • \$\begingroup\$ Especially when the data is complicated like this. The data needs to grouped properly before comparison will take place. \$\endgroup\$
    – Tony
    Apr 22, 2022 at 13:14
  • 1
    \$\begingroup\$ I looked into it. This would solve the initial part however, I still need the full list of data that is aggregated into setDetails. It's an array of objects that's grouped by date then put into setDetails. JSON_ARRAYAGG() might solve this but still looking into it. \$\endgroup\$
    – Tony
    Apr 24, 2022 at 0:15

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.