Ejemplo n.º 1
0
        /* Function: SegmentMenu
         * Segments the menu into smaller pieces and generates data file names.
         */
        protected void SegmentMenu(MenuEntries.Base.Container container, string dataFileType,
                                   ref StringTable <IDObjects.NumberSet> usedDataFiles)
        {
            // Generate the data file name for this container.

            IDObjects.NumberSet usedDataFileNumbers = usedDataFiles[dataFileType];

            if (usedDataFileNumbers == null)
            {
                usedDataFileNumbers = new IDObjects.NumberSet();
                usedDataFiles.Add(dataFileType, usedDataFileNumbers);
            }

            int dataFileNumber = usedDataFileNumbers.LowestAvailable;

            usedDataFileNumbers.Add(dataFileNumber);

            ContainerExtraData extraData = (ContainerExtraData)container.ExtraData;

            extraData.DataFileName = HTMLBuilder.Menu_DataFileNameOnly(dataFileType, dataFileNumber);


            // The data file has to include all the members in this container no matter what.

            int containerJSONSize = extraData.JSONBeforeMembers.Length + extraData.JSONAfterMembers.Length +
                                    extraData.JSONLengthOfMembers;

            List <MenuEntries.Base.Container> subContainers = null;

            foreach (var member in container.Members)
            {
                if (member is MenuEntries.Base.Container)
                {
                    if (subContainers == null)
                    {
                        subContainers = new List <MenuEntries.Base.Container>();
                    }

                    subContainers.Add((MenuEntries.Base.Container)member);
                }
            }


            // Now start including the contents of subcontainers until we reach the size limit.  We're going breadth-first instead of
            // depth first.

            List <MenuEntries.Base.Container> nextSubContainers = null;

            for (;;)
            {
                if (subContainers == null || subContainers.Count == 0)
                {
                    if (nextSubContainers == null || nextSubContainers.Count == 0)
                    {
                        break;
                    }
                    else
                    {
                        subContainers     = nextSubContainers;
                        nextSubContainers = null;
                    }
                }

                // Add subcontainers to the file in the order from smallest to largest.  This prevents one very large container early
                // in the list from causing all the other ones to be broken out into separate files.
                // DEPENDENCY: ContainerExtraData.JSONLengthOfMembers must cache its value for this algorithm to be efficient.

                int smallestSubContainerIndex = 0;
                int smallestSubContainerSize  = (subContainers[0].ExtraData as ContainerExtraData).JSONLengthOfMembers;

                for (int i = 1; i < subContainers.Count; i++)
                {
                    if ((subContainers[i].ExtraData as ContainerExtraData).JSONLengthOfMembers < smallestSubContainerSize)
                    {
                        smallestSubContainerIndex = i;
                        smallestSubContainerSize  = (subContainers[i].ExtraData as ContainerExtraData).JSONLengthOfMembers;
                    }
                }

                containerJSONSize += smallestSubContainerSize;

                if (containerJSONSize > SegmentLength)
                {
                    break;
                }

                foreach (var member in subContainers[smallestSubContainerIndex].Members)
                {
                    if (member is MenuEntries.Base.Container)
                    {
                        if (nextSubContainers == null)
                        {
                            nextSubContainers = new List <MenuEntries.Base.Container>();
                        }

                        nextSubContainers.Add((MenuEntries.Base.Container)member);
                    }
                }

                subContainers.RemoveAt(smallestSubContainerIndex);
            }


            // Now recurse through any remaining subcontainers so they get their own files.

            if (subContainers != null)
            {
                foreach (var subContainer in subContainers)
                {
                    SegmentMenu(subContainer, dataFileType, ref usedDataFiles);
                }
            }

            if (nextSubContainers != null)
            {
                foreach (var subContainer in nextSubContainers)
                {
                    SegmentMenu(subContainer, dataFileType, ref usedDataFiles);
                }
            }
        }