Groove.java

1
package com.github.dakusui.symfonion.song;
2
3
import com.github.dakusui.json.JsonFormatException;
4
import com.github.dakusui.json.JsonInvalidPathException;
5
import com.github.dakusui.json.JsonTypeMismatchException;
6
import com.github.dakusui.json.JsonUtils;
7
import com.github.dakusui.symfonion.utils.Fraction;
8
import com.github.dakusui.symfonion.exceptions.SymfonionException;
9
import com.github.dakusui.symfonion.utils.Utils;
10
import com.google.gson.JsonArray;
11
import com.google.gson.JsonElement;
12
import com.google.gson.JsonObject;
13
14
import java.util.LinkedList;
15
import java.util.List;
16
17
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.*;
18
import static com.github.dakusui.symfonion.exceptions.SymfonionIllegalFormatException.NOTE_LENGTH_EXAMPLE;
19
import static com.github.dakusui.symfonion.exceptions.SymfonionTypeMismatchException.OBJECT;
20
21
public class Groove {
22
  public static final Groove DEFAULT_INSTANCE = new Groove();
23
24
  record Beat(Fraction length, long ticks, int accent) {
25
  }
26
27
  public record Unit(long pos, int accentDelta) {
28
29
    public int accent() {
30 1 1. accent : replaced int return with 0 for com/github/dakusui/symfonion/song/Groove$Unit::accent → SURVIVED
        return this.accentDelta;
31
      }
32
    }
33
  
34
  List<Beat> beats = new LinkedList<>();
35
  
36
  private final int resolution;
37
  
38
  public Groove() {
39
    this(384);
40
  }
41
  
42
  public Groove(int resolution) {
43
    this.resolution = resolution;
44
  }
45
  
46
  public Unit resolve(Fraction offset) {
47 1 1. resolve : negated conditional → KILLED
    if (offset == null) {
48
      String msg = "offset cannot be null. (Groove#resolve)";
49
      throw runtimeException(msg, null);
50
    }
51 2 1. resolve : changed conditional boundary → KILLED
2. resolve : negated conditional → KILLED
    if (Fraction.compare(offset, Fraction.zero) < 0) {
52
      String msg = "offset cannot be negative. (Groove#resolve)";
53
      throw runtimeException(msg, null);
54
    }
55
    long pos = 0;
56
    
57
    Fraction rest = offset.clone();
58
    int i = 0;
59 2 1. resolve : negated conditional → KILLED
2. resolve : changed conditional boundary → KILLED
    while (Fraction.compare(rest, Fraction.zero) > 0) {
60 2 1. resolve : negated conditional → KILLED
2. resolve : changed conditional boundary → KILLED
      if (i >= this.beats.size()) {
61
        break;
62
      }
63
      Beat beat = this.beats.get(i);
64
      rest = Fraction.subtract(rest, beat.length);
65 1 1. resolve : Replaced long addition with subtraction → KILLED
      pos += beat.ticks;
66 1 1. resolve : Changed increment from 1 to -1 → KILLED
      i++;
67
    }
68
    long p;
69
    int d = 0;
70 2 1. resolve : changed conditional boundary → KILLED
2. resolve : negated conditional → KILLED
    if (Fraction.compare(rest, Fraction.zero) < 0) {
71 1 1. resolve : Replaced integer subtraction with addition → SURVIVED
      Beat beat = this.beats.get(i - 1);
72 2 1. resolve : Replaced double addition with subtraction → KILLED
2. resolve : Replaced double multiplication with division → KILLED
      p = (long) (pos + Fraction.div(rest, beat.length).doubleValue() * beat.ticks);
73 1 1. resolve : negated conditional → KILLED
    } else if (Fraction.compare(rest, Fraction.zero) == 0) {
74 2 1. resolve : negated conditional → KILLED
2. resolve : changed conditional boundary → KILLED
      if (i < this.beats.size()) {
75
        d = this.beats.get(i).accent;
76
      }
77
      p = pos;
78
    } else {
79 2 1. resolve : Replaced long addition with subtraction → KILLED
2. resolve : Replaced double multiplication with division → KILLED
      p = (pos + (long) (rest.doubleValue() * this.resolution));
80
    }
81 1 1. resolve : replaced return value with null for com/github/dakusui/symfonion/song/Groove::resolve → KILLED
    return new Unit(p, d);
82
  }
83
  
84
  public void add(Fraction length, long ticks, int accent) {
85 1 1. add : negated conditional → KILLED
    if (this == DEFAULT_INSTANCE) {
86
      throw runtimeException("Groove.DEFAULT_INSTANCE is immutable.", null);
87
    }
88
    beats.add(new Beat(length, ticks, accent));
89
  }
90
  
91
  public static Groove createGroove(JsonArray grooveDef) throws SymfonionException, JsonTypeMismatchException, JsonInvalidPathException, JsonFormatException {
92
    Groove ret = new Groove();
93
    for (JsonElement elem : grooveDef) {
94 1 1. createGroove : negated conditional → KILLED
      if (!elem.isJsonObject()) {
95
        throw typeMismatchException(elem, OBJECT);
96
      }
97
      JsonObject cur = elem.getAsJsonObject();
98
      String len = JsonUtils.asString(cur, Keyword.$length);
99
      long ticks = JsonUtils.asLong(cur, Keyword.$ticks);
100
      int accent = JsonUtils.asInt(cur, Keyword.$accent);
101
      
102
      Fraction f = Utils.parseNoteLength(len);
103 1 1. createGroove : negated conditional → KILLED
      if (f == null) {
104
        throw illegalFormatException(JsonUtils.asJsonElement(cur, Keyword.$length), NOTE_LENGTH_EXAMPLE);
105
      }
106 1 1. createGroove : removed call to com/github/dakusui/symfonion/song/Groove::add → KILLED
      ret.add(f, ticks, accent);
107
    }
108 1 1. createGroove : replaced return value with null for com/github/dakusui/symfonion/song/Groove::createGroove → KILLED
    return ret;
109
  }
110
}
111

Mutations

30

1.1
Location : accent
Killed by : none
replaced int return with 0 for com/github/dakusui/symfonion/song/Groove$Unit::accent → SURVIVED

47

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

51

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
changed conditional boundary → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

59

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
changed conditional boundary → KILLED

60

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A04(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B06(com.github.dakusui.symfonion.tests.song.GrooveTest)
changed conditional boundary → KILLED

65

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A05(com.github.dakusui.symfonion.tests.song.GrooveTest)
Replaced long addition with subtraction → KILLED

66

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A05(com.github.dakusui.symfonion.tests.song.GrooveTest)
Changed increment from 1 to -1 → KILLED

70

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
changed conditional boundary → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

71

1.1
Location : resolve
Killed by : none
Replaced integer subtraction with addition → SURVIVED

72

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A02(com.github.dakusui.symfonion.tests.song.GrooveTest)
Replaced double addition with subtraction → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A02(com.github.dakusui.symfonion.tests.song.GrooveTest)
Replaced double multiplication with division → KILLED

73

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

74

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_A05(com.github.dakusui.symfonion.tests.song.GrooveTest)
changed conditional boundary → KILLED

79

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B06(com.github.dakusui.symfonion.tests.song.GrooveTest)
Replaced long addition with subtraction → KILLED

2.2
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B06(com.github.dakusui.symfonion.tests.song.GrooveTest)
Replaced double multiplication with division → KILLED

81

1.1
Location : resolve
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
replaced return value with null for com/github/dakusui/symfonion/song/Groove::resolve → KILLED

85

1.1
Location : add
Killed by : com.github.dakusui.symfonion.tests.song.GrooveTest.test_B01(com.github.dakusui.symfonion.tests.song.GrooveTest)
negated conditional → KILLED

94

1.1
Location : createGroove
Killed by : com.github.dakusui.symfonion.tests.InvalidDataErrorTest.illegalNoteLength_01(com.github.dakusui.symfonion.tests.InvalidDataErrorTest)
negated conditional → KILLED

103

1.1
Location : createGroove
Killed by : com.github.dakusui.symfonion.tests.InvalidDataErrorTest.illegalNoteLength_01(com.github.dakusui.symfonion.tests.InvalidDataErrorTest)
negated conditional → KILLED

106

1.1
Location : createGroove
Killed by : com.github.dakusui.symfonion.tests.MidiCompilerTest.exercise[7: POSITIVE: given: 'sixteenth note with short gate (0.25)' when: 'compile' then: 'number of events and tick length seem ok'](com.github.dakusui.symfonion.tests.MidiCompilerTest)
removed call to com/github/dakusui/symfonion/song/Groove::add → KILLED

108

1.1
Location : createGroove
Killed by : com.github.dakusui.symfonion.tests.InvalidJsonErrorTest.missingSection_pattern(com.github.dakusui.symfonion.tests.InvalidJsonErrorTest)
replaced return value with null for com/github/dakusui/symfonion/song/Groove::createGroove → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.3