예제 #1
0
        /// <summary>
        /// Append the given block at the end of the current block. Pad with no-data if necessary
        /// </summary>
        /// <param name="block"></param>
        public void Append(TracingBlock block)
        {
            if (block == null)
            {
                throw new ArgumentNullException("block");
            }

            if (block.TotalSeconds == 0)
            {
                return;
            }

            if (block.End <= this.End)
            {
                return;
            }

            // Align the blocks HR and UP signals
            this.AlignSignals();
            block.AlignSignals();

            // Preallocate to speed up the append
            this.Capacity = (int)Math.Ceiling((block.End - this.Start).TotalSeconds);

            // Check if block are adjascent
            int gap = (int)(block.Start - this.Start).TotalSeconds - this.TotalSeconds;

            // Fix gap by bridging with NO data
            while (gap > 0)
            {
                this.HRs.Add(TracingBlock.NoData); this.HRs.Add(TracingBlock.NoData); this.HRs.Add(TracingBlock.NoData); this.HRs.Add(TracingBlock.NoData);
                this.UPs.Add(TracingBlock.NoData);
                --gap;
            }

            // Check for overlap
            int overlap = Math.Abs(gap);

            // Too much overlap, just leave NOW
            if ((overlap > 0) && (overlap >= block.TotalSeconds))
            {
                return;
            }

            // Append
            if (overlap > 0)
            {
                this.HRs.AddRange(block.HRs.SkipWhile((x, i) => i < (overlap * 4)));
                this.UPs.AddRange(block.UPs.SkipWhile((x, i) => i < overlap));
            }
            else
            {
                this.HRs.AddRange(block.HRs);
                this.UPs.AddRange(block.UPs);
            }
        }
예제 #2
0
        /// <summary>
        /// Merge blocks
        /// This does not modify the source blocks but create a copy of the blocks
        /// </summary>
        /// <param name="blocks">List of block to merged</param>
        /// <param name="maxBridgeableGap">Maximum duration (in seconds) that can be bridged between 2 blocks</param>
        /// <param name="maxMergedBlockSize">Maximum size of a merged block (if a block is already that big or even bigger, it just won't be merged with anything)</param>
        /// <returns></returns>
        public static List <TracingBlock> Merge(IEnumerable <TracingBlock> blocks, int maxBridgeableGap, int maxMergedBlockSize)
        {
            List <TracingBlock> result = new List <TracingBlock>();

            // Safety first
            if (blocks == null)
            {
                return(result);
            }

            TracingBlock last = null;

            foreach (TracingBlock block in blocks)
            {
                // Skip empty blocks
                if (block.TotalSeconds == 0)
                {
                    continue;
                }

                block.AlignSignals();

                // First block?
                if (last == null)
                {
                    last = new TracingBlock(block);
                    result.Add(last);
                    continue;
                }

                // Check if block are adjascent
                int gap = (int)(block.Start - last.End).TotalSeconds;

                // A gap that's not bridgeable or if the resulting merged block would be too big...
                if ((gap > maxBridgeableGap) || ((block.End - last.Start).TotalSeconds > maxMergedBlockSize))
                {
                    last = new TracingBlock(block);
                    result.Add(last);
                    continue;
                }

                last.Append(block);
            }

            // Optimize memory
            foreach (TracingBlock block in result)
            {
                block.HRs.TrimExcess();
                block.UPs.TrimExcess();
            }

            // Done
            return(result);
        }
예제 #3
0
        /// <summary>
        /// Split a given block in multiple blocks so that each block duration is less than maxBlockSize
        /// </summary>
        /// <param name="maxBlockSize"></param>
        /// <returns></returns>
        public List <TracingBlock> Split(int maxBlockSize)
        {
            // To make sure HRs and UP are properly aligned...
            this.AlignSignals();

            // Security
            System.Diagnostics.Debug.Assert(maxBlockSize > 0);
            maxBlockSize = Math.Max(1, maxBlockSize);

            // All fits in one block?
            var results = new List <TracingBlock>();

            if (this.TotalSeconds <= maxBlockSize)
            {
                results.Add(this);
                return(results);
            }

            // Need to cut!
            var position = 0;
            var duration = this.TotalSeconds;
            var time     = this.Start;

            while (position < duration)
            {
                var block_duration = Math.Min(duration - position, maxBlockSize);
                var block          = new TracingBlock {
                    Start = time, Capacity = block_duration
                };

                for (int i = position; i < position + block_duration; ++i)
                {
                    block.HRs.Add(this.HRs[(i * 4)]);
                    block.HRs.Add(this.HRs[(i * 4) + 1]);
                    block.HRs.Add(this.HRs[(i * 4) + 2]);
                    block.HRs.Add(this.HRs[(i * 4) + 3]);

                    block.UPs.Add(this.UPs[i]);
                }

                // If the block is pure no-data, just skip it...
                if (!block.IsCompleteNotData)
                {
                    results.Add(block);
                }

                position += block_duration;
                time      = time.AddSeconds(block_duration);
            }

            return(results);
        }