~ubuntu-branches/ubuntu/oneiric/tuxguitar/oneiric

« back to all changes in this revision

Viewing changes to TuxGuitar/src/org/herac/tuxguitar/gui/editors/chord/ChordCreatorUtil.java

  • Committer: Bazaar Package Importer
  • Author(s): Philippe Coval
  • Date: 2008-06-19 00:30:30 UTC
  • mto: (5.1.2 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20080619003030-h719szrhsngou7c6
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
 * Created on 31-dic-2005
 
4
 
 
5
 * Redesigned on 05-March-2007
 
6
 
 
7
 * 
 
8
 
 
9
 */
 
10
 
 
11
package org.herac.tuxguitar.gui.editors.chord;
 
12
 
 
13
import java.util.ArrayList;
 
14
import java.util.Collections;
 
15
 
 
16
import java.util.Comparator;
 
17
 
 
18
import java.util.Iterator;
 
19
 
 
20
import java.util.List;
 
21
 
 
22
import org.herac.tuxguitar.gui.TuxGuitar;
 
23
 
 
24
import org.herac.tuxguitar.song.models.TGChord;
 
25
 
 
26
/**
 
27
 * 
 
28
 * Class that helps to create a chord from information put in ChordSelector
 
29
 * dialog.
 
30
 * 
 
31
 * Also contains ChordDatabase static field.
 
32
 * 
 
33
 * @author Nikola Kolarovic
 
34
 * 
 
35
 * @author julian
 
36
 * 
 
37
 */
 
38
public class ChordCreatorUtil {
 
39
        
 
40
        /**
 
41
         * Maximum number of strings variable - has twin in TrackPropertiesAction
 
42
         * class
 
43
         */
 
44
        public static final int MAX_STRINGS = 7;
 
45
        
 
46
        /** Maximum fret distance for a chord */
 
47
        
 
48
        public static final int MAX_FRET_SPAN = 5;
 
49
        
 
50
        /** mark for bass note type **/
 
51
        private final int BASS_INDEX = -1;
 
52
        
 
53
        /** mark for essential note in a chord - MUST be in */
 
54
        private final int ESSENTIAL_INDEX = -2;
 
55
        
 
56
        /** mark for essential note in a chord - PENALTY if not in */
 
57
        private final int NOT_ESSENTIAL_INDEX = -3;
 
58
        
 
59
        /** Keep the Thread control */
 
60
        private static long runningProcess;
 
61
        
 
62
        // ------ attributes ------
 
63
        
 
64
        //protected ChordInfo info;
 
65
        private long processId;
 
66
        
 
67
        private ChordCreatorListener listener;
 
68
        
 
69
        /** the alteration List selectionIndex */
 
70
        private int alteration;
 
71
        
 
72
        private int chordIndex;
 
73
        
 
74
        /** essential notes for the chord (from ChordInfo) */
 
75
        private int[] requiredNotes;
 
76
        
 
77
        /** notes that expand the chord (add+-) */
 
78
        private int[] expandingNotes;
 
79
        
 
80
        /** is the fifth altered */
 
81
        private int add5 = 0;
 
82
        
 
83
        /** name of a chord */
 
84
        private String chordName = null;
 
85
        
 
86
        private int bassTonic; 
 
87
        
 
88
        private int chordTonic;
 
89
        
 
90
        /** current tunning */
 
91
        private int[] tuning;
 
92
        
 
93
        private ChordCreatorUtil(long processId,ChordCreatorListener listener){
 
94
                this.processId = processId;
 
95
                this.listener = listener;
 
96
        }
 
97
        
 
98
        public boolean isValidProcess(){
 
99
                return (this.processId == runningProcess);
 
100
        }
 
101
        
 
102
        public static long getNewProcess(){
 
103
                return (++ runningProcess);
 
104
        }
 
105
        
 
106
        public static void getChords(final ChordCreatorListener listener,
 
107
                                     final int[] tuning,
 
108
                                     final int chordIndex,
 
109
                                     final int alteration,
 
110
                                     final int plusMinus,
 
111
                                     final boolean add,
 
112
                                     final int add5,
 
113
                                     final int add9,
 
114
                                     final int add11,
 
115
                                     final int bassTonic,
 
116
                                     final int chordTonic,
 
117
                                     final boolean sharp){
 
118
                
 
119
                final ChordCreatorUtil chordCreator = new ChordCreatorUtil(getNewProcess(), listener );
 
120
                new Thread(new Runnable() {
 
121
                        public void run() {
 
122
                                chordCreator.getChords( tuning, chordIndex, alteration, plusMinus, add, add5, add9, add11, bassTonic, chordTonic, sharp);
 
123
                        }
 
124
                }).start();
 
125
        }
 
126
        
 
127
        protected void getChords(int[] tuning,
 
128
                                 int chordIndex,
 
129
                                 int alteration,
 
130
                                 int plusMinus,
 
131
                                 boolean add,
 
132
                                 int add5,
 
133
                                 int add9,
 
134
                                 int add11,
 
135
                                 int bassTonic,
 
136
                                 int chordTonic,
 
137
                                 boolean sharp) {
 
138
                
 
139
                if(!isValidProcess()){
 
140
                        return;
 
141
                }
 
142
                
 
143
                this.add5 = add5;
 
144
                
 
145
                this.tuning = tuning;
 
146
                
 
147
                this.chordIndex = chordIndex;
 
148
                
 
149
                this.chordTonic = chordTonic;
 
150
                
 
151
                this.bassTonic = bassTonic;
 
152
                
 
153
                this.alteration = alteration;
 
154
                
 
155
                this.chordName = new ChordNamingConvention().createChordName(this.chordTonic,
 
156
                                                                             this.chordIndex,
 
157
                                                                             this.alteration,
 
158
                                                                             plusMinus,
 
159
                                                                             add,
 
160
                                                                             add5,
 
161
                                                                             add9,
 
162
                                                                             add11,
 
163
                                                                             this.bassTonic,
 
164
                                                                             sharp);
 
165
                
 
166
                
 
167
                // find the notes that expand the chord
 
168
                if (this.alteration!=0) {
 
169
                        if (add) {
 
170
                                this.expandingNotes = new int[1];
 
171
                                this.expandingNotes[0]= getAddNote(this.alteration-1,plusMinus);
 
172
                        }
 
173
                        else { // not just add...
 
174
                                // 9+- = 7b !9(+-)    (index=1)
 
175
                                // 11+- = 7b !11(+-) 9(+-)  (index=2)
 
176
                                // 13+- = 7b !13(+-) 9(+-) 11(+-) (index=3)
 
177
                                this.expandingNotes = new int[1+this.alteration];
 
178
                                this.expandingNotes[0] = 11; //7b
 
179
                                this.expandingNotes[1] = getAddNote(this.alteration-1,plusMinus); //this.alteration+-
 
180
                                
 
181
                                // rest
 
182
                                for (int i=2; i<=this.alteration; i++)
 
183
                                        this.expandingNotes[i]=getAddNote(i-2, i==2 ? add9 : add11); // @2=add9+-, @3=add11+- tone
 
184
                        }
 
185
                        
 
186
                }
 
187
                else this.expandingNotes=new int[0];
 
188
                
 
189
                
 
190
                
 
191
                // Required notes
 
192
                //this.requiredNotes = ((ChordDatabase.ChordInfo)new ChordDatabase().getChords().get(chordIndex)).cloneRequireds();
 
193
                this.requiredNotes = ChordDatabase.get(chordIndex).cloneRequireds();
 
194
                //IT DON'T BUILD UNDER JRE1.4
 
195
                //this.requiredNotes = ((ChordDatabase.ChordInfo) ChordCreatorUtil.getChordData().getChords().get(chordIndex)).getRequiredNotes().clone();
 
196
                
 
197
                
 
198
                // adjust the subdominant if needed
 
199
                if (add5!=0) {
 
200
                        for (int i=0; i<this.requiredNotes.length; i++)
 
201
                                if (this.requiredNotes[i]==8) // alternate the subdominant
 
202
                                        this.requiredNotes[i]+=(add5==1 ? 1 : -1);
 
203
                }
 
204
                
 
205
                // first count different from -1
 
206
                int count = 0;
 
207
                for (int i=0; i<this.requiredNotes.length; i++) {
 
208
                        this.requiredNotes[i]=checkForOverlapping(this.requiredNotes[i]);
 
209
                        if (this.requiredNotes[i]!=-1)
 
210
                                count++;
 
211
                }
 
212
                // then fill in the new array
 
213
                int[] tempNotes = new int[count];
 
214
                count = 0;
 
215
                for (int i=0; i<this.requiredNotes.length; i++)
 
216
                        if (this.requiredNotes[i]!=-1) {
 
217
                                tempNotes[count]=this.requiredNotes[i];
 
218
                                count++;
 
219
                        }
 
220
                // and substitute them
 
221
                this.requiredNotes = tempNotes;
 
222
                
 
223
                //return getChords();
 
224
                if(isValidProcess()){
 
225
                        List chords = getChords();
 
226
                        if(chords != null && isValidProcess()){
 
227
                                this.listener.notifyChords(this, chords);
 
228
                        }
 
229
                }
 
230
        }
 
231
        
 
232
        /** We have to make sure that if required note is already inside
 
233
         * expanding notes array so we don't put it twice...
 
234
         */
 
235
        protected int checkForOverlapping(int checkIt) {
 
236
                for (int i=0; i<this.expandingNotes.length; i++)
 
237
                        if (this.expandingNotes[i]==checkIt)
 
238
                                return -1;
 
239
                return checkIt;
 
240
        }
 
241
        
 
242
        /**
 
243
         * 
 
244
         * Creates the chord combinations out of given data and then uses some kind
 
245
         * of
 
246
         * 
 
247
         * heuristics to check the most suitable formations.
 
248
         * 
 
249
         * @return the list of TGChord structures that are most suitable
 
250
         * 
 
251
         */
 
252
        private java.util.List getChords() {
 
253
                if(!isValidProcess()){
 
254
                        return null;
 
255
                }
 
256
                ArrayList potentialNotes = makePotentialNotes();
 
257
                
 
258
                ArrayList combinations = makeCombinations( potentialNotes);
 
259
                
 
260
                ArrayList priorities = determinePriority( combinations);
 
261
                
 
262
                ArrayList theBestOnes = takeBest( priorities);
 
263
                
 
264
                return createChords( theBestOnes);
 
265
        }
 
266
        
 
267
        /**
 
268
         * Creates the TGChord ArrayList out of StringValue's ArrayLists
 
269
         * 
 
270
         * @param Highest rated StringValues
 
271
         * @return TGChord collection
 
272
         */
 
273
        private ArrayList createChords(ArrayList top) {
 
274
                if(!isValidProcess()){
 
275
                        return null;
 
276
                }
 
277
                
 
278
                ArrayList chords = new ArrayList(top.size());
 
279
                
 
280
                Iterator it = top.iterator();
 
281
                
 
282
                while (it.hasNext()) {
 
283
                        TGChord chord = TuxGuitar.instance().getSongManager().getFactory()
 
284
                                        .newChord(this.tuning.length);
 
285
                        Iterator it2 = ((ArrayList) it.next()).iterator();
 
286
                        
 
287
                        while (it2.hasNext()) {
 
288
                                StringValue stringValue = (StringValue) it2.next();
 
289
                                int string = ((chord.getStrings().length - 1) - (stringValue.getString()));
 
290
                                int fret = stringValue.getFret();
 
291
                                chord.addFretValue(string, fret);
 
292
                                chord.setName(this.chordName);
 
293
                        }
 
294
                        
 
295
                        chords.add(chord);
 
296
                }
 
297
                return chords;
 
298
        }
 
299
        
 
300
        /**
 
301
         * 
 
302
         * If string/fret combination is needed for the chord formation, add it into
 
303
         * List
 
304
         * 
 
305
         * @return true if the note is needed for chord formation
 
306
         * 
 
307
         */
 
308
        private void find(int stringTone, int stringIndex, int fret,List stringList){
 
309
                if(!isValidProcess()){
 
310
                        return;
 
311
                }
 
312
                boolean bassAlreadyIn=false;
 
313
                // chord base notes
 
314
                for (int i = 0; i < this.requiredNotes.length; i++)
 
315
                        if ((stringTone + fret) % 12 == (this.chordTonic+this.requiredNotes[i] - 1) % 12) {
 
316
                                if (!bassAlreadyIn && (stringTone + fret) % 12 == this.bassTonic)
 
317
                                        bassAlreadyIn=true;
 
318
                                stringList.add(new StringValue(stringIndex, fret, i));
 
319
                                return;
 
320
                        }
 
321
                
 
322
                // alterations
 
323
                if (this.expandingNotes.length!=0) {
 
324
                        for (int i=0; i<this.expandingNotes.length; i++) {
 
325
                                if ((stringTone+fret)%12==(this.chordTonic+this.expandingNotes[i]-1)%12) {
 
326
                                        if (!bassAlreadyIn && (stringTone + fret) % 12 == this.bassTonic)
 
327
                                                bassAlreadyIn=true;
 
328
                                        stringList.add(new StringValue(stringIndex,fret,(i<2 ? this.ESSENTIAL_INDEX : this.NOT_ESSENTIAL_INDEX)));
 
329
                                }
 
330
                        }
 
331
                }
 
332
                
 
333
                // bass tone
 
334
                if (!bassAlreadyIn)
 
335
                        if ((stringTone + fret) % 12 == this.bassTonic) {
 
336
                                stringList.add(new StringValue(stringIndex, fret, this.BASS_INDEX));
 
337
                                return;
 
338
                        }
 
339
                
 
340
        }
 
341
        
 
342
        /**
 
343
         * Returns the wanted note for ADD chord
 
344
         * 
 
345
         * @param type
 
346
         *            0==add9; 1==add11; 2==add13; 
 
347
         * @param selectionIndex
 
348
         *            index of selected item in the List combo
 
349
         * @return wanted note, or -1 if nothing was selected
 
350
         * 
 
351
         */
 
352
        private int getAddNote(int type, int selectionIndex) {
 
353
                
 
354
                int wantedNote = 0;
 
355
                
 
356
                switch (type) {
 
357
                        case 0:
 
358
                                wantedNote = 3; // add9
 
359
                                break;
 
360
                        case 1:
 
361
                                wantedNote = 6; // add11
 
362
                                break;
 
363
                        case 2:
 
364
                                wantedNote = 10; // add13
 
365
                                break;
 
366
                }
 
367
                
 
368
                switch (selectionIndex) {
 
369
                        case 1:
 
370
                                wantedNote++;
 
371
                                break;
 
372
                        case 2:
 
373
                                wantedNote--;
 
374
                                break;
 
375
                        default:
 
376
                                break;
 
377
                }
 
378
                
 
379
                return wantedNote;
 
380
        }
 
381
        
 
382
        private ArrayList makePotentialNotes(){
 
383
                if(!isValidProcess()){
 
384
                        return null;
 
385
                }
 
386
                ArrayList potentialNotes = new ArrayList(this.tuning.length);
 
387
                
 
388
                for (int string = 0; string < this.tuning.length; string++) {
 
389
                        
 
390
                        ArrayList currentStringList = new ArrayList(10);
 
391
                        
 
392
                        // search all the frets
 
393
                        
 
394
                        if (ChordSettings.instance().getFindChordsMin()>0 && ChordSettings.instance().isEmptyStringChords())
 
395
                                find(this.tuning[string], string, 0, currentStringList); // if it's open chord but wanted to search from different minimal fret
 
396
                                
 
397
                        
 
398
                        for (int fret = ChordSettings.instance().getFindChordsMin(); fret <= ChordSettings.instance().getFindChordsMax(); fret++) {
 
399
                                // put in all the needed notes
 
400
                                find(this.tuning[string], string, fret, currentStringList);
 
401
                        }
 
402
                        
 
403
                        potentialNotes.add(currentStringList);
 
404
                        
 
405
                }
 
406
                return potentialNotes;
 
407
        }
 
408
        
 
409
        /**
 
410
         * 
 
411
         * Makes the all-possible combinations of found notes that can be reached by
 
412
         * fingers
 
413
         * 
 
414
         * @param potentialNotes
 
415
         *            list consisted of found notes for each string
 
416
         * 
 
417
         * @return list of list of StringValues, with tones that can form a chord
 
418
         * 
 
419
         */
 
420
        private ArrayList makeCombinations(ArrayList potentialNotes) {
 
421
                if(!isValidProcess()){
 
422
                        return null;
 
423
                }
 
424
                
 
425
                // COMBINATIONS of strings used in a chord
 
426
                ArrayList stringCombination = new ArrayList(60);
 
427
                ArrayList lastLevelCombination = null;
 
428
                
 
429
                for (int i = 0; i < this.tuning.length - 1; i++)
 
430
                {
 
431
                        lastLevelCombination = makeStringCombination(lastLevelCombination);
 
432
                        
 
433
                        // lastLevelCombination after 3rd round: [[0, 1, 2, 3], [0, 1, 2,
 
434
                        // 4], [0, 1, 3, 4], [0, 2, 3, 4], [1, 2, 3, 4], [0, 1, 2, 5], [0,
 
435
                        // 1, 3, 5], [0, 2, 3, 5], [1, 2, 3, 5], [0, 1, 4, 5], [0, 2, 4, 5],
 
436
                        // [1, 2, 4, 5], [0, 3, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]]
 
437
                        
 
438
                        stringCombination.addAll(lastLevelCombination);
 
439
                }
 
440
                
 
441
                ArrayList combinations = new ArrayList(800);
 
442
                
 
443
                // --- combine the StringValues according to strings combination
 
444
                // ----------------------=======
 
445
                
 
446
                Iterator iterator = stringCombination.iterator();
 
447
                
 
448
                while (iterator.hasNext()) { // go through all string combinations list
 
449
                        // take a string combinations
 
450
                        ArrayList currentStringCombination = (ArrayList) iterator.next();
 
451
                        lastLevelCombination = null;
 
452
                        
 
453
                        // go through all the strings in one combination
 
454
                        for (int level = 0; level < currentStringCombination.size(); level++) { 
 
455
                                
 
456
                                // take the string index
 
457
                                int currentString = ((Integer) currentStringCombination.get(level)).intValue();
 
458
                                
 
459
                                // take all the potential notes from currentString and combine
 
460
                                // them with potential notes from other strings
 
461
                                
 
462
                                lastLevelCombination = makeStringValueCombination(lastLevelCombination,(ArrayList)potentialNotes.get(currentString));
 
463
                                
 
464
                                // the structure of combinations is AL { AL(StringValue,SV,SV),
 
465
                                // AL(SV), AL(SV,SV),AL(SV,SV,SV,SV,SV,SV) }
 
466
                                
 
467
                        }
 
468
                        
 
469
                        if(lastLevelCombination != null){
 
470
                                combinations.addAll(lastLevelCombination);
 
471
                        }
 
472
                }
 
473
                
 
474
                return combinations;
 
475
        }
 
476
        
 
477
        /**
 
478
         * Makes a combination of string indices
 
479
         * 
 
480
         * @param lastLevelCombination
 
481
         *            structure to be expanded by current level
 
482
         * 
 
483
         * @return structure of stringCombination is AL { AL(0), AL(0,1),
 
484
         *         AL(0,2),AL(0,1,3,4),AL(0,1,2,3,4,5) }
 
485
         */
 
486
        private ArrayList makeStringCombination(ArrayList lastLevelCombinationRef){
 
487
                if(!isValidProcess()){
 
488
                        return null;
 
489
                }
 
490
                
 
491
                List lastLevelCombination = lastLevelCombinationRef;
 
492
                
 
493
                if (lastLevelCombination == null) {
 
494
                        // first combination is AL { AL(0), AL(1), AL(2), AL(3), AL(4),
 
495
                        // ...AL(tuning.length) }
 
496
                        lastLevelCombination = new ArrayList();
 
497
                        
 
498
                        for (int i = 0; i < this.tuning.length; i++) {
 
499
                                lastLevelCombination.add(new ArrayList());
 
500
                                ((ArrayList) lastLevelCombination.get(i)).add(new Integer(i));
 
501
                        }
 
502
                }
 
503
                
 
504
                ArrayList thisLevelCombination = new ArrayList();
 
505
                for (int current = 1; current < this.tuning.length; current++)
 
506
                {
 
507
                        Iterator it = lastLevelCombination.iterator();
 
508
                        
 
509
                        while (it.hasNext()) {
 
510
                                ArrayList combination = (ArrayList) it.next();
 
511
                                Integer currentInteger = new Integer(current);
 
512
                                if (((Integer) combination.get(combination.size() - 1))
 
513
                                                .intValue() < current
 
514
                                                && !combination.contains(currentInteger)) {
 
515
                                        
 
516
                                        // check if the string is already in combination
 
517
                                        ArrayList newCombination = (ArrayList) combination.clone();
 
518
                                        newCombination.add(currentInteger);
 
519
                                        thisLevelCombination.add(newCombination);
 
520
                                }
 
521
                                
 
522
                        }
 
523
                        
 
524
                }
 
525
                
 
526
                return thisLevelCombination;
 
527
                
 
528
        }
 
529
        
 
530
        /**
 
531
         * Makes a combination of notes by multiplying last combination and current
 
532
         * note arrays
 
533
         * 
 
534
         * 
 
535
         * 
 
536
         * @param lastLevelCombination
 
537
         *            structure to be expanded by current level
 
538
         * 
 
539
         * @param notes
 
540
         *            notes that can be considered into making a chord
 
541
         * 
 
542
         * @return structure of StringValue combinations : AL {
 
543
         *         AL(StringValue,SV,SV), AL(SV), AL(SV,SV),AL(SV,SV,SV,SV,SV,SV) }
 
544
         * 
 
545
         */
 
546
        private ArrayList makeStringValueCombination(ArrayList lastLevelCombination, ArrayList notes) {
 
547
                if(!isValidProcess()){
 
548
                        return null;
 
549
                }
 
550
                ArrayList thisLevelCombination = null;
 
551
                
 
552
                if (lastLevelCombination == null) { // initial combination
 
553
                        
 
554
                        thisLevelCombination = new ArrayList(notes.size());
 
555
                        
 
556
                        for (int i = 0; i < notes.size(); i++) {
 
557
                                
 
558
                                thisLevelCombination.add(new ArrayList(6));
 
559
                                
 
560
                                ((ArrayList) thisLevelCombination.get(i)).add(notes.get(i));
 
561
                                
 
562
                        }
 
563
                        
 
564
                        // first combination is AL { AL(firstOne), AL(anotherFret) }
 
565
                        
 
566
                }
 
567
                
 
568
                else {
 
569
                        
 
570
                        thisLevelCombination = new ArrayList();
 
571
                        
 
572
                        for (int i = 0; i < notes.size(); i++)
 
573
                                for (int j = 0; j < lastLevelCombination.size(); j++) { // cartesian multiplication
 
574
                                        ArrayList currentCombination = (ArrayList) ((ArrayList) lastLevelCombination.get(j)).clone();
 
575
                                        currentCombination.add(notes.get(i));
 
576
                                        
 
577
                                        // if the distance maximum between the existing frets
 
578
                                        // is less than wanted, add it into potential list
 
579
                                        
 
580
                                        if (checkCombination(currentCombination))
 
581
                                                thisLevelCombination.add(currentCombination);
 
582
                                        
 
583
                                }
 
584
                }
 
585
                
 
586
                return thisLevelCombination;
 
587
        }
 
588
        
 
589
        /**
 
590
         * Checks if the combination can be reached by fingers. It is reachable
 
591
         * 
 
592
         * if the distance between lowest and highest fret is less than
 
593
         * 
 
594
         * <i>ChordCreatorUtil.MAX_FRET_SPAN</i>.
 
595
         * 
 
596
         * Also note that this method eliminates or includes the chords with empty
 
597
         * strings,
 
598
         * 
 
599
         * which is controlled with <i>boolean ChordCreatorUtil.EMPTY_STRING_CHORDS</i>
 
600
         * 
 
601
         * @param combination
 
602
         *            current combination to be examined
 
603
         * 
 
604
         * @return true if it can be reached
 
605
         * 
 
606
         */
 
607
        private boolean checkCombination(ArrayList combination) {
 
608
                
 
609
                Iterator it = combination.iterator();
 
610
                int maxLeft, maxRight;
 
611
                
 
612
                maxLeft = maxRight = ((StringValue) combination.get(0)).getFret();
 
613
                
 
614
                while (it.hasNext()) {
 
615
                        
 
616
                        int fret = ((StringValue) it.next()).getFret();
 
617
                        
 
618
                        //chords with empty-string are welcome
 
619
                        if (fret != 0 || !ChordSettings.instance().isEmptyStringChords()) {
 
620
                                
 
621
                                if (fret < maxLeft)
 
622
                                        maxLeft = fret;
 
623
                                
 
624
                                if (fret > maxRight)
 
625
                                        maxRight = fret;
 
626
                                
 
627
                        }
 
628
                        
 
629
                }
 
630
                
 
631
                if (Math.abs(maxLeft - maxRight) >= MAX_FRET_SPAN)
 
632
                        
 
633
                        return false;
 
634
                
 
635
                return true;
 
636
                
 
637
        }
 
638
        
 
639
        /**
 
640
         * orders the StringValue ArrayList by their priority, calculated here
 
641
         * 
 
642
         * for every single chord combination.<br>
 
643
         * 
 
644
         * Priority is higher if:<br>
 
645
         *  - tone combination has all notes required for the chord basis<br>
 
646
         *  - has good chord semantics uses many basic tones, and all necessary
 
647
         * tones in their place<br>
 
648
         *  - tone combination has all subsequent strings (no string skipping)<br>
 
649
         *  - has a chord bass tone as lowest tone<br>
 
650
         *  - uses more strings<br>
 
651
         *  - uses good fingering positions<br>
 
652
         * 
 
653
         * @param allCombinations
 
654
         *            all the StringValue combinations that make some sense
 
655
         * 
 
656
         * @return Treemap of the StringValue ArrayLists, in which the key is
 
657
         * 
 
658
         * <i>float priority</i>.
 
659
         * 
 
660
         */
 
661
        private ArrayList determinePriority(ArrayList allCombinations) {
 
662
                if(!isValidProcess()){
 
663
                        return null;
 
664
                }
 
665
                ArrayList ordered = new ArrayList();
 
666
                
 
667
                Iterator it = allCombinations.iterator();
 
668
                
 
669
                while (it.hasNext() && isValidProcess()) {
 
670
                        
 
671
                        float priority = 0;
 
672
                        
 
673
                        ArrayList stringValueCombination = (ArrayList) it.next();
 
674
                        
 
675
                        // tone combination has all notes required for the chord basis
 
676
                        
 
677
                        priority += combinationHasAllRequiredNotes(stringValueCombination);
 
678
                        
 
679
                        // uses good chord semantics
 
680
                        
 
681
                        priority += combinationChordSemantics(stringValueCombination);
 
682
                        
 
683
                        // tone combination has all subsequent strings (no string skipping)
 
684
                        
 
685
                        priority += combinationHasSubsequentStrings(stringValueCombination);
 
686
                        
 
687
                        // has a chord bass tone as lowest tone
 
688
                        
 
689
                        priority += combinationBassInBass(stringValueCombination);
 
690
                        
 
691
                        // uses many strings
 
692
                        // 4 and less strings will be more praised in case of negative grade
 
693
                        // 4 and more strings will be more praised in case of positive grade 
 
694
                        priority += ChordSettings.instance().getManyStringsGrade() / 3
 
695
                                * (stringValueCombination.size()-this.tuning.length / 
 
696
                                                (ChordSettings.instance().getManyStringsGrade()>0 ? 2 : 1.2) );
 
697
                        
 
698
                        // uses good fingering positions
 
699
                        
 
700
                        priority += combinationHasGoodFingering(stringValueCombination);
 
701
                        
 
702
                        // System.out.println("OVERALL:
 
703
                        // "+priority+"----------------------------");
 
704
                        
 
705
                        PriorityItem item = new PriorityItem();
 
706
                        
 
707
                        item.priority = priority;
 
708
                        
 
709
                        item.stringValues = stringValueCombination;
 
710
                        
 
711
                        ordered.add(item);
 
712
                        
 
713
                }
 
714
                
 
715
                return ordered;
 
716
                
 
717
        }
 
718
        
 
719
        /**
 
720
         * 
 
721
         * Takes the StringValue ArrayLists that has the best priority rating
 
722
         * 
 
723
         */
 
724
        private ArrayList takeBest(ArrayList priorityItems) {
 
725
                if(!isValidProcess()){
 
726
                        return null;
 
727
                }
 
728
                
 
729
                int maximum = ChordSettings.instance().getChordsToDisplay();
 
730
                
 
731
                ArrayList bestOnes = new ArrayList(maximum);
 
732
                
 
733
                Collections.sort(priorityItems, new PriorityComparator());
 
734
                for(int i = 0; i < priorityItems.size() && isValidProcess(); i ++){
 
735
                        PriorityItem item = (PriorityItem)priorityItems.get(i);
 
736
                        if (!checkIfSubset(item.stringValues, bestOnes) ){
 
737
                                bestOnes.add(item.stringValues);
 
738
                                
 
739
                                if( bestOnes.size() >= maximum ){
 
740
                                        break;
 
741
                                }
 
742
                        }
 
743
                }
 
744
                
 
745
                return bestOnes;
 
746
                
 
747
        }
 
748
        
 
749
        /** adds points if the combination has all the notes in the basis of chord */
 
750
        private float combinationHasAllRequiredNotes(ArrayList stringValueCombination) {
 
751
                if(!isValidProcess()){
 
752
                        return 0;
 
753
                }
 
754
                Iterator it = stringValueCombination.iterator();
 
755
                int[] values = new int[this.requiredNotes.length];
 
756
                int currentIndex = 0;
 
757
                
 
758
                while (it.hasNext()) {
 
759
                        StringValue sv = (StringValue) it.next();
 
760
                        
 
761
                        if (sv.requiredNoteIndex >= 0) { // only basis tones
 
762
                                boolean insert = true;
 
763
                                
 
764
                                for (int i = 0; i < currentIndex; i++)
 
765
                                        if (values[i] == sv.requiredNoteIndex + 1)
 
766
                                                insert = false;
 
767
                                
 
768
                                // sv.requiredNoteIndex+1, because we have index 0 and we don't
 
769
                                // want it inside
 
770
                                
 
771
                                if (insert) {
 
772
                                        values[currentIndex] = sv.requiredNoteIndex + 1;
 
773
                                        currentIndex++;
 
774
                                }
 
775
                                
 
776
                        }
 
777
                }
 
778
                
 
779
                if (currentIndex == this.requiredNotes.length) {
 
780
                        return ChordSettings.instance().getRequiredBasicsGrade();
 
781
                }
 
782
                
 
783
                if (currentIndex == this.requiredNotes.length - 1) {
 
784
                        
 
785
                        boolean existsSubdominant = false;
 
786
                        
 
787
                        Iterator it2 = stringValueCombination.iterator();
 
788
                        while (it2.hasNext()) {
 
789
                                StringValue current = (StringValue)it2.next();
 
790
                                if ((this.tuning[current.string] + current.fret) % 12 == (this.chordTonic + 7) %12)
 
791
                                        existsSubdominant = true;
 
792
                        }
 
793
                        
 
794
                        if (!existsSubdominant && currentIndex == this.requiredNotes.length-1) {
 
795
                                // if not riff. "sus" chord, or chord with altered fifth allow chord without JUST subdominant (fifth) with small penalty 
 
796
                                
 
797
                                //if ( !((ChordInfo)new ChordDatabase().getChords().get(this.chordIndex)).getName().contains("sus") && this.requiredNotes.length!=2 && this.add5==0) {
 
798
                                //String.contains(String) is not available at JRE1.4
 
799
                                //Replaced by "String.indexOf(String) >= 0"
 
800
                                if ( ChordDatabase.get(this.chordIndex).getName().indexOf("sus") >= 0 && this.requiredNotes.length != 2 && this.add5 == 0) {
 
801
                                        return ( ChordSettings.instance().getRequiredBasicsGrade() * 4 / 5 );
 
802
                                }
 
803
                        }
 
804
                        
 
805
                }
 
806
                
 
807
                // required notes count should decrease the penalty
 
808
                int noteCount = (this.alteration == 0 ? 0 : 1+ this.alteration)+currentIndex+ (this.bassTonic == this.chordTonic ? 0 : 1);
 
809
                
 
810
                // sometimes, when noteCount is bigger then tunning length, this pennalty will become positive, which may help
 
811
                return -ChordSettings.instance().getRequiredBasicsGrade()
 
812
                                * (this.tuning.length - noteCount) / this.tuning.length * 2;
 
813
                
 
814
        }
 
815
        
 
816
        /** adds points if the combination has strings in a row */
 
817
        private float combinationHasSubsequentStrings(ArrayList stringValueCombination) {
 
818
                if(!isValidProcess()){
 
819
                        return 0;
 
820
                }
 
821
                boolean stumbled = false, noMore = false, penalty = false;
 
822
                
 
823
                for (int i = 0; i < this.tuning.length; i++) {
 
824
                        boolean found = false;
 
825
                        Iterator it = stringValueCombination.iterator();
 
826
                        while (it.hasNext())
 
827
                                if (((StringValue) it.next()).string == i)
 
828
                                        found = true;
 
829
                        if (found) {
 
830
                                if (!stumbled)
 
831
                                        stumbled = true;
 
832
                                if (noMore)
 
833
                                        penalty = true;
 
834
                                if (penalty) // penalty for skipped strings
 
835
                                        return -ChordSettings.instance().getSubsequentGrade();
 
836
                        }
 
837
                        else
 
838
                        if (stumbled)
 
839
                                noMore = true;
 
840
                }
 
841
                
 
842
                if (penalty)
 
843
                        return 0.0f;
 
844
                
 
845
                return ChordSettings.instance().getSubsequentGrade();
 
846
        }
 
847
        
 
848
        /** checks if the bass tone is the lowest tone in chord */
 
849
        private float combinationBassInBass(ArrayList stringValueCombination) {
 
850
                if(!isValidProcess()){
 
851
                        return 0;
 
852
                }
 
853
                for (int i = 0; i < this.tuning.length; i++) {
 
854
                        
 
855
                        Iterator it = stringValueCombination.iterator();
 
856
                        
 
857
                        while (it.hasNext()) {
 
858
                                StringValue sv = (StringValue) it.next();
 
859
                                
 
860
                                if (sv.string == i) { // stumbled upon lowest tone
 
861
                                        if ( (this.tuning[sv.string]+sv.fret) % 12 == this.bassTonic  )
 
862
                                          return ChordSettings.instance().getBassGrade();
 
863
                                        // else
 
864
                                        return -ChordSettings.instance().getBassGrade();
 
865
                                }
 
866
                        }
 
867
                        
 
868
                }
 
869
                
 
870
                return 0;
 
871
        }
 
872
        
 
873
        /**
 
874
         * grades the fingering in a chord.
 
875
         * 
 
876
         * fingering is good if:<br>
 
877
         *  - uses as little as possible fret positions<br>
 
878
         *  - uses less than 3 fret positions<br>
 
879
         *  - distributes good among fingers<br>
 
880
         *  - can be placed capo <br>
 
881
         * 
 
882
         */
 
883
        private float combinationHasGoodFingering(ArrayList stringValueCombination) {
 
884
                if(!isValidProcess()){
 
885
                        return 0;
 
886
                }
 
887
                // init: copy into simple array
 
888
                float finalGrade = 0;
 
889
                int[] positions = new int[this.tuning.length];
 
890
                for (int i = 0; i < this.tuning.length; i++)
 
891
                        positions[i] = -1;
 
892
                {
 
893
                        Iterator it = stringValueCombination.iterator();
 
894
                        
 
895
                        while (it.hasNext()) {
 
896
                                StringValue sv = (StringValue) it.next();
 
897
                                positions[sv.string] = sv.fret;
 
898
                        }
 
899
                }
 
900
                // algorithm
 
901
                
 
902
                // distance between fingers
 
903
                int min = ChordSettings.instance().getFindChordsMax()+2, max = 0, maxCount=0;
 
904
                boolean openChord = false, zeroString = false;
 
905
                
 
906
                for (int i = 0; i < this.tuning.length; i++) {
 
907
                        
 
908
                        openChord|= ChordSettings.instance().isEmptyStringChords() && positions[i] == 0;
 
909
                        zeroString |= positions[i]==0;
 
910
                        
 
911
                        if (positions[i] < min && positions[i] != 0 && positions[i]!=-1)
 
912
                                min = positions[i];
 
913
                        
 
914
                        if (positions[i] > max) {
 
915
                                max = positions[i];
 
916
                                maxCount=1;
 
917
                        }
 
918
                        else 
 
919
                                if (positions[i]==max) 
 
920
                                        maxCount++;
 
921
                        
 
922
                }
 
923
                
 
924
                // finger as capo
 
925
                
 
926
                int count = 0;
 
927
                
 
928
                for (int i = 0; i < this.tuning.length; i++)
 
929
                        if (positions[i] == min)
 
930
                                count++;
 
931
                
 
932
                if (!openChord) { 
 
933
                        if (zeroString)
 
934
                                finalGrade += ChordSettings.instance().getFingeringGrade()/8;
 
935
                        else
 
936
                                if (count >= 2)
 
937
                                        finalGrade += ChordSettings.instance().getFingeringGrade()/8;
 
938
                }
 
939
                else
 
940
                        if (openChord)
 
941
                                finalGrade += ChordSettings.instance().getFingeringGrade()/8;
 
942
                
 
943
                // position distance: 1-2 nice 3 good 4 bad 5 disaster
 
944
                float distanceGrade;
 
945
                
 
946
                switch(Math.abs(max-min)) {
 
947
                        case 0 : distanceGrade=ChordSettings.instance().getFingeringGrade()/5;
 
948
                                        break;
 
949
                        case 1 : distanceGrade=ChordSettings.instance().getFingeringGrade()/(5+maxCount);
 
950
                                        break;
 
951
                        case 2 : distanceGrade=ChordSettings.instance().getFingeringGrade()/(6+maxCount);
 
952
                                         if (min<5) distanceGrade*=0.9;
 
953
                                        break;
 
954
                        case 3 : distanceGrade=-ChordSettings.instance().getFingeringGrade()/10*maxCount;
 
955
                                        // I emphasize the penalty if big difference is on some 
 
956
                                        // lower frets (it is greater distance then)
 
957
                                        if (min<5) distanceGrade*=1.3;
 
958
                                        break;
 
959
                        case 4 : distanceGrade=-ChordSettings.instance().getFingeringGrade()/4*maxCount;
 
960
                                        if (min<=5) distanceGrade*=1.8;
 
961
                                        break;
 
962
                        default : distanceGrade=-ChordSettings.instance().getFingeringGrade()*maxCount;
 
963
                                        break;
 
964
                }
 
965
                finalGrade += distanceGrade;
 
966
                
 
967
                // ============== finger position abstraction ==================
 
968
                // TODO: what to do with e.g. chord -35556 (C7)
 
969
                // ... it can be held with capo on 5th fret, but very hard :)
 
970
                // ... This is the same as with "capo after", I didn't consider that (e.g. chord -35555)
 
971
                ArrayList[] fingers={new ArrayList(2),new ArrayList(2),new ArrayList(2),new ArrayList(2)};
 
972
                // TODO: still no thumb, sorry :)
 
973
                
 
974
                // STRUCTURE: ArrayList consists of Integers - first is fret
 
975
                //                                           - others are strings
 
976
/*              
 
977
                for (int i=0; i<this.tuning.length; i++)
 
978
                        System.out.print(" "+positions[i]);
 
979
                System.out.println("");
 
980
*/
 
981
                
 
982
                // if chord is open, then we can have capo only in strings before open string
 
983
                int lastZeroIndex = 0;
 
984
                
 
985
                if (zeroString)
 
986
                        for (int i=0; i<positions.length; i++)
 
987
                                if (positions[i]==0) lastZeroIndex=i;
 
988
                
 
989
                // open or not not open chord,
 
990
                // index finger is always on lowest fret possible
 
991
                fingers[0].add(new Integer(min));
 
992
                
 
993
                for (int i=lastZeroIndex; i<positions.length; i++)
 
994
                                if (positions[i]==min) {
 
995
                                        fingers[0].add(new Integer(i));
 
996
                                        positions[i]=-1;
 
997
                                }
 
998
                
 
999
                // other fingers
 
1000
                // if not zero-fret, occupy fingers respectivly
 
1001
                int finger=1;
 
1002
                for (int i=0; i<positions.length; i++) {
 
1003
                        if (positions[i]!=0 && positions[i]!=-1) {
 
1004
                                if (finger<4) {
 
1005
                                        fingers[finger].add(new Integer(positions[i]));
 
1006
                                        fingers[finger].add(new Integer(i));
 
1007
                                        positions[i]=-1;
 
1008
                                }
 
1009
                                finger++;
 
1010
                        }
 
1011
                }
 
1012
                
 
1013
/*              System.out.println("Positions:");
 
1014
                for (int i=0; i<4; i++) {
 
1015
                        if (fingers[i].size()>1)
 
1016
                                System.out.print("G"+(i+1)+"R"+((Integer)fingers[i].get(0)).intValue()+"S"+((Integer)fingers[i].get(1)).intValue()+" ");
 
1017
                }
 
1018
*/              
 
1019
                
 
1020
                if (finger>4) 
 
1021
                        finalGrade-=ChordSettings.instance().getFingeringGrade();
 
1022
                 else
 
1023
                        finalGrade+=ChordSettings.instance().getFingeringGrade()*0.1*(15-2*finger);
 
1024
                
 
1025
                // TODO: maybe to put each finger's distance from the minimum
 
1026
                return finalGrade;
 
1027
                
 
1028
        }
 
1029
        
 
1030
        /**
 
1031
         * grades the chord semantics, based on theory.
 
1032
         * 
 
1033
         * Tone semantics is good if:<br>
 
1034
         *  - there appear tones from chord basis or bass tone<br>
 
1035
         *  - there appear alteration tones on their specific places<br><br>
 
1036
         *
 
1037
         * Algorithm:<br>
 
1038
         *  - search for chord tonic. If some note is found before (and it's not bass) do penalty<br>
 
1039
         *  - make penalty if the bass tone is not in bass<br>
 
1040
         *  - check if all the expanding notes are here. If some are not, do penalty<br>
 
1041
         *  - if expanding note isn't higher than tonic octave, then priority should be less<br>
 
1042
         *  - If there are not some with NON_ESSENTIAL_INDEX are not here, penalty should be less<br>
 
1043
         */
 
1044
        private float combinationChordSemantics(ArrayList stringValueCombination) {
 
1045
                if(!isValidProcess()){
 
1046
                        return 0;
 
1047
                }
 
1048
                float finalGrade = 0;
 
1049
                
 
1050
                int foundTonic = -1;
 
1051
                
 
1052
                int[] foundExpanding = new int[this.expandingNotes.length];
 
1053
                int stringDepth=0;
 
1054
                
 
1055
                for (int string = 0; string < this.tuning.length; string++) {
 
1056
                        // we have to go string-by-string because of the octave
 
1057
                        Iterator it = stringValueCombination.iterator();
 
1058
                        StringValue current = null;
 
1059
                        boolean found=false;
 
1060
                        
 
1061
                        while (it.hasNext() && !found) {
 
1062
                                StringValue sv = (StringValue) it.next();
 
1063
                                if (sv.string == string &&!found && sv.fret!=-1) { // stumbled upon next string
 
1064
                                        current = sv;
 
1065
                                        found=true;
 
1066
                                        stringDepth++;
 
1067
                                }
 
1068
                        }
 
1069
                        
 
1070
                        // grade algorithms----
 
1071
                        if (current != null) {
 
1072
                                // search for tonic
 
1073
                                if (foundTonic==-1 && current.requiredNoteIndex==0)
 
1074
                                        foundTonic=this.tuning[current.string]+current.fret;
 
1075
                                
 
1076
                                // specific bass not in bass?
 
1077
                                if (stringDepth>1) {
 
1078
                                        if (current.requiredNoteIndex==this.BASS_INDEX)  
 
1079
                                                finalGrade -= ChordSettings.instance().getGoodChordSemanticsGrade();
 
1080
                                        
 
1081
                                        if (current.requiredNoteIndex<0) { // expanding tones
 
1082
                                                // expanding tone found before the tonic
 
1083
                                                if (foundTonic==-1)
 
1084
                                                        finalGrade -= ChordSettings.instance().getGoodChordSemanticsGrade()/2;
 
1085
                                                else {
 
1086
                                                        // if expanding note isn't higher than tonic's octave
 
1087
                                                        if (foundTonic+11 > this.tuning[current.string]+current.fret)
 
1088
                                                                finalGrade -= ChordSettings.instance().getGoodChordSemanticsGrade()/3;
 
1089
                                                }
 
1090
                                                
 
1091
                                                // search for distinct expanding notes
 
1092
                                                for (int i=0; i<this.expandingNotes.length; i++)
 
1093
                                                        if ((this.tuning[string]+current.fret)%12==(this.chordTonic+this.expandingNotes[i]-1)%12)
 
1094
                                                                if (foundExpanding[i]==0)
 
1095
                                                                        foundExpanding[i]=current.requiredNoteIndex;
 
1096
                                                
 
1097
                                        }
 
1098
                                }
 
1099
                        }
 
1100
                }
 
1101
                
 
1102
                // penalties for not founding an expanding note
 
1103
                if (this.alteration!=0) {
 
1104
                        int essentials=0, nonEssentials=0;
 
1105
                        for (int i=0; i<foundExpanding.length; i++) {
 
1106
                                if (foundExpanding[i]==this.ESSENTIAL_INDEX)
 
1107
                                        essentials++;
 
1108
                                else
 
1109
                                        if (foundExpanding[i]!=0)
 
1110
                                                nonEssentials++;
 
1111
                        }
 
1112
                        
 
1113
                        if (essentials+nonEssentials==this.expandingNotes.length)
 
1114
                                finalGrade+=ChordSettings.instance().getGoodChordSemanticsGrade();
 
1115
                        else {
 
1116
                                if (essentials==2) // if all essentials are there, it's good enough
 
1117
                                        finalGrade+=ChordSettings.instance().getGoodChordSemanticsGrade()/2;
 
1118
                                
 
1119
                                // but if some are missing, that's BAD:
 
1120
                                else {
 
1121
                                        finalGrade+= (essentials+nonEssentials-this.expandingNotes.length)*ChordSettings.instance().getGoodChordSemanticsGrade();
 
1122
                                        // half of the penalty for non-essential notes
 
1123
                                        finalGrade+= nonEssentials*ChordSettings.instance().getGoodChordSemanticsGrade()/2;
 
1124
                                }
 
1125
                        }
 
1126
                }
 
1127
                
 
1128
                return finalGrade;
 
1129
                
 
1130
        }
 
1131
        
 
1132
        /**
 
1133
         *  If current StringValue is a subset or superset of already better ranked
 
1134
         *  chords, it shouldn't be put inside, because it is duplicate.
 
1135
         *  @param stringValues current StringValue to be examined
 
1136
         *  @param betterOnes ArrayList of already stored StringList chords
 
1137
         *  @return true if it is duplicate, false if it is unique
 
1138
         */
 
1139
        private boolean checkIfSubset(List stringValues, List betterOnes) {
 
1140
                if(!isValidProcess()){
 
1141
                        return false;
 
1142
                }
 
1143
                Iterator it = betterOnes.iterator();
 
1144
                while (it.hasNext()) {
 
1145
                        List currentStringValue = (List)it.next();
 
1146
                        boolean foundDifferentFret = false;
 
1147
                        // repeat until gone through all strings, or found something different
 
1148
                        for (int i=0; i<currentStringValue.size(); i++) {
 
1149
                                int currentString = ((ChordCreatorUtil.StringValue)currentStringValue.get(i)).string ;
 
1150
                                // search for the same string - if not found do nothing
 
1151
                                for (int j=0; j<stringValues.size(); j++)
 
1152
                                if ( ((ChordCreatorUtil.StringValue)stringValues.get(j)).string == currentString) {
 
1153
                                        // if the frets on the same string differ, then chords are not subset/superset of each other
 
1154
                                        if (((ChordCreatorUtil.StringValue)stringValues.get(j)).fret != ((ChordCreatorUtil.StringValue)currentStringValue.get(i)).fret)
 
1155
                                                foundDifferentFret=true;
 
1156
                                }
 
1157
                                
 
1158
                        }
 
1159
                        if (!foundDifferentFret)// nothing is different
 
1160
                                return true;
 
1161
                }
 
1162
                
 
1163
                return false;
 
1164
        }
 
1165
        
 
1166
        /**
 
1167
         * contains information about the note: string, fret and tone function in a
 
1168
         * chord
 
1169
         * 
 
1170
         * @author julian
 
1171
         * 
 
1172
         */
 
1173
        
 
1174
        private class StringValue {
 
1175
                
 
1176
                protected int string;
 
1177
                protected int fret;
 
1178
                protected int requiredNoteIndex;
 
1179
                
 
1180
                public StringValue(int string, int fret, int requiredNoteIndex) {
 
1181
                        this.string = string;
 
1182
                        this.fret = fret;
 
1183
                        this.requiredNoteIndex = requiredNoteIndex;
 
1184
                        
 
1185
                }
 
1186
                
 
1187
                public int getString() {
 
1188
                        return this.string;
 
1189
                }
 
1190
                
 
1191
                public void setString(int string) {
 
1192
                        this.string = string;
 
1193
                }
 
1194
                
 
1195
                public int getFret() {
 
1196
                        return this.fret;
 
1197
                }
 
1198
                
 
1199
                public void setFret(int fret) {
 
1200
                        this.fret = fret;
 
1201
                }
 
1202
                
 
1203
                public int getRequiredNoteIndex() {
 
1204
                        return this.requiredNoteIndex;
 
1205
                }
 
1206
                
 
1207
                public void setRequiredNoteIndex(int requiredNoteIndex) {
 
1208
                        this.requiredNoteIndex = requiredNoteIndex;
 
1209
                }
 
1210
                
 
1211
        }
 
1212
        
 
1213
        /** used just to sort StringValue ArrayLists by priorities */
 
1214
        protected class PriorityItem {
 
1215
                
 
1216
                ArrayList stringValues;
 
1217
                float priority;
 
1218
                
 
1219
        }
 
1220
        
 
1221
        /** used to sort the array */
 
1222
        protected class PriorityComparator implements Comparator {
 
1223
                
 
1224
                public int compare(Object o1, Object o2) {
 
1225
                        return Math.round(((PriorityItem) o2).priority - ((PriorityItem) o1).priority);
 
1226
                }
 
1227
                
 
1228
        }
 
1229
}
 
 
b'\\ No newline at end of file'