< Summary

Class:ThrottledRegexProfanityFilter
Assembly:ProfanityFiltering
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/ProfanityFiltering/ThrottledRegexProfanityFilter.cs
Covered lines:28
Uncovered lines:3
Coverable lines:31
Total lines:72
Line coverage:90.3% (28 of 31)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ThrottledRegexProfanityFilter(...)0%330100%
Filter()0%8.638078.57%
CheckTimerAndSkipFrame()0%8.744033.33%
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;
 8
 9public class ThrottledRegexProfanityFilter : IProfanityFilter
 10{
 111    private readonly List<Regex> regexSteps = new List<Regex>();
 12
 113    public ThrottledRegexProfanityFilter(IProfanityWordProvider wordProvider, int partitionSize = 1)
 14    {
 115        List<string> explicitWords = wordProvider.GetExplicitWords().ToList();
 116        List<string> nonExplicitWords = wordProvider.GetNonExplicitWords().ToList();
 17
 118        var explicitWordsChunks = ToChunks(explicitWords, partitionSize);
 119        var nonExplicitWordsChunks = ToChunks(nonExplicitWords, partitionSize);
 20
 621        for (int i = 0; i < explicitWordsChunks.Count; i++)
 22        {
 223            var explicitWordsRegex = ToRegex(explicitWordsChunks[i]);
 224            var regex = new Regex(@$"\b({explicitWordsRegex})\b", RegexOptions.IgnoreCase | RegexOptions.Compiled);
 225            regexSteps.Add(regex);
 26        }
 27
 4028        for (int i = 0; i < nonExplicitWordsChunks.Count; i++)
 29        {
 1930            var nonExplicitWordsRegex = ToRegex(nonExplicitWordsChunks[i]);
 1931            var regex = new Regex(@$"\\b|({nonExplicitWordsRegex})", RegexOptions.IgnoreCase | RegexOptions.Compiled);
 1932            regexSteps.Add(regex);
 33        }
 134    }
 35
 36    public async UniTask<string> Filter(string message)
 37    {
 1338        if (string.IsNullOrEmpty(message))
 039            return message;
 40
 1341        var stopwatch = new Stopwatch();
 1342        stopwatch.Start();
 43
 57244        foreach (Regex regexStep in regexSteps)
 45        {
 27346            await CheckTimerAndSkipFrame(stopwatch);
 27647            message = regexStep.Replace(message, match => new StringBuilder().Append('*', match.Value.Length).ToString()
 27348        }
 49
 1350        return message;
 1351    }
 52
 53    private async Task CheckTimerAndSkipFrame(Stopwatch stopwatch)
 54    {
 27355        if (stopwatch.ElapsedMilliseconds > 1)
 56        {
 057            await UniTask.WaitForEndOfFrame();
 058            stopwatch.Restart();
 59        }
 27360    }
 61
 2162    private string ToRegex(IEnumerable<string> words) => string.Join("|", words);
 63
 64    private List<List<T>> ToChunks<T>(List<T> source, int chunkSize)
 65    {
 266        return source
 67               .Select((value, index) => (index, value))
 68               .GroupBy(x => x.index / chunkSize)
 69               .Select(x => x.Select(v => v.value).ToList())
 70               .ToList();
 71    }
 72}