예제 #1
0
        private static Submission[] CollectFiles(Configuration cfg, Tokenizer.ITokenizer tokenizer)
        {
            if (cfg.Filter.Count == 0 && cfg.Dirs.Count > 0)
            {
                cfg.Filter.Add("*.*");
            }
            if (cfg.Dirs.Count == 0 && cfg.Filter.Count > 0)
            {
                cfg.Dirs.Add(".");
            }

            var files = new List<string>();
            var include = cfg.Include.Select(i => new Regex(i)).ToList();
            var exclude = cfg.Exclude.Select(i => new Regex(i)).ToList();
            var includeDir = cfg.IncludeDir.Select(i => new Regex(i)).ToList();
            var excludeDir = cfg.ExcludeDir.Select(i => new Regex(i)).ToList();

            CollectFilesRecurse(files, cfg.Dirs, true, include, exclude, includeDir, excludeDir, cfg);

            files.AddRange(cfg.ExtraFiles.Where(f =>
            {
                if (File.Exists(f))
                {
                    return true;
                }
                else
                {
                    Console.WriteLine("  ** Warning, file \"{0}\" not found.", f);
                    return false;
                }
            }));

            if (cfg.Verbose)
            {
                Console.WriteLine("Files:");
                foreach (var f in files)
                {
                    Console.WriteLine(f);
                }
                Console.WriteLine();
            }

            return files
                    .Select(f =>
                    {
                        var s = new Submission(f, tokenizer);
                        s.Parse();
                        return s;
                    })
                    .ToArray();
        }
예제 #2
0
 public FriendFinder(Configuration cfg)
 {
     this._cfg = cfg;
 }
예제 #3
0
        private static void CollectFilesRecurse(List<string> files, IEnumerable<string> directories, bool isFirstLevel, IEnumerable<Regex> include, IEnumerable<Regex> exclude, IEnumerable<Regex> includeDir, IEnumerable<Regex> excludeDir, Configuration cfg)
        {
            foreach (var dir in directories)
            {
                if (!Directory.Exists(dir))
                {
                    // At the first level, this may occour
                    Console.WriteLine("  ** Warning, directory \"{0}\" not found.", dir);
                    continue;
                }
                if (cfg.Verbose) Console.WriteLine("D: {0}", dir);
                if (!isFirstLevel)
                {
                    if (includeDir.Any() && !includeDir.Any(r => r.Match(dir).Success)) continue;
                    if (excludeDir.Any() && excludeDir.Any(r => r.Match(dir).Success)) continue;
                }

                foreach (var pattern in cfg.Filter)
                {
                    string[] dirFiles;
                    try
                    {
                        dirFiles = Directory.GetFiles(dir, pattern);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("  ** Warning: Unable to list directory with patern \"{0}\": {1}", pattern, ex.Message);
                        continue;
                    }

                    foreach (var f in dirFiles)
                    {
                        if (cfg.Verbose) Console.WriteLine("  F: {0}", f);

                        if (include.Any() && !include.Any(r => r.Match(f).Success)) continue;
                        if (exclude.Any() && exclude.Any(r => r.Match(f).Success)) continue;

                        files.Add(f);
                    }
                }

                if (cfg.Recurse)
                {
                    CollectFilesRecurse(files, Directory.GetDirectories(dir), false, include, exclude, includeDir, excludeDir, cfg);
                }
            }
        }
예제 #4
0
 private static void SaveConfig(Configuration cfg, string file)
 {
     Console.WriteLine("Writing current configuration.\n");
     using (var fs = new FileStream(file, FileMode.Create))
     {
         fs.SetLength(0);
         cfg.ToXmlStream(fs);
         fs.Flush();
     }
 }
예제 #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();

                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);
            }
        }
예제 #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);
 }
예제 #7
0
 public Comparer(Configuration cfg, IProgressReporter progress)
 {
     this._cfg = cfg;
     this._progress = progress;
 }