Ejemplo n.º 1
0
        public void Find(OSPCResult result, List <CompareResult> compareResult)
        {
            var friends = new Dictionary <Submission, FriendOf>();
            var min_friend_finder_similarity = _cfg.MIN_FRIEND_FINDER_SIMILARITY >= 0
                ? _cfg.MIN_FRIEND_FINDER_SIMILARITY
                : result.POI_Similarity - 0.2;

            min_friend_finder_similarity = Math.Max(min_friend_finder_similarity, _cfg.MIN_SIMILARITY);

            // if result.POI_Similarity is 0, min_friend_finder_similarity may become negative.
            // So every submission is a group and every match is in that group.
            if (min_friend_finder_similarity > 0)
            {
                foreach (var cp in compareResult)
                {
                    ProcessMatch(friends, cp, cp.A, cp.SimilarityB, min_friend_finder_similarity);
                    ProcessMatch(friends, cp, cp.B, cp.SimilarityA, min_friend_finder_similarity);
                }
            }

            result.Friends = friends.Values
                             .Where(i => i.InMatches.Count > 1)
                             .OrderByDescending(i => i.SumSimilarity)
                             .ToList();
        }
Ejemplo n.º 2
0
        public static OSPCResult Create(List <CompareResult> compareResult)
        {
            var result = new OSPCResult();

            result.Results = compareResult
                             .Where(r => r.MatchCount > 0)
                             .OrderByDescending(r => Math.Max(r.SimilarityA, r.SimilarityB))
                             .ThenByDescending(r => Math.Min(r.SimilarityA, r.SimilarityB))
                             .Select((item, idx) =>
            {
                item.Seal(idx);
                return(item);
            })
                             .ToList();

            double[] lst = result.Results.SelectMany(i => new[] { i.SimilarityA, i.SimilarityB }).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                var poiidx = lst.CalcDerv2().MaxIndex();
                result.AVG_Similarity = lst.Average();
                result.POI_Similarity = poiidx >= 0 ? lst[poiidx] : 0;
            }

            lst = result.Results.Select(i => (double)i.TokenCount).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                var poiidx = lst.CalcDerv2().MaxIndex();
                result.AVG_TokenCount = lst.Average();
                result.POI_TokenCount = poiidx >= 0 ? lst[poiidx] : 0;
            }

            lst = result.Results.Select(i => (double)i.TokenCount / (double)i.MatchCount).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                var poiidx = lst.CalcDerv2().MaxIndex();
                result.AVG_TokenPerMatch = lst.Average();
                result.POI_TokenPerMatch = poiidx >= 0 ? lst[poiidx] : 0;
            }
            return(result);
        }
Ejemplo n.º 3
0
        public static OSPCResult Create(List<CompareResult> compareResult)
        {
            var result = new OSPCResult();
            result.Results = compareResult
                .Where(r => r.MatchCount > 0)
                .OrderByDescending(r => Math.Max(r.SimilarityA, r.SimilarityB))
                .ThenByDescending(r => Math.Min(r.SimilarityA, r.SimilarityB))
                .Select((item, idx) =>
                {
                    item.Seal(idx);
                    return item;
                })
                .ToList();

            double[] lst = result.Results.SelectMany(i => new[] { i.SimilarityA, i.SimilarityB }).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                result.AVG_Similarity = lst.Average();
                result.POI_Similarity = lst[lst.CalcDerv2().MaxIndex()];
            }

            lst = result.Results.Select(i => (double)i.TokenCount).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                result.AVG_TokenCount = lst.Average();
                result.POI_TokenCount = lst[lst.CalcDerv2().MaxIndex()];
            }

            lst = result.Results.Select(i => (double)i.TokenCount / (double)i.MatchCount).OrderBy(i => i).ToArray();
            if (lst.Length > 0)
            {
                result.AVG_TokenPerMatch = lst.Average();
                result.POI_TokenPerMatch = lst[lst.CalcDerv2().MaxIndex()];

            }
            return result;
        }
Ejemplo n.º 4
0
        public void Find(OSPCResult result, List<CompareResult> compareResult)
        {
            var friends = new Dictionary<Submission, FriendOf>();
            var min_friend_finder_similarity = _cfg.MIN_FRIEND_FINDER_SIMILARITY >= 0
                ? _cfg.MIN_FRIEND_FINDER_SIMILARITY
                : result.POI_Similarity - 0.2;
            min_friend_finder_similarity = Math.Max(min_friend_finder_similarity, _cfg.MIN_SIMILARITY);

            // if result.POI_Similarity is 0, min_friend_finder_similarity may become negative.
            // So every submission is a group and every match is in that group.
            if (min_friend_finder_similarity > 0)
            {
                foreach (var cp in compareResult)
                {
                    ProcessMatch(friends, cp, cp.A, cp.SimilarityB, min_friend_finder_similarity);
                    ProcessMatch(friends, cp, cp.B, cp.SimilarityA, min_friend_finder_similarity);
                }
            }

            result.Friends = friends.Values
                .Where(i => i.InMatches.Count > 1)
                .OrderByDescending(i => i.SumSimilarity)
                .ToList();
        }
Ejemplo n.º 5
0
        static void Main(string[] args)
        {
            try
            {
                var  cfg      = new Configuration();
                bool showHelp = false;

                // common dependencies
                var progress = new ConsoleProgressReporter();

                // changable through config or arguments
                Reporter.IReporter   html      = null;
                Reporter.IReporter   console   = new Reporter.ConsoleReporter();
                Tokenizer.ITokenizer tokenizer = new Tokenizer.CLikeTokenizer();
                var p = new OptionSet()
                {
                    { "h|?|help", "Prints this help", v => showHelp = true },
                    { "c=", "Reads the given configuration. Note, this switch should be the first argument as it overrides any other argument parsed yet.", v => cfg = LoadConfig(v) },
                    { "write-config=", "Write the current configuration to the given file. Note, this switch should be the last argument.", v => SaveConfig(cfg, v) },

                    { "f=", "File filter. If -d is specified, then -f defaults to \"*.*.\"", v => cfg.Filter.Add(v) },
                    { "d=", "Specifies a directory where the filer applies. If -f is specified, then -d defaults to \".\"", v => cfg.Dirs.Add(v) },
                    { "include=", "Specifies a regular expression that every file must match. More than one expression is allowed. A file must match any of these expressions.", v => cfg.Include.Add(v) },
                    { "exclude=", "Specifies a regular expression to exclude files. More than one expression is allowed. If a file must match any of these expressions it will be excluded.", v => cfg.Exclude.Add(v) },
                    { "recurse", "Traversals all directories recurse. Use include-dir and exclude-dir to have more control over the selected directories.", v => cfg.Recurse = true },
                    { "include-dir=", "Specifies a regular expression that every file must match. More than one expression is allowed. A file must match any of these expressions.", v => cfg.IncludeDir.Add(v) },
                    { "exclude-dir=", "Specifies a regular expression to exclude files. More than one expression is allowed. If a file must match any of these expressions it will be excluded.", v => cfg.ExcludeDir.Add(v) },
                    { "againstdir", "Compares the files specified as arguments against the directory set with -d", v => cfg.OneAgainstDir = true },
                    { "detailed", "Print a detailed report to the console", v => console = new Reporter.DetailedConsoleReporter() },
                    { "summary", "Print only a summay to the console. Usefull if --html is used.", v => console = new Reporter.SummaryConsoleReporter() },
                    { "html:", "Saves a html report to the specified directory. Defaults to \"report\"", v => html = new Reporter.Html.HtmlReporter(v, progress) },
                    { "min-similarity=", "Minimum similarity of match reports (0 - 1). Default is 0.5 (=50%).", v => cfg.MIN_SIMILARITY = double.Parse(v, System.Globalization.CultureInfo.InvariantCulture) },

                    { "min-match-length=", "Minimum count of matching tokens, including non-matching tokens.", v => cfg.MIN_MATCH_LENGTH = int.Parse(v) },
                    { "max-match-distance=", "Maximum distance between tokens to count as a match. 1 = exact match.", v => cfg.MAX_MATCH_DISTANCE = int.Parse(v) },
                    { "min-common-token=", "Percent of token that must match to count as a match. 1 = every token must match.", v => cfg.MIN_COMMON_TOKEN = double.Parse(v, System.Globalization.CultureInfo.InvariantCulture) },


                    { "v|verbose", "Verbose output.", v => cfg.Verbose = true },
                };

                var extraFiles = p.Parse(args);
                // split that, as during parse the reference of cfg may change.
                // The compiler might save the reference to the old, overridden
                // config instance.
                cfg.ExtraFiles = extraFiles;

                if (showHelp)
                {
                    ShowHelp(p);
                    return;
                }

                var comparer     = new Comparer(cfg, progress);
                var friendfinder = new FriendFinder(cfg);
                var watch        = Stopwatch.StartNew();


                if (cfg.OneAgainstDir)
                {
                    var dirFiles   = CollectFiles(cfg, tokenizer, true, false);
                    var givenFiles = CollectFiles(cfg, tokenizer, false, true);

                    var compareResult = comparer.Compare(givenFiles, dirFiles);
                    var result        = OSPCResult.Create(compareResult);
                    friendfinder.Find(result, compareResult);
                    CreateReports(cfg, html, console, result);
                }
                else
                {
                    var files = CollectFiles(cfg, tokenizer);
                    if (files.Length != 0)
                    {
                        var compareResult = comparer.Compare(files);
                        var result        = OSPCResult.Create(compareResult);
                        friendfinder.Find(result, compareResult);
                        CreateReports(cfg, html, console, result);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine("********** Error occurred, exiting **********");
                Console.WriteLine(ex.ToString());
                Environment.Exit(1);
            }
        }
Ejemplo n.º 6
0
 private static void CreateReports(Configuration cfg, Reporter.IReporter html, Reporter.IReporter console, OSPCResult result)
 {
     if (html != null)
     {
         html.Create(cfg, result);
     }
     console.Create(cfg, result);
 }
Ejemplo n.º 7
0
 private static void CreateReports(Configuration cfg, Reporter.IReporter html, Reporter.IReporter console, OSPCResult result)
 {
     if (html != null)
     {
         html.Create(cfg, result);
     }
     console.Create(cfg, result);
 }
Ejemplo n.º 8
0
        static void Main(string[] args)
        {
            try
            {
                var  cfg      = new Configuration();
                bool showHelp = false;

                // common dependencies
                var progress = new ConsoleProgressReporter();

                // changable through config or arguments
                Reporter.IReporter   html      = null;
                Reporter.IReporter   console   = new Reporter.ConsoleReporter();
                Tokenizer.ITokenizer tokenizer = new Tokenizer.CLikeTokenizer();

                Console.WriteLine("Open Software Plagiarism Checker");
                Console.WriteLine("================================");
                Console.WriteLine("Version {0}", typeof(OSPC.Program).Assembly.GetName().Version);
                Console.WriteLine();
                Console.WriteLine("Copyright (C) 2015 Arthur Zaczek at the UAS Technikum Wien, GPL V3");
                Console.WriteLine("This program comes with ABSOLUTELY NO WARRANTY; see the GPL V3 for details.");
                Console.WriteLine("This is free software, and you are welcome to redistribute it");
                Console.WriteLine("under certain conditions; see the GPL V3 for details.");
                Console.WriteLine();

                var p = new OptionSet()
                {
                    { "h|?|help", "Prints this help", v => showHelp = true },
                    { "c=", "Reads the given configuration. Note, this switch should be the first argument as it overrides any other argument parsed yet.", v => cfg = LoadConfig(v) },
                    { "write-config=", "Write the current configuration to the given file. Note, this switch should be the last argument.", v => SaveConfig(cfg, v) },

                    { "f=", "File filter. If -d is specified, then -f defaults to \"*.*.\"", v => cfg.Filter.Add(v) },
                    { "d=", "Specifies a directory where the filer applies. If -f is specified, then -d defaults to \".\"", v => cfg.Dirs.Add(v) },
                    { "include=", "Specifies a regular expression that every file must match. More than one expression is allowed. A file must match any of these expressions.", v => cfg.Include.Add(v) },
                    { "exclude=", "Specifies a regular expression to exclude files. More than one expression is allowed. If a file must match any of these expressions it will be excluded.", v => cfg.Exclude.Add(v) },
                    { "recurse", "Traversals all directories recurse. Use include-dir and exclude-dir to have more control over the selected directories.", v => cfg.Recurse = true },
                    { "include-dir=", "Specifies a regular expression that every file must match. More than one expression is allowed. A file must match any of these expressions.", v => cfg.IncludeDir.Add(v) },
                    { "exclude-dir=", "Specifies a regular expression to exclude files. More than one expression is allowed. If a file must match any of these expressions it will be excluded.", v => cfg.ExcludeDir.Add(v) },

                    { "detailed", "Print a detailed report to the console", v => console = new Reporter.DetailedConsoleReporter() },
                    { "summary", "Print only a summay to the console. Usefull if --html is used.", v => console = new Reporter.SummaryConsoleReporter() },
                    { "html:", "Saves a html report to the specified directory. Defaults to \"report\"", v => html = new Reporter.Html.HtmlReporter(v, progress) },
                    { "min-similarity=", "Minimum similarity of match reports (0 - 1). Default is 0.5 (=50%).", v => cfg.MIN_SIMILARITY = double.Parse(v, System.Globalization.CultureInfo.InvariantCulture) },

                    { "min-match-length=", "Minimum count of matching tokens, including non-matching tokens.", v => cfg.MIN_MATCH_LENGTH = int.Parse(v) },
                    { "max-match-distance=", "Maximum distance between tokens to count as a match. 1 = exact match.", v => cfg.MAX_MATCH_DISTANCE = int.Parse(v) },
                    { "min-common-token=", "Percent of token that must match to count as a match. 1 = every token must match.", v => cfg.MIN_COMMON_TOKEN = double.Parse(v, System.Globalization.CultureInfo.InvariantCulture) },

                    { "v|verbose", "Verbose output.", v => cfg.Verbose = true },
                };

                var extraFiles = p.Parse(args);
                // split that, as during parse the reference of cfg may change.
                // The compiler might save the reference to the old, overridden
                // config instance.
                cfg.ExtraFiles = extraFiles;

                if (showHelp)
                {
                    ShowHelp(p);
                    return;
                }

                var comparer     = new Comparer(cfg, progress);
                var friendfinder = new FriendFinder(cfg);
                var watch        = Stopwatch.StartNew();

                Console.WriteLine("Collecting files");
                var files = CollectFiles(cfg, tokenizer);
                Console.WriteLine("  finished; time: {0:n2} sec.", watch.Elapsed.TotalSeconds);
                if (files.Length == 0)
                {
                    Console.WriteLine("No files found to compare!");
                }
                else
                {
                    Console.Write("Comparing {0} files ", files.Length);
                    var compareResult = comparer.Compare(files);
                    Console.WriteLine("  finished; time: {0:n2} sec.", watch.Elapsed.TotalSeconds);

                    Console.WriteLine("Creating statistics");
                    var result = OSPCResult.Create(compareResult);
                    friendfinder.Find(result, compareResult);
                    Console.WriteLine("  finished; time: {0:n2} sec.", watch.Elapsed.TotalSeconds);

                    Console.WriteLine("Creating reports");
                    CreateReports(cfg, html, console, result);
                    Console.WriteLine("  finished in total {0:n2} sec.", watch.Elapsed.TotalSeconds);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine("********** Error occurred, exiting **********");
                Console.WriteLine(ex.ToString());
                Environment.Exit(1);
            }
        }