formationsDirCtrl.js 9.19 KB
import './lastname';

angular.module('fr.formationsDirCtrl', ['fr.lastname'])

.factory('formationsDirCtrl', ['$rootScope', '$filter', 'lastname', function ($rootScope, $filter, lastname) {
    return function ($scope) {
        // Goes from 1-11.
        var posLevels;

        this.init = function () {
            posLevels = {
                home: [],
                away: [],
            };

            $rootScope.isShowLineup = $scope.isShowLineup = _($scope.lineup).where({ type: 'Starter' }).length >= 22;

            this.calcSubbedIn();
            this.calcFormations();

            $scope.formation.homeAsText = $filter('formation')($scope.formation.home);
            $scope.formation.awayAsText = $filter('formation')($scope.formation.away);

            $scope.homeCoach = _($scope.lineup).findWhere({ type: 'Coach', side: 'home' });
            $scope.awayCoach = _($scope.lineup).findWhere({ type: 'Coach', side: 'away' });

            $scope.startingLineup = _($scope.lineup).where({ type: 'Starter' });
            $scope.homeStartingLineup = _($scope.lineup).where({ type: 'Starter', side: 'home' });
            $scope.awayStartingLineup = _($scope.lineup).where({ type: 'Starter', side: 'away' });

            $scope.homeSubedIn = _(
                _($scope.lineup).where({ type: 'Substitute', side: 'home' })
            ).filter($scope.usedSubs);

            $scope.awaySubedIn = _(
                _($scope.lineup).where({ type: 'Substitute', side: 'away' })
            ).filter($scope.usedSubs);

            $scope.homeUnusedSubs = _(
                _($scope.lineup).where({ type: 'Substitute', side: 'home' })
            ).filter($rootScope.not($scope.usedSubs));

            $scope.awayUnusedSubs = _(
                _($scope.lineup).where({ type: 'Substitute', side: 'away' })
            ).filter($rootScope.not($scope.usedSubs));

            _($scope.lineup).each(function (person) {
                posLevels[person.side][Math.floor(person.enetPos / 10)] = true;
                person.styling = this.place(person);
                person.shortName = getShortName(person.participant.name);
                person.incidents = _($scope.incidents)
                .filter($scope.incidentsByPlayerFilter(person))
                .reduce(function (incidents, incident) {
                    let incidentGroup;
                    if (/^(g|eg|p|ep)$/.test(incident.code.id)) {
                        incidentGroup = 'g';
                    } else if (/^(pm|epm|psm)$/.test(incident.code.id)) {
                        incidentGroup = 'pm';
                    } else {
                        incidentGroup = incident.code.id;
                    }

                    incidents[incidentGroup] = incidents[incidentGroup] || [];

                    incidents[incidentGroup].push(incident);

                    return incidents;
                }, {});
            }, this);
        };

        // Re-run calculations when formation update requested.
        $scope.$on('formation-update', _.bind(function () {
            this.init();
        }, this));

        /**
         * Public Methods.
         */

        this.calcSubbedIn = function () {
            $scope.subbedIn = _.reduce($scope.incidents, function (memo, incident) {
                if (incident.code.id == 'si') {
                    memo.push(incident);
                }
                return memo;
            }, []);
        };

        this.calcFormations = function () {
            $scope.formation = {
                home: $scope.calcFormation(_.where($scope.lineup, {type: 'Starter', side: 'home'})),
                away: $scope.calcFormation(_.where($scope.lineup, {type: 'Starter', side: 'away'})),
            };
        };

        this.getPlayerCoordinates = function (player) {
            /**
             * Normalize Enetpulse positioning for better visualizations.
             */
            if ($scope.formation[player.side][0] == 3 && player.enetPos == 34) {
                player.enetPos = 35;
            }

            if (player.enetPos === 94) {
                player.enetPos = 93;
            }

            if (player.enetPos === 96) {
                player.enetPos = 97;
            }

            /**
             * Calculate field position represented by Enetpulse positioning system.
             * We also normalize some values for better visualizations.
             */
            var row = Math.floor(player.enetPos / 10);
            var col = player.enetPos % 10;

            if (row === 5 || row === 6) {
                row = 5.5;
            }

            if (row === 7 && !$scope.formation[player.side][3]) {
                row = 6.5;
            } else if (row === 7 && $scope.formation[player.side][3]) {
                row = 6;
            }

            if (row === 9) {
                row = 8.5;
            }

            if (row === 10 && posLevels[player.side][8]) {
                row = 11;
            }

            if (row === 11) {
                row = 10.6;
            }

            return {
                row: row,
                col: col,
            };
        };

        this.place = function (player) {
            var coordinates = this.getPlayerCoordinates(player),
                style = {},
                offset,
                side,
                col,
                row,
                spacingFactor = 4.12;

            if (!$scope.isVertical) {
                col = (player.side == 'home') ? Math.abs(coordinates.col - 10) : coordinates.col;
                side = (player.side == 'home') ? 'left' : 'right';

                switch (player.enetPos) {
                    case 11:
                        style[side] = '0';
                        style.top = '39.5%';
                        break;
                    case undefined:
                        break;
                    default:
                        style[side] = (coordinates.row - 1) * spacingFactor + '%';
                        style.top = Math.max(Math.min(col * 11 - 15.5, 80), 0) + '%';
                        break;
                }
            } else {
                offset = (player.side == 'home') ? 2.5 : 48.5;
                side = (player.side == 'home') ? 'top' : 'bottom';
                col = (player.side == 'home') ? coordinates.col : Math.abs(coordinates.col - 10);
                row = (player.side == 'home') ? coordinates.row : Math.abs(coordinates.row - 12);

                switch (player.enetPos) {
                    case 11:
                        style[side] = 0;
                        style.left = 0;
                        break;
                    case undefined:
                        break;
                    default:
                        style.top = (row - 1) * spacingFactor + offset + '%';
                        style.left = Math.max(Math.min(col * 11 - 15, 80), 0) + '%';
                        break;
                }
            }

            return style;
        };

        /**
         * Scope Methods.
         */

        $scope.incidentsByPlayerFilter = function (player) {
            return function (incident) {
                if (player.participant.enetId) {
                    return incident.player.enetID == player.participant.enetId;
                }
                return incident.player.name == player.participant.name;
            };
        };

        $scope.calcFormation = function (lineup) {
            var formation = [0, 0, 0, 0, 0];

            _.each(lineup, function (lineup) {
                var level = Math.floor(lineup.enetPos / 10);
                if (level >= 2 && level <= 4) formation[0]++;
                else if (level >= 5 && level <= 6) formation[1]++;
                else if (level >= 7 && level <= 8) formation[2]++;
                else if (level == 9) formation[3]++;
                else if (level >= 10 && level <= 11) formation[4]++;
            });

            return formation;
        };

        $scope.usedSubs = function (player) {
            return _($scope.subbedIn).some($scope.incidentsByPlayerFilter(player));
        };

        $scope.name = function (player) {
            return lastname(player.participant.name || 'Unnamed');
        };

        $scope.reasonUnavailableText = function (reason) {
            switch (reason) {
                case 'injured': return 'Injured';
                case 'injured-doubtful': return 'Doubtful';
                case 'suspended': return 'Suspended';
                case 'banned': return 'Banned';
                case 'int-duty': return 'International Duty';
                case 'not-qual': return 'Ineligible';
                case 'illness': return 'Illness';
                case 'personal-reasons': return 'Personal Reasons';
                case 'fitness': return 'Lack of Fitness';
                case 'coach-decision': return 'Coach Decision';
                case 'other': return 'Unavailable';
                default: return reason;
            }
        };

        /**
         * Returns a shorter version of name if it exceeds defined maximum
         * length.
         *
         * @param {string} name
         *
         * @return {string}
         */
        function getShortName(name) {
            if (name.length > 29) {
                return lastname(name);
            }

            return name;
        }
    };
}]);