diff --git a/README.md b/README.md
index 8684f09..6a0ca63 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Check hitsound issues in osu!mania maps
2. The result will be displayed as hyperlink, clicking it will direct you to the note in osu editor.
## Download
-https://drive.google.com/open?id=1a1rDu9wMDM8re2qUGNXRf8OwJst9W7ht
+https://drive.google.com/open?id=1KpFyeb0lEAZkhLb0kZuzkUHoO0tlkt-O
## Usage
1. Check unused hitsound
@@ -20,6 +20,9 @@ Note: support WFC stacked on 1 note, custom hitsound and additions
## Change Log
+###### Update: Jan 13, 2019
+Added check for duplicate hitsound in a chord (including SB)
+
###### Update: Jan 10, 2019
Fixed bug Sampleset = None causing program to crash
diff --git a/src/detective/MistakeType.java b/src/detective/MistakeType.java
index 6450d40..912520f 100644
--- a/src/detective/MistakeType.java
+++ b/src/detective/MistakeType.java
@@ -10,7 +10,8 @@ public enum MistakeType {
SameOffsetTiming("Same Offset Timing"),
UnusedGreenTiming("Unused timing"),
MissingImage("Bg image is missing"),
- BadResolutionImage("Bg image must be within " + ImageDetective.MAX_WIDTH + "x"+ ImageDetective.MAX_HEIGHT + " pixels")
+ BadResolutionImage("Bg image must be within " + ImageDetective.MAX_WIDTH + "x"+ ImageDetective.MAX_HEIGHT + " pixels"),
+ DuplicateHitsound("Duplicate Hitsound")
;
private final String value;
diff --git a/src/detective/ResultsWindow.java b/src/detective/ResultsWindow.java
index 54f6fce..e00416d 100644
--- a/src/detective/ResultsWindow.java
+++ b/src/detective/ResultsWindow.java
@@ -27,7 +27,7 @@ public class ResultsWindow extends JFrame {
private JPanel contentPane;
private JTabbedPane tabbedPane;
- private static final String VERSION = "v20180825";
+ private static final String VERSION = "v20190113";
private static final String A_HREF = "";
private static final String HREF_END = "";
diff --git a/src/detective/hitsound/HitsoundDetectiveThread.java b/src/detective/hitsound/HitsoundDetectiveThread.java
index 74c0a7b..c5950c5 100644
--- a/src/detective/hitsound/HitsoundDetectiveThread.java
+++ b/src/detective/hitsound/HitsoundDetectiveThread.java
@@ -118,6 +118,10 @@ public void run() {
if (chord.SbHasSoundWhenHoIsEmpty()) {
mistakes.add(new TimedMistake(chord.getStartTime(), MistakeType.SBwhenNoNote));
}
+
+ if (chord.containsDuplicateHitsound()) {
+ mistakes.add(new TimedMistake(chord.getStartTime(), MistakeType.DuplicateHitsound));
+ }
if (!sourceDifficulty.equals(targetDifficulty)) {
int i = -1;
@@ -126,7 +130,7 @@ public void run() {
sourceChord = sourceChords.get(chord.getStartTime()+i);
i++;
}
-
+
if (!chord.containsHitsounds(sourceChord)) {
mistakes.add(new TimedMistake(chord.getStartTime(), MistakeType.Inconsistency));
}
diff --git a/src/osu/beatmap/Chord.java b/src/osu/beatmap/Chord.java
index 64c2a69..7b2cc05 100644
--- a/src/osu/beatmap/Chord.java
+++ b/src/osu/beatmap/Chord.java
@@ -1,4 +1,5 @@
package osu.beatmap;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -6,41 +7,64 @@
import osu.beatmap.event.Sample;
import osu.beatmap.hitobject.HitObject;
-
-public class Chord{
+public class Chord {
private ArrayList list_HO;
private ArrayList list_SB;
- public Chord(){
+ public Chord() {
list_HO = new ArrayList();
list_SB = new ArrayList();
}
-
- public long getStartTime(){
- if (list_HO.size()>0)
+
+ public long getStartTime() {
+ if (list_HO.size() > 0)
return list_HO.get(0).getStartTime();
- else if (list_SB.size()>0)
+ else if (list_SB.size() > 0)
return list_SB.get(0).getStartTime();
- else
+ else
return -1;
}
-
- public Set getHitsounds(){
- Set output = new HashSet<>();
+
+ public boolean containsDuplicateHitsound() {
+ Set set = new HashSet<>();
+ for (Sample sample : list_SB) {
+ if (!set.add(sample.gethitSound())){
+ return true;
+ }
+ }
+ for (HitObject hitObject : list_HO) {
+ if (hitObject.hasHitsound()) {
+ for (String hs : hitObject.toHitsoundString()) {
+ if (!set.add(hs)){
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ *
+ * @return Set of unique hitsounds
+ */
+ public Set getHitsounds() {
+ Set output = new HashSet<>();
+
for (Sample sample : list_SB) {
output.add(sample.gethitSound());
- }
-
+ }
+
for (HitObject hitObject : list_HO) {
if (hitObject.hasHitsound()) {
output.addAll(hitObject.toHitsoundString());
}
}
-
+
return output;
}
-
+
public boolean SbHasSoundWhenHoIsEmpty() {
if (list_HO.isEmpty()) {
if (!list_SB.isEmpty()) {
@@ -49,70 +73,71 @@ public boolean SbHasSoundWhenHoIsEmpty() {
}
return false;
}
-
+
@Override
public int hashCode() {
return getHitsounds().hashCode();
}
-
+
public boolean containsHitsounds(Chord chord) {
- if (chord == null) return true;
+ if (chord == null)
+ return true;
return this.getHitsounds().containsAll(chord.getHitsounds());
}
-
+
@Override
public boolean equals(Object other) {
if (other instanceof Chord) {
return getHitsounds().equals(((Chord) other).getHitsounds());
}
-
+
return false;
}
-
+
public void addALLSB(ArrayList SB) {
for (Sample s : SB) {
list_SB.add(s.clone());
}
}
-
- public void add(HitObject ho){
+
+ public void add(HitObject ho) {
list_HO.add(ho);
}
-
- public void add(Sample s){
+
+ public void add(Sample s) {
list_SB.add(s);
}
-
- public HitObject getHitObjectByIndex(int i){
+
+ public HitObject getHitObjectByIndex(int i) {
return list_HO.get(i);
}
-
- public Chord Clone(){
+
+ public Chord Clone() {
Chord newChord = new Chord();
- for (HitObject ho : list_HO){
+ for (HitObject ho : list_HO) {
newChord.add(ho.clone());
}
return newChord;
}
@Override
- public String toString(){
+ public String toString() {
String output = "Hit Objects\n";
- for (HitObject ho:list_HO){
+ for (HitObject ho : list_HO) {
try {
- output+= ho.toSample().toString() + "\n";
+ output += ho.toSample().toString() + "\n";
} catch (Exception e) {
e.printStackTrace();
}
}
output += "\nSamples\n";
- for (Sample s:list_SB){
- output+= s.toString() + "\n";
+ for (Sample s : list_SB) {
+ output += s.toString() + "\n";
}
-
+
return output;
}
-
+
public int getSize() {
return getHitsounds().size();
}