
/* Generated by Interface Builder */

#import "Car_main.h"
#import "Engine.h"
#import "DataView.h"
#import "defs.h"
#import "appkit/nextstd.h"
#import "Transmission.h"
#import "DataView.h"
#import "Cycle.h"
#import "GasTank.h"

@implementation Engine

- init
{
    [super init];
    engine = self;
    return self;
}

- read:(NXTypedStream *)stream
{
    [super read:stream];
    NXReadTypes(stream,"fffff",&efficiency,&mass,&redline,&stallSpeed,&startLag);
    NXReadArray(stream,"f",6,coefficients);
    return self;
}

- write:(NXTypedStream *)stream
{
    [super write:stream];
    NXWriteTypes(stream,"fffff",&efficiency,&mass,&redline,&stallSpeed,&startLag);
    NXWriteArray(stream,"f",6,coefficients);
    return self;
}

- (float *)coefficients
{
    return coefficients;
}

- setCoefficients:(float *)theCoefficients
{
int i;

    for ( i = 0 ; i < 6 ; i++ )
        coefficients[i] = theCoefficients[i];
    return self;
}

- (float)efficiency
{
    return efficiency;
}

- setEfficiency:(float)aNumber
{
    efficiency = aNumber;
    return self;
}
 
- (float)mass
{
    return mass;
}

- setMass:(float)aNumber
{
    mass = aNumber;
    return self;
}
 
- (float)redline
{
    return redline;
}

- setRedline:(float)aNumber
{
    redline = aNumber;
    return self;
}

- (float)stallSpeed
{
    return stallSpeed;
}

- setStallSpeed:(float)aNumber
{
    stallSpeed = aNumber;
    return self;
}

- (float)startLag
{
    return startLag;
}

- setStartLag:(float)aNumber
{
    startLag = aNumber;
    return self;
}

/******************************************************************************************************************************
 *    This is the part that is called during the simulation.  Notice that the engine will deliver as much stopping power as   *
 *    needed.                                                                                                                 *
 ******************************************************************************************************************************/
- powerRequired:(float)power
{
float angVelocity;
float torqueRequired;
float torqueAvailable;
float energyRequired;

    angVelocity = [transmission inputSpeed];
    if ( angVelocity != 0 )
       torqueRequired = power / angVelocity;
    else if ( power > 0 )
       torqueRequired = 999999;
    else if ( power < 0 )
       torqueRequired = -999999;
    else if ( power == 0 )
       torqueRequired = 0;
    torqueAvailable = evaluatePolynomial(coefficients,6,angVelocity * 60 / (2 * PI)); // Remember the map is in rpm

    if ( torqueRequired >= 0 )						// Here is where we actually pass the power on.
        [transmission engineInput:MIN(torqueAvailable,torqueRequired)];	// Make sure we don't give more power than is needed.
    else
        [transmission engineInput:torqueRequired];			// The car can have all the negative power it wants.

/******************************************************************************************************************************
 *    Here's where we update the gas tank.  There are no provisions to stop the simulation if we run out of gas, but the      *
 *    final gas level will turn out negative.  This is not nearly as important as the whole battery/charge thing.             *
 ******************************************************************************************************************************/
    if ( torqueRequired > 0 )		// Only draw gas if we require positive power.
        {
        energyRequired = MIN(torqueAvailable,torqueRequired) * angVelocity * [cycle timeStep] / efficiency;
        [gasTank energyRequired:energyRequired];
        }

    return self;
}

@end
