5
\$\begingroup\$

This gives you one note and asks you go up or down the scale for a certain number:

///////////////////////////////
//// ClearConsole.java
///////////////////////////////


/**
 * Created by IDEA on 06/12/14.
 */
public final class ClearConsole {
    static void clear() {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            stringBuilder.append(String.format("%n"));
        }
        String s = stringBuilder.toString();
        System.out.println(s);
    }
}

///////////////////////////////
//// Note.java
///////////////////////////////


import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.apache.commons.lang3.ArrayUtils;

import java.util.Arrays;
import java.util.stream.Stream;

import static java.lang.Math.abs;

/**
 * Created by IDEA on 06/12/14.
 */
public class Note {
    public final static int octaveNumber = 7;
    public final static int totalNotes = 14;
    public final static String[] lowNotes   = {"C", "D", "E", "F", "G", "A", "B"};
    public final static String[] hightNotes = {"c", "d", "e", "f", "g", "a", "b"};
    public final static String[] notes = Stream.concat(Arrays.stream(lowNotes), Arrays.stream(hightNotes)).toArray(size -> new String[size]);
    private String note;
    public static BiMap<String, Integer> noteMap = HashBiMap.create();
    public static BiMap<Integer, String> numberMap;

    static {
        for(int i=0; i<notes.length; i++){
            noteMap.put(notes[i], new Integer(i));
        }
        numberMap = noteMap.inverse();
    }

    public Note(String note) throws Exception {
        if(!ArrayUtils.contains(notes, note)) {
            throw new IllegalArgumentException("Not a valid note");
        }
        this.note = note;
    }

    public Note(int number) throws Exception {
        this(notes[number]);
    }

    public Note() throws Exception {
        this("C");
    }

    public int getNumber() {
        return noteMap.get(note).intValue();
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public boolean isHigh() {
        return ArrayUtils.contains(hightNotes, note) ? true : false;
    }

    // go up or down the scale by a number
    public Note add(int number) throws Exception {
        if(this.isHigh() && number > 0) {
            throw new IllegalArgumentException("You can only add to low notes (ABCDEFG)");
        }
        if(!this.isHigh() && number < 0) {
            throw new IllegalArgumentException("You can only subtract from notes (abcdefg)");
        }
        if(abs(number) > octaveNumber) {
            throw new IllegalArgumentException(String.format("Maximum amount of increase or decrease is %d", octaveNumber));
        }

        int newNumber = getNumber() + number;
        return new Note(newNumber);
    }

    @Override
    public String toString() {
        return String.format("Note('%s')", note);
    }


    // test
//    public static void main(String[] args) throws Exception {
//        Note n1 = new Note("A");
//        Note n2 = n1.add(3);
//        Note n3 = new Note(13);
//        Note n4 = n3.add(-7);
//        System.out.println(n1);
//        System.out.println(n2);
//        System.out.println(n3);
//        System.out.println(n4);
//    }

}

///////////////////////////////
//// Sheet.java
///////////////////////////////


import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by IDEA on 06/12/14.
 */
public class Sheet {
    private final static int lineLength = 70;
    private final static int extraLineLength = 35;
    private final static int notePos = 18;
    private static String line;
    private static String space;
    private static String extraLine;
    private static String extraSpace;
    private List<String> template = initTemplate();
    private List<String> sheet;

    private static List<String> initTemplate() {
        StringBuilder sb1, sb2;
        sb1 = new StringBuilder();
        sb2 = new StringBuilder();
        for(int i=0; i<lineLength; i++) {
            sb1.append("—");
            sb2.append(" ");
        }
        line = sb1.toString();
        space = sb2.toString();
        extraLine = line.substring(0, extraLineLength);
        extraSpace = space.substring(0, extraLineLength);

        List<String> res = new ArrayList<>();
        res.add(extraSpace);
        res.add(extraLine);
        for(int i=0; i<5; i++) {
            res.add(space);
            res.add(line);
        }
        res.add(extraSpace);
        res.add(extraLine);
        return res;
    }

    public Sheet() {
        reset();
    }

    public Sheet annotate(Note note, String annotation) {
        // music notes go from bottom to top, strings are printed from top to bottom
        int index = 13 - note.getNumber();
        String annotatedRow = sheet.get(index);
        annotatedRow = annotatedRow.substring(0, notePos) + annotation + annotatedRow.substring(notePos+annotation.length());
        sheet.set(index, annotatedRow);
        return this;
    }

    public Sheet annotate(Note note) {
        annotate(note, note.getNote());
        return this;
    }

    public void reset() {
        sheet = new ArrayList<>(template);
    }

    @Override
    public String toString() {
        sheet.add(0, extraLine);
        return Joiner.on(System.lineSeparator()).join(sheet) + System.lineSeparator();
    }

//    public static void main(String[] args) throws Exception {
//        Sheet s = new Sheet();
//        s.annotate(new Note("b"));
//        s.annotate(new Note("G"), "?");
//        System.out.println(s);
//    }

}

///////////////////////////////
//// Trainer.java
///////////////////////////////


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Random;

/**
 * Created by IDEA on 06/12/14.
 */
public class Trainer {
    private final Sheet sheet = new Sheet();
    private Note note1;
    private Note note2;
    private final Random rand = new Random();
    private int nTry = 0;
    private int nCorrect = 0;
    private int intervalNumber;

//    public Trainer() throws Exception {
//        rand = new Random();
//    }

    public void update() throws Exception {
        intervalNumber = rand.nextInt(Note.octaveNumber) + 1;
        int noteNumber = rand.nextInt(Note.totalNotes);
        note1 = new Note(noteNumber);
        if(note1.isHigh()) {
            intervalNumber = -intervalNumber;
        }
        note2 = note1.add(intervalNumber);
    }

    public String countString() {
        return String.format("[ %d / %d ]%n%n", nCorrect, nTry);
    }

    public String mathQuizString() {
        return String.format("%s + (%d) = ?", note1.getNote(), intervalNumber);
    }

    public String mathRevealString() {
        return String.format("%s + (%d) = %s", note1.getNote(), intervalNumber, note2.getNote());
    }

    public String quizString() {
        sheet.reset();
        return countString() + sheet.annotate(note1).annotate(note2, "?").toString() + System.lineSeparator() + mathQuizString();
    }

    public String revealString() {
        sheet.reset();
        return countString() + sheet.annotate(note1).annotate(note2).toString() + System.lineSeparator() + mathRevealString();
    }

    public static void main(String[] args) throws Exception {
        Trainer trainer = new Trainer();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            trainer.update();
            ClearConsole.clear();
            System.out.println(trainer.quizString());
            System.out.print("Your answer (type 'quit' shut me down): ");
            String ans = reader.readLine();
            ans = ans.trim();

            if(ans.equals("quit")) {
                break;
            }

            trainer.nTry++;
            ClearConsole.clear();
            if(ans.toLowerCase().equals(trainer.note2.getNote().toLowerCase())) {
                trainer.nCorrect++;
                System.out.println(trainer.revealString());
                System.out.printf("You answer is %s, your are right.%nPress enter to continue.", ans);
            } else {
                System.out.println(trainer.revealString());
                System.out.printf("You answer is %s, your are wrong.%nPress enter to continue.", ans);
            }
            ans = reader.readLine();
        }
    }
}
\$\endgroup\$
4
\$\begingroup\$
  • I find this to be an effective, but smelly way to clear the console:

    public final class ClearConsole {
        static void clear() {
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < 1000; i++) {
                stringBuilder.append(String.format("%n"));
            }
            String s = stringBuilder.toString();
            System.out.println(s);
        }
    }
    

    There are better ways to go about this.

  • The real musical scale has half-steps. This code ignores that.

  • Looks like you've got a typo here:

    hightNotes
    
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.