< Summary

Class:DCL.ProfanityFiltering.ThrottledRegexProfanityFilter
Assembly:ProfanityFiltering
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/ProfanityFiltering/ThrottledRegexProfanityFilter.cs
Covered lines:22
Uncovered lines:14
Coverable lines:36
Total lines:91
Line coverage:61.1% (22 of 36)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ThrottledRegexProfanityFilter(...)0%110100%
Dispose()0%110100%
Initialize()0%330100%
Filter()0%72800%
CheckTimerAndSkipFrame()0%20400%
ToRegex(...)0%110100%
ToChunks[T](...)0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/ProfanityFiltering/ThrottledRegexProfanityFilter.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Diagnostics;
 3using System.Linq;
 4using System.Text;
 5using System.Text.RegularExpressions;
 6using System.Threading.Tasks;
 7using Cysharp.Threading.Tasks;
 8using System;
 9
 10namespace DCL.ProfanityFiltering
 11{
 12    public class ThrottledRegexProfanityFilter : IProfanityFilter
 13    {
 14        private readonly IProfanityWordProvider wordProvider;
 15        private readonly int partitionSize;
 10216        private readonly List<Regex> regexSteps = new ();
 17
 18        /// <param name="wordProvider"></param>
 19        /// <param name="partitionSize">Check https://github.com/decentraland/unity-renderer/issues/2201 for more info a
 10220        public ThrottledRegexProfanityFilter(IProfanityWordProvider wordProvider, int partitionSize = 1)
 21        {
 10222            this.wordProvider = wordProvider;
 10223            this.partitionSize = partitionSize;
 10224        }
 25
 26        public void Dispose()
 27        {
 10228            regexSteps.Clear();
 10229        }
 30
 31        public void Initialize()
 32        {
 10233            List<string> explicitWords = wordProvider.GetExplicitWords().ToList();
 10234            List<string> nonExplicitWords = wordProvider.GetNonExplicitWords().ToList();
 35
 10236            var explicitWordsChunks = ToChunks(explicitWords, partitionSize);
 10237            var nonExplicitWordsChunks = ToChunks(nonExplicitWords, partitionSize);
 38
 61239            for (var i = 0; i < explicitWordsChunks.Count; i++)
 40            {
 20441                var explicitWordsRegex = ToRegex(explicitWordsChunks[i]);
 20442                var regex = new Regex(@$"\b({explicitWordsRegex})\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
 20443                regexSteps.Add(regex);
 44            }
 45
 408046            for (var i = 0; i < nonExplicitWordsChunks.Count; i++)
 47            {
 193848                var nonExplicitWordsRegex = ToRegex(nonExplicitWordsChunks[i]);
 193849                var regex = new Regex(@$"\\b|({nonExplicitWordsRegex})", RegexOptions.IgnoreCase | RegexOptions.Compiled
 193850                regexSteps.Add(regex);
 51            }
 10252        }
 53
 54        public async UniTask<string> Filter(string message)
 55        {
 056            if (string.IsNullOrEmpty(message))
 057                return message;
 58
 059            var stopwatch = new Stopwatch();
 060            stopwatch.Start();
 61
 062            foreach (Regex regexStep in regexSteps)
 63            {
 064                await CheckTimerAndSkipFrame(stopwatch);
 065                message = regexStep.Replace(message, match => new StringBuilder().Append('*', match.Value.Length).ToStri
 066            }
 67
 068            return message;
 069        }
 70
 71        private async Task CheckTimerAndSkipFrame(Stopwatch stopwatch)
 72        {
 073            if (stopwatch.ElapsedMilliseconds > 1)
 74            {
 075                await UniTask.WaitForEndOfFrame();
 076                stopwatch.Restart();
 77            }
 078        }
 79
 214280        private string ToRegex(IEnumerable<string> words) => string.Join("|", words);
 81
 82        private List<List<T>> ToChunks<T>(List<T> source, int chunkSize)
 83        {
 20484            return source
 85                  .Select((value, index) => (index, value))
 86                  .GroupBy(x => x.index / chunkSize)
 87                  .Select(x => x.Select(v => v.value).ToList())
 88                  .ToList();
 89        }
 90    }
 91}