frLsMatchGroupDirective.js 6.73 KB
import frLsMatchGroup from '../../../public/views/ng/common/frLsMatchGroup.html';

export default function () {
    return {
        restrict: 'A',
        template: frLsMatchGroup,
        scope: true,
        controller: ['$scope', '$attrs', function ($scope, $attrs) {
            var stagesByParent = $scope.stagesByParent;
            var stagesById = $scope.stagesById;
            var competition = $scope.competition;
            var matchesByStage = $scope.matchesByStage;

            console.time('build');
            (function () {
                var groups = [];
                var matchGroupsIndex = {};

                function walkTree(stage) {
                    // Case: Competition
                    // - Create a match group, indexed by competition (stage) id.
                    // - We don't use the name of competition, we use name of the season for the match group.
                    if (stage.type == 'competition') {
                        matchGroupsIndex[stage.id] = {
                            name: '',
                            url: stage.meta.url,
                            subgroups: [],
                        };

                        groups.push(matchGroupsIndex[stage.id]);
                    }

                    // Case: Season
                    // - Modify the name of the match group by the name of the season.
                    // Note: `season` must always be an immidiate child of `competition`.
                    // Note: This implementation assumes there's only one season per competition.
                    if (stage.type == 'season') {
                        matchGroupsIndex[stage.parent].name = stage.name;
                        matchGroupsIndex[stage.id] = matchGroupsIndex[stage.parent];
                    }

                    // Case: Tournament Proper in normal league type.
                    // - Make it a subgroup of main group.
                    // - Don't set name of the subgroup.
                    if (stage.type == 'stage' && stage.parent && stagesById[stage.parent].type == 'season' && !stageHasManyChildren(stage.parent) && !stageHasChildren(stage.id)) {
                        matchGroupsIndex[stage.parent].subgroups.push({
                            matches: matchesByStage[stage.id],
                        });
                    }

                    // Case: A stage that is a single immidiate child of a season and a parent to other stages.
                    // - Change the name of the match group to include the name of this stage.
                    if (stage.type == 'stage' && stagesById[stage.parent].type == 'season' && !stageHasManyChildren(stage.parent) && stageHasChildren(stage.id)) {
                        matchGroupsIndex[stage.parent].name += ' - ' + stage.name;
                        matchGroupsIndex[stage.id] = {
                            name: '',
                        };
                    }

                    // Case: A stage that is one of multiple immidiate children of a season and a parent to other stages.
                    // - Index this stage
                    if (stage.type == 'stage' && stagesById[stage.parent].type == 'season' && stageHasManyChildren(stage.parent) && stageHasChildren(stage.id)) {
                        matchGroupsIndex[stage.id] = {
                            name: stage.name,
                        };
                    }

                    // Case:  A stage that is a child of another stage and is a parent to other stages.
                    // - Index this stage.
                    // - Concat the name with the parent.
                    if (stage.type == 'stage' && stagesById[stage.parent].type != 'season' && stageHasChildren(stage.id)) {
                        matchGroupsIndex[stage.id] = {
                            name: matchGroupsIndex[stage.parent] && matchGroupsIndex[stage.parent].name ? matchGroupsIndex[stage.parent].name + ' - ' + stage.name : stage.name,
                        };
                    }

                    // Case: A leaf stage that is a child of another stage and is not a parent to any stages. Also not a group.
                    // - Add the stage as a subgroup to the main group.
                    // - The name of the subgroup is a tree of stages before it, that are not in main group, plus it's own name.
                    if (stage.type == 'stage' && stagesById[stage.parent].type != 'season' && !stageHasChildren(stage.id)) {
                        groups[0].subgroups.push({
                            name: matchGroupsIndex[stage.parent].name ? matchGroupsIndex[stage.parent].name + ' - ' + stage.name : stage.name,
                            matches: matchesByStage[stage.id],
                        });
                    }

                    // Case: A stage that is a group stage, ie has children that are groups.
                    // - Concat the name with the parent.
                    // - Add all matches that bellong to the groups.
                    if (stageIsGroupStage(stage.id)) {
                        groups[0].subgroups.push({
                            name: stageHasManyChildren(stage.parent) ?
                                (matchGroupsIndex[stage.parent].name ? matchGroupsIndex[stage.parent].name + ' - ' + stage.name : stage.name) : '',
                            matches: _(stagesByParent[stage.id]).reduce(function (matches, stage) {
                                [].push.apply(matches, matchesByStage[stage.id]);
                                return matches;
                            }, []),
                        });
                    }

                    // Case: Group
                    // - Precalculate group name and save it
                    if (stage.type == 'group' && stage.name) {
                        stage.groupName = stage.name.replace('Group ', '');
                    }

                    // Keep walking.
                    _(stagesByParent[stage.id]).each(walkTree);
                }

                function stageHasChildren(id) {
                    return stagesByParent[id] && stagesByParent[id].length > 0;
                }

                function stageHasManyChildren(id) {
                    return stagesByParent[id] && stagesByParent[id].length > 1;
                }

                function stageIsGroupStage(id) {
                    return stagesByParent[id] && stagesByParent[id][0].type == 'group';
                }

                walkTree(competition);

                $scope.group = _(groups).uniq()[0];

                _($scope.group.subgroups).each(function (group) {
                    group.matches = _(group.matches).sortBy(function (match) {
                        return match.datetime;
                    });
                });
            }());
            console.timeEnd('build');
        }],
    };
}