JPlagComparison.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package de.jplag;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Objects;
  5. /**
  6. * This method represents the whole result of a comparison between two submissions.
  7. */
  8. public class JPlagComparison { // FIXME TS: contains a lot of code duplication
  9. private static final int ROUNDING_FACTOR = 10;
  10. private final Submission firstSubmission;
  11. private final Submission secondSubmission;
  12. private final List<Match> matches;
  13. public JPlagComparison(Submission firstSubmission, Submission secondSubmission) {
  14. this.firstSubmission = firstSubmission;
  15. this.secondSubmission = secondSubmission;
  16. matches = new ArrayList<>();
  17. }
  18. /**
  19. * Add a match to the comparison (token indices and number of tokens), if it does not overlap with the existing matches.
  20. * @see Match#Match(int, int, int)
  21. */
  22. /* package-private */ final void addMatch(int startOfFirst, int startOfSecond, int length) {
  23. for (Match match : matches) {
  24. if (match.overlap(startOfFirst, startOfSecond, length)) {
  25. return;
  26. }
  27. }
  28. matches.add(new Match(startOfFirst, startOfSecond, length));
  29. }
  30. @Override
  31. public boolean equals(Object other) {
  32. if (other == this) {
  33. return true;
  34. }
  35. if (!(other instanceof JPlagComparison otherComparison)) {
  36. return false;
  37. }
  38. return firstSubmission.equals(otherComparison.getFirstSubmission()) && secondSubmission.equals(otherComparison.getSecondSubmission())
  39. && matches.equals(otherComparison.matches);
  40. }
  41. @Override
  42. public int hashCode() {
  43. return Objects.hash(firstSubmission, secondSubmission, matches);
  44. }
  45. /**
  46. * @return the base code matches of the first submission.
  47. */
  48. public JPlagComparison getFirstBaseCodeMatches() {
  49. return firstSubmission.getBaseCodeComparison();
  50. }
  51. /**
  52. * @return the first of the two submissions.
  53. */
  54. public Submission getFirstSubmission() {
  55. return firstSubmission;
  56. }
  57. /**
  58. * @return all matches between the two submissions.
  59. */
  60. public List<Match> getMatches() {
  61. return matches;
  62. }
  63. /**
  64. * Get the total number of matched tokens for this comparison.
  65. */
  66. public final int getNumberOfMatchedTokens() {
  67. int numberOfMatchedTokens = 0;
  68. for (Match match : matches) {
  69. numberOfMatchedTokens += match.length();
  70. }
  71. return numberOfMatchedTokens;
  72. }
  73. /**
  74. * @return the base code matches of the second submissions.
  75. */
  76. public JPlagComparison getSecondBaseCodeMatches() {
  77. return secondSubmission.getBaseCodeComparison();
  78. }
  79. /**
  80. * @return the second of the two submissions.
  81. */
  82. public Submission getSecondSubmission() {
  83. return secondSubmission;
  84. }
  85. /**
  86. * @return Maximum similarity in percent of both submissions.
  87. */
  88. public final float maximalSimilarity() {
  89. return Math.max(similarityOfFirst(), similarityOfSecond());
  90. }
  91. /**
  92. * @return Minimum similarity in percent of both submissions.
  93. */
  94. public final float minimalSimilarity() {
  95. return Math.min(similarityOfFirst(), similarityOfSecond());
  96. }
  97. /**
  98. * @return Similarity in percent (what percentage of tokens across both submissions are matched).
  99. */
  100. public final float similarity() {
  101. boolean subtractBaseCode = firstSubmission.hasBaseCodeMatches() && secondSubmission.hasBaseCodeMatches();
  102. float sa = firstSubmission.getSimilarityDivisor(subtractBaseCode);
  103. float sb = secondSubmission.getSimilarityDivisor(subtractBaseCode);
  104. return (200 * getNumberOfMatchedTokens()) / (sa + sb);
  105. }
  106. /**
  107. * @return Similarity in percent for the first submission (what percent of the first submission is similar to the
  108. * second).
  109. */
  110. public final float similarityOfFirst() {
  111. int divisor = firstSubmission.getSimilarityDivisor(true);
  112. return (divisor == 0 ? 0f : (getNumberOfMatchedTokens() * 100 / (float) divisor));
  113. }
  114. /**
  115. * @return Similarity in percent for the second submission (what percent of the second submission is similar to the
  116. * first).
  117. */
  118. public final float similarityOfSecond() {
  119. int divisor = secondSubmission.getSimilarityDivisor(true);
  120. return (divisor == 0 ? 0f : (getNumberOfMatchedTokens() * 100 / (float) divisor));
  121. }
  122. /**
  123. * @return Similarity in percent rounded down to the nearest tenth.
  124. */
  125. public final float roundedSimilarity() {
  126. return ((int) (similarity() * ROUNDING_FACTOR)) / (float) ROUNDING_FACTOR;
  127. }
  128. /**
  129. * @return Similarity of the first submission to the basecode in percent rounded down to the nearest tenth.
  130. */
  131. public final float basecodeSimilarityOfFirst() {
  132. return ((int) (firstBasecodeSimilarity() * ROUNDING_FACTOR)) / (float) ROUNDING_FACTOR;
  133. }
  134. /**
  135. * @return Similarity of the second submission to the basecode in percent rounded down to the nearest tenth.
  136. */
  137. public final float basecodeSimilarityOfSecond() {
  138. return ((int) (secondBasecodeSimilarity() * ROUNDING_FACTOR)) / (float) ROUNDING_FACTOR;
  139. }
  140. @Override
  141. public String toString() {
  142. return firstSubmission.getName() + " <-> " + secondSubmission.getName();
  143. }
  144. private float firstBasecodeSimilarity() {
  145. float sa = firstSubmission.getSimilarityDivisor(false);
  146. JPlagComparison firstBaseCodeMatches = firstSubmission.getBaseCodeComparison();
  147. return firstBaseCodeMatches.getNumberOfMatchedTokens() * 100 / sa;
  148. }
  149. private float secondBasecodeSimilarity() {
  150. float sb = secondSubmission.getSimilarityDivisor(false);
  151. JPlagComparison secondBaseCodeMatches = secondSubmission.getBaseCodeComparison();
  152. return secondBaseCodeMatches.getNumberOfMatchedTokens() * 100 / sb;
  153. }
  154. }