package instantbach.service;
// Control
import instantbach.InstantBach;
// Custom Data
import instantbach.data.Graph;
import instantbach.data.graph.Edge;
import instantbach.data.graph.Vertex;
import instantbach.data.chord.Symbol;
import instantbach.data.SymbolList;
import instantbach.data.Chord;
// Custom I/O
import instantbach.service.text.LoadProgressionGraph;
import instantbach.service.logic.VoiceThread;
// Standard Data
import java.util.ArrayList;
import java.util.LinkedList;
// Interfaces
import instantbach.InstantBachInterface;
// Exceptions
import instantbach.service.exception.BadRulesException;
/**
* <p>Title: Service</p>
*
* <p>Description: Represents the service tier of this application</p>
*
* <p>Copyright: Copyright (c) 2007</p>
*
* <p>Company: </p>
*
* @author John Valentino II
* @version 1.0
*/
public class Service implements InstantBachInterface {
/** Reference to the parent controller */
private InstantBach parent;
/** Represents the progression graph */
private Graph graph;
/** Represents the location of the progession graph */
private String graphLocation = "rule.txt";
/** Represents a list of available chord symbols */
private SymbolList availableSymbols;
/**
* Creates the service tier
* @todo Load chord symbols and rules from external file
* @param parent InstantBach
* @throws BadRulesException
*/
public Service(InstantBach parent) throws BadRulesException {
this.parent = parent;
//create a graph of rules for chord progressions
LoadProgressionGraph loader = new LoadProgressionGraph(this);
graph = loader.createProgressionGraph(graphLocation);
//create a list of available chords
availableSymbols = new SymbolList();
availableSymbols.add("ii","ii");
availableSymbols.add("iii","iii");
availableSymbols.add("IV","IV");
availableSymbols.add("V","V");
availableSymbols.add("7V","V7");
availableSymbols.add("vi","vi");
availableSymbols.add("viio","viio");
availableSymbols.add("7vii0","vii07");
availableSymbols.add("V/V","V/V");
availableSymbols.add("7V/V","V7/V");
availableSymbols.add("V/IV","V/IV");
availableSymbols.add("7V/IV","V7/IV");
availableSymbols.add("N6","N6");
availableSymbols.add("7Fr+6","Fr+6");
availableSymbols.add("I","I");
}
/** SERVICE TIER METHODS */
/**
* Returns the list of available symbols
* @return SymbolList
*/
public SymbolList getAvailableSymbols() {
return this.availableSymbols;
}
/**
* Attempts to voice the specified progression
* @param progression SymbolList
*/
public synchronized void voiceProgression(SymbolList progression) {
VoiceThread thread = new VoiceThread(this, graph, progression);
thread.start();
}
/**
* Generates a random progression and attempts to voice it
*/
public synchronized void generateAndVoiceProgression() {
SymbolList progression = new SymbolList();
ArrayList<String> identifiers = new ArrayList<String>();
//add the root as the last chord
identifiers.add("I");
//add the dominant as the second to last
identifiers.add("7V");
//get the current vertex (for the cadence)
Vertex currentVertex = graph.getVertex("7V");
for (int i = 0; i < 9; i++) {
//get the adjacent edges to the current vertex
LinkedList<Edge> currentEdges = currentVertex.getAdjacent();
int numToChoose = currentEdges.size();
int randomNumber = (int) (Math.random() * numToChoose + 0);
//get a random edge
Edge randomEdge = currentEdges.get(randomNumber);
//get the destination of the random edge
currentVertex = randomEdge.getDestination();
String identifier = currentVertex.getName();
identifiers.add(identifier);
//returnVector.add(current.name);
}
//create a progression using the given identifiers
for (int i = identifiers.size() - 1; i >= 0; i--) {
//get the symbol for the current identifier
String id = identifiers.get(i);
Symbol symbol = availableSymbols.getSymbolByIdentifier(id);
//add this symbol to the current progression
progression.add(symbol);
}
//pass this progression to be voiced
this.voiceProgression(progression);
}
/** GUI TIER METHODS */
/**
* Displays the given chords for the given progression
* @param prog SymbolList
* @param chords Chord[]
*/
public void displayChords(SymbolList prog, Chord[] chords) {
parent.displayChords(prog, chords);
}
/**
* Displays the given error
* @param errors ArrayList
*/
public synchronized void displayErrors(ArrayList<String> errors) {
parent.displayErrors(errors);
}
/**
* Appends the given text to the information area
* @param line String
*/
public synchronized void appendInfo(String line) {
parent.appendInfo(line);
}
}