Skip to content

Commit 9821be6

Browse files
authored
Merge pull request #2168 from jplag/feature/implicitViewMode
Added automatic mode selection
2 parents cd83953 + ffc90c9 commit 9821be6

File tree

6 files changed

+142
-130
lines changed

6 files changed

+142
-130
lines changed

README.md

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -80,86 +80,59 @@ The language can either be set with the -l parameter or as a subcommand (`jplag
8080
Language-specific arguments can be set when using the subcommand. A list of language-specific options can be obtained by requesting the help page of a subcommand (e.g., `jplag java —h`).
8181

8282
```
83-
Parameter descriptions:
83+
Parameter descriptions:
8484
[root-dirs[,root-dirs...]...]
85-
Root-directory with submissions to check for
86-
plagiarism. If mode is set to VIEW, this parameter
87-
can be used to specify a file to open. In that case
88-
only a single file may be specified.
85+
Root-directory with submissions to check for plagiarism. If mode is set to VIEW, this parameter can be used to specify a report file to open. In that
86+
case only a single file may be specified.
8987
-bc, --bc, --base-code=<baseCode>
90-
Path to the base code directory (common framework used
91-
in all submissions).
92-
-l, --language=<language>
93-
Select the language of the submissions (default: java).
94-
See subcommands below.
95-
-M, --mode=<{RUN, VIEW, RUN_AND_VIEW}>
96-
The mode of JPlag. If VIEW is chosen, you can specify a
97-
result file to display. One of: RUN, VIEW,
98-
RUN_AND_VIEW (default: null)
99-
-n, --shown-comparisons=<shownComparisons>
100-
The maximum number of comparisons that will be shown in
101-
the generated report, if set to -1 all comparisons
102-
will be shown (default: 2500)
88+
Path to the base code directory (common framework used in all submissions).
89+
-l, --language=<language>
90+
Select the language of the submissions (default: java). See subcommands below.
91+
-M, --mode=<{RUN, VIEW, RUN_AND_VIEW, AUTO}>
92+
The mode of JPlag. One of: RUN, VIEW, RUN_AND_VIEW, AUTO (default: null). If VIEW is chosen, you can optionally specify a path to an existing report.
93+
-n, --shown-comparisons=<shownComparisons>
94+
The maximum number of comparisons that will be shown in the generated report, if set to -1 all comparisons will be shown (default: 2500)
10395
-new, --new=<newDirectories>[,<newDirectories>...]
104-
Root-directories with submissions to check for
105-
plagiarism (same as root).
106-
--normalize Activate the normalization of tokens. Supported for
107-
languages: Java, C++.
96+
Root-directories with submissions to check for plagiarism (same as root).
97+
--normalize Activate the normalization of tokens. Supported for languages: Java, C++.
10898
-old, --old=<oldDirectories>[,<oldDirectories>...]
109-
Root-directories with prior submissions to compare
110-
against.
111-
-r, --result-file=<resultFile>
112-
Name of the file in which the comparison results will
113-
be stored (default: results). Missing .zip endings
114-
will be automatically added.
115-
-t, --min-tokens=<minTokenMatch>
116-
Tunes the comparison sensitivity by adjusting the
117-
minimum token required to be counted as a matching
118-
section. A smaller value increases the sensitivity
119-
but might lead to more false-positives.
99+
Root-directories with prior submissions to compare against.
100+
-r, --result-file=<resultFile>
101+
Name of the file in which the comparison results will be stored (default: results). Missing .zip endings will be automatically added.
102+
-t, --min-tokens=<minTokenMatch>
103+
Tunes the comparison sensitivity by adjusting the minimum token required to be counted as a matching section. A smaller value increases the
104+
sensitivity but might lead to more false-positives.
120105
121106
Advanced
122107
--csv-export Export pairwise similarity values as a CSV file.
123-
-d, --debug Store on-parsable files in error folder.
108+
-d, --debug Store on-parsable files in error folder.
124109
--log-level=<{ERROR, WARN, INFO, DEBUG, TRACE}>
125110
Set the log level for the cli.
126-
-m, --similarity-threshold=<similarityThreshold>
127-
Comparison similarity threshold [0.0-1.0]: All
128-
comparisons above this threshold will be saved
129-
(default: 0.0).
111+
-m, --similarity-threshold=<similarityThreshold>
112+
Comparison similarity threshold [0.0-1.0]: All comparisons above this threshold will be saved (default: 0.0).
130113
--overwrite Existing result files will be overwritten.
131-
-p, --suffixes=<suffixes>[,<suffixes>...]
132-
comma-separated list of all filename suffixes that are
133-
included.
134-
-P, --port=<port> The port used for the internal report viewer (default:
135-
1996).
136-
-s, --subdirectory=<subdirectory>
114+
-p, --suffixes=<suffixes>[,<suffixes>...]
115+
comma-separated list of all filename suffixes that are included.
116+
-P, --port=<port> The port used for the internal report viewer (default: 1996).
117+
-s, --subdirectory=<subdirectory>
137118
Look in directories <root-dir>/*/<dir> for programs.
138-
-x, --exclusion-file=<exclusionFileName>
139-
All files named in this file will be ignored in the
140-
comparison (line-separated list).
119+
-x, --exclusion-file=<exclusionFileName>
120+
All files named in this file will be ignored in the comparison (line-separated list).
141121
142122
Clustering
143123
--cluster-alg, --cluster-algorithm=<{AGGLOMERATIVE, SPECTRAL}>
144-
Specifies the clustering algorithm. Available
145-
algorithms: agglomerative, spectral (default:
146-
spectral).
124+
Specifies the clustering algorithm. Available algorithms: agglomerative, spectral (default: spectral).
147125
--cluster-metric=<{AVG, MIN, MAX, INTERSECTION}>
148-
The similarity metric used for clustering. Available
149-
metrics: average similarity, minimum similarity,
150-
maximal similarity, matched tokens (default: average
151-
similarity).
126+
The similarity metric used for clustering. Available metrics: average similarity, minimum similarity, maximal similarity, matched tokens (default:
127+
average similarity).
152128
--cluster-skip Skips the cluster calculation.
153129
154130
Subsequence Match Merging
155131
--gap-size=<maximumGapSize>
156-
Maximal gap between neighboring matches to be merged
157-
(between 1 and minTokenMatch, default: 6).
158-
--match-merging Enables merging of neighboring matches to counteract
159-
obfuscation attempts.
132+
Maximal gap between neighboring matches to be merged (between 1 and minTokenMatch, default: 6).
133+
--match-merging Enables merging of neighboring matches to counteract obfuscation attempts.
160134
--neighbor-length=<minimumNeighborLength>
161-
Minimal length of neighboring matches to be merged
162-
(between 1 and minTokenMatch, default: 2).
135+
Minimal length of neighboring matches to be merged (between 1 and minTokenMatch, default: 2).
163136
Languages:
164137
c
165138
cpp
@@ -171,6 +144,7 @@ Languages:
171144
javascript
172145
kotlin
173146
llvmir
147+
multi
174148
python3
175149
rlang
176150
rust

cli/src/main/java/de/jplag/cli/CLI.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.io.File;
44
import java.io.FileNotFoundException;
55
import java.io.IOException;
6+
import java.util.ArrayList;
7+
import java.util.List;
68

79
import org.slf4j.ILoggerFactory;
810
import org.slf4j.Logger;
@@ -32,6 +34,8 @@ public final class CLI {
3234
private static final String OUTPUT_FILE_EXISTS = "The output file (also with suffixes e.g. results(1).zip) already exists. You can use --overwrite to overwrite the file.";
3335
private static final String OUTPUT_FILE_NOT_WRITABLE = "The output file (%s) cannot be written to.";
3436

37+
private static final String ZIP_FILE_EXTENSION = ".zip";
38+
3539
private final CliInputHandler inputHandler;
3640

3741
/**
@@ -58,7 +62,8 @@ public void executeCli() throws ExitException, IOException {
5862
switch (this.inputHandler.getCliOptions().mode) {
5963
case RUN -> runJPlag();
6064
case VIEW -> runViewer(this.inputHandler.getFileForViewMode());
61-
case RUN_AND_VIEW -> runViewer(runJPlag());
65+
case RUN_AND_VIEW -> runAndView();
66+
case AUTO -> selectModeAutomatically();
6267
}
6368
}
6469
}
@@ -105,6 +110,15 @@ public File runJPlag() throws ExitException, FileNotFoundException {
105110
return target;
106111
}
107112

113+
/**
114+
* Runs JPlag and shows the result in the report viewer
115+
* @throws IOException If something went wrong with the internal server
116+
* @throws ExitException If JPlag threw an exception
117+
*/
118+
public void runAndView() throws IOException, ExitException {
119+
runViewer(runJPlag());
120+
}
121+
108122
/**
109123
* Runs the report viewer using the given file as the default result.zip.
110124
* @param zipFile The zip file to pass to the viewer. Can be null, if no result should be opened by default
@@ -115,6 +129,31 @@ public void runViewer(File zipFile) throws IOException {
115129
JPlagRunner.runInternalServer(zipFile, this.inputHandler.getCliOptions().advanced.port);
116130
}
117131

132+
private void selectModeAutomatically() throws IOException, ExitException {
133+
List<File> inputs = this.getAllInputs();
134+
135+
if (inputs.isEmpty()) {
136+
this.runViewer(null);
137+
return;
138+
}
139+
140+
// if the selected mode is auto and there is exactly one zip file selected as an input it is opened in the report viewer
141+
if (inputs.size() == 1 && inputs.getFirst().getName().endsWith(ZIP_FILE_EXTENSION)) {
142+
this.runViewer(inputs.getFirst());
143+
return;
144+
}
145+
146+
this.runAndView();
147+
}
148+
149+
private List<File> getAllInputs() {
150+
List<File> inputs = new ArrayList<>();
151+
inputs.addAll(List.of(this.inputHandler.getCliOptions().rootDirectory));
152+
inputs.addAll(List.of(this.inputHandler.getCliOptions().newDirectories));
153+
inputs.addAll(List.of(this.inputHandler.getCliOptions().oldDirectories));
154+
return inputs;
155+
}
156+
118157
private void finalizeLogger() {
119158
ILoggerFactory factory = LoggerFactory.getILoggerFactory();
120159
if (!(factory instanceof CollectedLoggerFactory collectedLoggerFactory)) {

cli/src/main/java/de/jplag/cli/options/CliOptions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class CliOptions implements Runnable {
5555

5656
@Option(names = {"-M",
5757
"--mode"}, description = "The mode of JPlag. One of: ${COMPLETION-CANDIDATES} (default: ${DEFAULT_VALUE}). If VIEW is chosen, you can optionally specify a path to an existing report.")
58-
public JPlagMode mode = JPlagMode.RUN_AND_VIEW;
58+
public JPlagMode mode = JPlagMode.AUTO;
5959

6060
@Option(names = {"--normalize"}, description = "Activate the normalization of tokens. Supported for languages: Java, C++.")
6161
public boolean normalize = false;

cli/src/main/java/de/jplag/cli/options/JPlagMode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@ public enum JPlagMode {
1515
/**
1616
* Run JPlag and open the result in report viewer
1717
*/
18-
RUN_AND_VIEW
18+
RUN_AND_VIEW,
19+
/**
20+
* Choose the mode automatically from the given input files
21+
*/
22+
AUTO,
1923
}

cli/src/test/java/de/jplag/cli/ModeTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package de.jplag.cli;
22

33
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNull;
45
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
56

67
import java.io.File;
@@ -53,6 +54,18 @@ void testViewWithMultipleFiles() {
5354
});
5455
}
5556

57+
@Test
58+
void testImplicitView() throws IOException, ExitException {
59+
CliInputHandler inputHandler = this.runCli(args -> args.with(CliArgument.RESULT_FILE, "result.zip")).inputHandler();
60+
assertEquals(new File("result.zip"), inputHandler.getFileForViewMode());
61+
}
62+
63+
@Test
64+
void testImplicitReportViewer() throws IOException, ExitException {
65+
CliInputHandler inputHandler = this.runCli().inputHandler();
66+
assertNull(inputHandler.getFileForViewMode());
67+
}
68+
5669
@Override
5770
public void addDefaultParameters() {
5871
// prevents the submission directory from being added to the parameters automatically

0 commit comments

Comments
 (0)