Expected unqualified-id at end of input

I Keep getting this code

src/main.cpp:95:1: error: expected ‘}’ at end of input
}
^
In file included from src/main.cpp:19:
src/Bounce.h:25:1: note: to match this ‘{’
{
^
src/main.cpp:95:1: error: expected unqualified-id at end of input
}
^

The code im writing goes as:

void loop() 
{
  bool bLED= 0; 
  double fps = 0;

  BouncingBallEffect balls(NUM_LEDS, 1);

  while (true)
  {
    bLED = !bLED;
    digitalWrite(LED_BUILTIN, bLED);

    double dStart = millis() / 1000.0;                                    //display frame rate and calc how long it takes

    // Draw LED here

    balls.Draw();

    for (int i = 9; i< NUM_LEDS; i ++)                                  // WARNING Be sure to LIMIT POWER
      g_LEDS[i] = CRGB::White;

    //Handle OLED Drawing

    uint32_t milliwatts = calculate_unscaled_power_mW(g_LEDs, NUM_LEDS);  // hOW MUCCH POER WE PULLING

    static unsigned long msLastUpdate = millis();
    if (millis() - msLastUpdate > 100)
    {
      g_OLED.clearBuffer();
      g_OLED.setCursor(0, g_lineHeight);
      g_OLED.printf("FPS : %.1lf", fps);
      g_OLED.setCursor(0, g_lineHeight * 2);
      g_OLED.printf("Power; %u mW", milliwatts);
      g_OLED.sendBuffer();        msLastUpdate = millis();
    }

    FastLED.show(g_Brightness);

    double dEnd = millis() / 1000.0;
    fps = FramePerSecond(dEnd - dStart);
  }
}

The braces in the shown code seem to be balanced correctly. The problem is either in the not-shown part of src/main.cpp or in src/Bounce.h.

Here Is the whole code

#include <Arduino.h>      //Arduino Framework
#include <U8g2lib.h>      // For text on OLED
#define FASTLED_INTERNAL  // Surpress build banner
#include <FastLED.h>      // FastLED Lib

#define OLED_CLOCK 15     //Pins For the OLED Display
#define OLED_DATA 4
#define OLED_RESET 16

#define NUM_LEDS 172      //FastLED definitions
#define LED_PIN 5

CRGB g_LEDs[NUM_LEDS] = {0};    //Frame buffer for FastLED

U8G2_SSD1306_128X64_NONAME_F_HW_I2C g_OLED(U8G2_R2, OLED_RESET, OLED_CLOCK, OLED_DATA);
int g_lineHeight = 0;
int g_Brightness = 255;         // 0-255 brightness scale

#include "Bounce.h"

// Frames Per Second
//
//Tracks a weigth average in order to smooth out the values that is given. Computes the FPS as the simple reciprocal
// of the amount of time taken specified by the caller. So 1/3 of a second is 3fps, and it
// will take 10 frames or so  to stablize that value.

 double FramePerSecond(double seconds)
{
  static double framesPerSecond;
  framesPerSecond = (framesPerSecond * 0.9) + (1.0 / seconds * 0.1);
  return framesPerSecond;
}

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(115200);
  while (!Serial) { }
  Serial.println("ESP32 Startup");
  
  g_OLED.begin();
  g_OLED.clear();
  g_OLED.setFont(u8g2_font_profont15_tf);
  g_lineHeight = g_OLED.getFontAscent() - g_OLED.getFontDescent();      //Descent is a negative number so we add it to the total

  FastLED.addLeds<WS2812B, LED_PIN, GRB>(g_LEDs, NUM_LEDS);             //Add our LED strip to the FastLED Library
  FastLED.setBrightness(255);

  FastLED.setMaxPowerInMilliWatts(900);
}

void loop() 
{
  bool bLED= 0; 
  double fps = 0;

  BouncingBallEffect balls(NUM_LEDS, 1);

  while (true)
  {
    bLED = !bLED;
    digitalWrite(LED_BUILTIN, bLED);

    double dStart = millis() / 1000.0;                                    //display frame rate and calc how long it takes

    // Draw LED here

    balls.Draw();

    //Handle OLED Drawing

    uint32_t milliwatts = calculate_unscaled_power_mW(g_LEDs, NUM_LEDS);  // hOW MUCCH POER WE PULLING

    static unsigned long msLastUpdate = millis();
    if (millis() - msLastUpdate > 100)
    {
      g_OLED.clearBuffer();
      g_OLED.setCursor(0, g_lineHeight);
      g_OLED.printf("FPS : %.1lf", fps);
      g_OLED.setCursor(0, g_lineHeight * 2);
      g_OLED.printf("Power; %u mW", milliwatts);
      g_OLED.sendBuffer(); msLastUpdate = millis();
    }

    FastLED.show(g_Brightness);

    double dEnd = millis() / 1000.0;
    fps = FramePerSecond(dEnd - dStart);
  }
}

And what’s in this file?

#include <sys/time.h>               //for time of day

#include <Arduino.h>
#define FastLED_INTERNAL
#include <FastLED.h>

using namespace std;
#include <vector>

extern CRGB g_LEDS[];

#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))   // Count elements in static array

static const CRGB ballColors[] =
{
    CRGB::Green,
    CRGB::Red,
    CRGB::Blue,
    CRGB::Orange,
    CRGB::Indigo

};

class BouncingBallEffect
{
    private:

    double InitialBallSpeed(double height) const
    {
        return sqrt(-2 * Gravity * height);     // Because math
    }
    size_t _cLength;
    size_t _cBalls;
    byte   _fadeRate;
    bool   _bMirrored;

    const double Gravity = -9.81;                // Because Physic
    const double StartHeight =1;                // Drop Balls from Max height initiatally
    const double ImpactVelocity = InitialBallSpeed(StartHeight);
    const double SpeedKnob = 4.0;               // Higher value will show effect

    vector<double> ClockTimeAtLastBounce, Height, BallSpeed, Dampening;
    vector<CRGB>    Colors;

    static double Time()
    {
        timeval tv = { 0 };
        gettimeofday(&tv, nullptr);
        return (double)(tv.tv_usec / 1000000.0 + (double) tv.tv_sec);
    }

    public:
    
    //BouncingBallEffect
    //
    // CAller specs strip length, number of balls, persistence level (255 is lest), and whether the 
    // balls should be draw mirrored from each side

    BouncingBallEffect(size_t cLength, size_t ballCount = 3, byte fade = 0, bool bMirrored = false)
        :_cLength (cLength - 1),
         _cBalls(ballCount),
         _fadeRate(fade),
         _bMirrored(bMirrored),
         ClockTimeAtLastBounce(ballCount),
         Height(ballCount),
         BallSpeed(ballCount),
         Dampening(ballCount),
         Colors(ballCount)
    {
        for (size_t i = 0; i < ballCount; i++)
        {
            Height[i]            =StartHeight;                   //Current ball height
            ClockTimeAtLastBounce[i] =Time();
            Dampening[i]         =0.90 - i / pow(_cBalls, 2);    //Bounciness of this ball
            BallSpeed[i]         = InitialBallSpeed(Height[i]);   // Dont dampin initial launch
            Colors[i]            = ballColors[ i % ARRAYSIZE(ballColors) ];
        }
    }

    // Draw
    //
    // Draw each of the balls. When any ball settles with to little energy, it is " kicked" to restart it

    virtual void Draw()
    {
        if (_fadeRate != 0)
        {
            for(size_t i = 0; i < _cLength; i++)
            g_LEDs[i].fadeToBlackBy(_fadeRate);
        }
        else
            FastLED.clear();
        
    // Draw each of the balls

    for (size_t i = 0; i< _cBalls; i++)
    {
        double TimeSinceLastBounce = (Time()- ClockTimeAtLastBounce[i]) / SpeedKnob;

        //Use standard constant accelerationfuction -
        Height[i] = .05 * Gravity* pow(TimeSinceLastBounce, 2.0); BallSpeed[i] * TimeSinceLastBounce;

        // Balls hits ground - bounce
        if (Height[i] < 0)
        {
            Height[i] = 0;
            BallSpeed[i] = Dampening[i] * BallSpeed[i];
            ClockTimeAtLastBounce[i] = Time();
            
            if (BallSpeed[i] < 0.01)
                BallSpeed[i] = InitialBallSpeed(StartHeight) * Dampening[i];
        }

        size_t position = (size_t)(Height[i] * (_cLength - 1) / StartHeight);

        g_LEDs [position] = Colors[i];
        g_LEDs [ position=1] = Colors[i];

        if (_bMirrored)
        {
             g_LEDs [_cLength - 1 - position] = Colors[i];
             g_LEDs [_cLength - position]    = Colors[i];
        }

        delay(20);
    
    }    
};

This function is not closed correctly. First of all the indentation is wrong, eveything after the for loop is one level to deep, second of all the function is not closed with a } properly. The final }; closes the class.

So just modify the code starting at the draw function to

    virtual void Draw()
    {
        if (_fadeRate != 0)
        {
            for(size_t i = 0; i < _cLength; i++)
            g_LEDs[i].fadeToBlackBy(_fadeRate);
        }
        else
            FastLED.clear();
        
		// Draw each of the balls
		for (size_t i = 0; i< _cBalls; i++)
		{
			double TimeSinceLastBounce = (Time()- ClockTimeAtLastBounce[i]) / SpeedKnob;

			//Use standard constant accelerationfuction -
			Height[i] = .05 * Gravity* pow(TimeSinceLastBounce, 2.0); BallSpeed[i] * TimeSinceLastBounce;

			// Balls hits ground - bounce
			if (Height[i] < 0)
			{
				Height[i] = 0;
				BallSpeed[i] = Dampening[i] * BallSpeed[i];
				ClockTimeAtLastBounce[i] = Time();
				
				if (BallSpeed[i] < 0.01)
					BallSpeed[i] = InitialBallSpeed(StartHeight) * Dampening[i];
			}

			size_t position = (size_t)(Height[i] * (_cLength - 1) / StartHeight);

			g_LEDs [position] = Colors[i];
			g_LEDs [ position=1] = Colors[i];

			if (_bMirrored)
			{
				 g_LEDs [_cLength - 1 - position] = Colors[i];
				 g_LEDs [_cLength - position]    = Colors[i];
			}

			delay(20);
		}
    }    
};