source : ShiftLights.js

'use strict';
/**
 * This widget is a generic implementation of the shift light bar.
 * It shows progressive lights, green, yellow, red as approaching the shift point.
 * It also shows the same lights as you are approaching pit road speed.
 * <p>
 * Example:
 * <p><b>
 * <sra-shift-lights></sra-shift-lights><br />
 * </b>
 * <img src="../widgets/ShiftLights/icon.png" />
 * @ngdoc directive
 * @name sra-shift-lights
 * @param {boolean} sra-pit-speeding If false, does not use the lights for pit road speed. Default is true.
 * @param {milliseconds} data-sra-args-flash-rate The rate to flash when CRITICAL state is reached.
 * @param {boolean} data-sra-args-flash-on-critical Enable or disable the flash on critical. Defaults to true.
 * @author Jeffrey Gilliam
 * @since 1.0
 * @copyright Copyright (C) 2015 - 2024 Jeffrey Gilliam
 * @license Apache License 2.0
 */
define(['SIMRacingApps','css!widgets/ShiftLights/ShiftLights'],
function(SIMRacingApps) {
    var self = {
        name:            "sraShiftLights",
        url:             'ShiftLights',
        template:        'ShiftLights.html',
        defaultWidth:    800,
        defaultHeight:   100,
        defaultInterval: 30   //initialize with the default interval
    };
    self.module = angular.module('SIMRacingApps'); //get the main module
    self.module.directive(self.name,
           ['sraDispatcher', '$filter', '$location', '$interval', '$rootScope',
    function(sraDispatcher,  $filter,   $location,    $interval,   $rootScope) {
        return {
            restrict: 'EA',
            scope: true,
            templateUrl: sraDispatcher.getWidgetUrl(self.url) + '/' + self.template,
            controller: [ '$scope', function($scope) {
                $scope.directiveName   = self.name;
                $scope.defaultWidth    = self.defaultWidth;
                $scope.defaultHeight   = self.defaultHeight;
                $scope.defaultInterval = self.defaultInterval;
                $scope.percentages= [
                                          //These should be from lowest to highest
                                          { value: 0.00, color: 'SIMRacingApps-Widget-ShiftLights-start'  },
                                          { value: 0.10, color: 'SIMRacingApps-Widget-ShiftLights-start'  },
                                          { value: 0.20, color: 'SIMRacingApps-Widget-ShiftLights-start'  },
                                          { value: 0.30, color: 'SIMRacingApps-Widget-ShiftLights-start'  },
                                          { value: 0.40, color: 'SIMRacingApps-Widget-ShiftLights-middle' },
                                          { value: 0.50, color: 'SIMRacingApps-Widget-ShiftLights-middle' },
                                          { value: 0.60, color: 'SIMRacingApps-Widget-ShiftLights-middle' },
                                          { value: 0.70, color: 'SIMRacingApps-Widget-ShiftLights-end'    },
                                          { value: 0.80, color: 'SIMRacingApps-Widget-ShiftLights-end'    },
                                          { value: 0.90, color: 'SIMRacingApps-Widget-ShiftLights-end'    }
                                         ];
                $scope.maxSizePercent  = 0.8; //controls the spacing/size of the lights. 1.0 means no spacing.
                $scope.offColor        = 'SIMRacingApps-Widget-ShiftLights-off';
                $scope.lights          = [];
                $scope.flashRate       = 100;
                $scope.limitRate       = 500;
                $scope.flashOnCritical = true;
                $scope.pitSpeeding     = true;
                $scope.calculateLights = function() {
                    $scope.lights = [];
                    var numberOfLights = $scope.percentages.length;
                    for (var i=0; i < numberOfLights; i++) {
                        var r = Math.min(self.defaultHeight,self.defaultWidth / numberOfLights) / 2;
                        var light = {
                            x:             ((self.defaultWidth / numberOfLights) * i) + ((self.defaultWidth / numberOfLights) / 2),
                            y:             self.defaultHeight / 2,
                            r:             (r * $scope.maxSizePercent),
                            percentage:    $scope.percentages[i],
                            on:            false,
                            className:     $scope.offColor
                        };
                        $scope.lights.push(light);
                    }
                };
                $scope.calculateLights(); //execute this now, just so the array is populated when the SVG element gets added to the DOM.
                $scope.updateColors = function() {
                    var value             = $scope.data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.Value          || 0.0;
                    var state             = $scope.data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.State          || 'OFF';
                    var percent           = ($scope.data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.StatePercent  || 0.0) / 100.0;
                    var speedState        = $scope.data.Car.REFERENCE.Gauge.Speedometer.ValueCurrent.State         || 'OFF';
                    var speedPercent      = ($scope.data.Car.REFERENCE.Gauge.Speedometer.ValueCurrent.StatePercent || 0.0) / 100.0;
                    var excessiveSpeeding = sraDispatcher.State.isWAYOVERLIMIT(speedState);
                    var pitRoadActive     = $scope.data.Car.REFERENCE.Status.Value.indexOf("PIT") >= 0 && $scope.data.Car.REFERENCE.Status.Value != "LEAVINGPITS";
                    var pitLimiter        = $scope.data.Car.REFERENCE.Messages.Value.indexOf(";PITSPEEDLIMITER;") >= 0;
                    //first turn the light on and off based on where the actual value falls
                    for (var i=0; i < $scope.lights.length; i++) {
                        if (pitLimiter) {
                            $scope.lights[i].on = true;
                        }
                        else
                        if ($scope.pitSpeeding
                        &&  pitRoadActive
                        &&  sraDispatcher.State.isAPPROACHINGLIMIT(speedState)
                        &&  speedPercent >= $scope.lights[i].percentage.value
                        ) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink)
                                $scope.lights[i].className = $scope.lights[i].percentage.color;
                        }
                        else
                        if ($scope.pitSpeeding
                        &&  pitRoadActive
                        &&  sraDispatcher.State.isLIMIT(speedState)
                        ) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink) {
                                //do not turn on the last light, shift the percentages up and don't use the first range
                                if (i < ($scope.lights.length-1) && speedPercent >= $scope.lights[i+1].percentage.value)
                                    $scope.lights[i].className = 'SIMRacingApps-Widget-ShiftLights-overlimit';
                                else
                                    $scope.lights[i].className = 'SIMRacingApps-Widget-ShiftLights-limit';
                            }
                        }
                        else
                        if ($scope.pitSpeeding
                        &&  pitRoadActive
                        &&  sraDispatcher.State.isOVERLIMIT(speedState)
                        ) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink)
                                $scope.lights[i].className = 'SIMRacingApps-Widget-ShiftLights-overlimit';
                        }
                        else
                        if ($scope.pitSpeeding
                        &&  pitRoadActive
                        &&  sraDispatcher.State.isWAYOVERLIMIT(speedState)
                        ) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink)
                                $scope.lights[i].className = 'SIMRacingApps-Widget-ShiftLights-overlimit';
                        }
                        else
                        if (sraDispatcher.State.isSHIFTLIGHTS(state) 
                        && percent >= $scope.lights[i].percentage.value
                        ) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink)
                                $scope.lights[i].className = $scope.lights[i].percentage.color;
                        }
                        else
                        if (sraDispatcher.State.isSHIFT(state) 
                        ||  sraDispatcher.State.isSHIFTBLINK(state)
                        ||  sraDispatcher.State.isCRITICAL(state)) {
                            $scope.lights[i].on = true;
                            if (!$scope._blink)
                                $scope.lights[i].className = 'SIMRacingApps-Widget-ShiftLights-end';
                        } 
                        else {
                            $scope.lights[i].on = false;
                            if (!$scope._blink)
                                $scope.lights[i].className = $scope.offColor;
                        }
                    }
                    if ($scope.flashOnCritical
                    && (
                          sraDispatcher.State.isSHIFTBLINK(state) 
                       || sraDispatcher.State.isCRITICAL(state)
                       || ($scope.pitSpeeding && pitRoadActive &&  sraDispatcher.State.isWAYOVERLIMIT(speedState))
                       || pitLimiter
                       )
                    ) {
                        //TODO: Make it blink between critical and warning, self.blinkRate
                        if ($scope._blink == null) {
                            console.log("ShiftLights - Blink Start");
                            $scope._blink = $interval(function() {
                                var currentColor = $scope.lights[0].className;
                                for (var j=0; j < $scope.lights.length; j++) {
                                    if (currentColor != $scope.offColor) {
                                        $scope.lights[j].className  = $scope.offColor;
                                    }
                                    else {
                                        $scope.lights[j].className = $scope.lights[j].on 
                                                                   ? 'SIMRacingApps-Widget-ShiftLights-end' 
                                                                   : $scope.offColor;
                                    }
                                }
                            }, pitLimiter ? $scope.limitRate : $scope.flashRate);
                        }
                    }
                    else {
                        //stop the blinking if we are not in the critical state.
                        if ($scope._blink) {
                            console.log("ShiftLights - Blink Stop");
                            $interval.cancel($scope._blink);
                            $scope._blink = null;
                        }
                    }
                };
            }]
            , link: function($scope,$element,$attrs) {
                $scope.maxSizePercent = sraDispatcher.getTruthy($scope.sraArgsMAXSIZEPERCENT, $attrs.sraArgsMaxSizePercent, $scope.maxSizePercent)  * 1.0;
                $scope.flashRate      = sraDispatcher.getTruthy($scope.sraArgsFLASHRATE, $attrs.sraArgsFlashRate, $scope.flashRate) * 1;
                $scope.flashOnCritical= sraDispatcher.getBoolean($scope.sraArgsFLASHONCRITICAL,$attrs.sraArgsFlashOnCritical,$scope.flashOnCritical,true);
                $scope.pitSpeeding    = sraDispatcher.getBoolean($scope.sraArgsPITSPEEDING, $attrs.sraArgsPitSpeeding, $scope.pitSpeeding);
                $attrs.sraArgsData  = "Car/REFERENCE/Gauge/Tachometer/ValueCurrent"
                                    + ";Car/REFERENCE/Gauge/Speedometer/ValueCurrent"
                                    + ";Car/REFERENCE/Status"
                                    + ";Car/REFERENCE/Messages";
                $scope.$watch("data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.Value",         $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.State",         $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Gauge.Tachometer.ValueCurrent.StatePercent",  $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Gauge.Speedometer.ValueCurrent.Value",        $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Gauge.Speedometer.ValueCurrent.State",        $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Gauge.Speedometer.ValueCurrent.StatePercent", $scope.updateColors);
                $scope.$watch("data.Car.REFERENCE.Messages.Value",                              $scope.updateColors);
                $rootScope.$on('sraResize', sraDispatcher.resize($scope,$element,self.defaultWidth,self.defaultHeight));
           /**standard code that should be in every directive **/
                $scope.names        = sraDispatcher.subscribe($scope,$attrs,self.defaultInterval); //register subscriptions and options to the dispatcher
            }
        };
    }]);
    return self;
});