Subversion Repositories pianoUtils

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 janik 1
from collections import namedtuple
2
import random
3
 
4
class NoteTeacher:
5
    Level = namedtuple("Level", ("start_note", "counter", "notes", "desc"))
6
    Note = namedtuple("Note", ("clef", "tone"))
7
 
8
    G_NOTES = ["c1", "e1", "g1", "h1", "d2", "f2", "a2", # priority goes to notes on lines
9
                 "d1", "f1", "a1", "c2", "e2", "g2", "h2"]
10
 
11
    F_NOTES = ["c1", "a", "f", "d", "H", "G", "E", "C", # priority goes to notes on lines
12
                 "h", "g", "e", "c", "A", "F", "D"]
13
 
14
    ALL_NOTES = {"G": [Note(tone = tone, clef = "G") for tone in G_NOTES],
15
                 "F": [Note(tone = tone, clef = "F") for tone in F_NOTES]}
16
 
17
    LEVELS = (Level(start_note = "g1", counter = 8, notes = ALL_NOTES["G"], desc = "G clef with 2 notes at start"),
18
              Level(start_note = "d2", counter = 14, notes = ALL_NOTES["G"], desc = "G clef with 4 notes at start"),
19
              Level(start_note = "d1", counter = 20, notes = ALL_NOTES["G"], desc = "G clef with 7 notes at start"),
20
              Level(start_note = "e2", counter = 26, notes = ALL_NOTES["G"], desc = "G clef with 11 notes at start"),
21
              Level(start_note = None, counter = 32, notes = ALL_NOTES["G"], desc = "G clef with all notes at start"),
22
              Level(start_note = "f", counter = 8, notes = ALL_NOTES["F"], desc = "F clef with 2 notes at start"),
23
              Level(start_note = "H", counter = 14, notes = ALL_NOTES["F"], desc = "F clef with 4 notes at start"),
24
              Level(start_note = "h", counter = 20, notes = ALL_NOTES["F"], desc = "F clef with 8 notes at start"),
4 janik 25
              Level(start_note = "A", counter = 26, notes = ALL_NOTES["F"], desc = "F clef with 12 notes at start"),
26
              Level(start_note = None, counter = 32, notes = ALL_NOTES["F"], desc = "F clef with all notes at start"),
2 janik 27
              Level(start_note = None, counter = 38, notes = ALL_NOTES["G"] + ALL_NOTES["F"], desc = "both clefs with all notes at start")
28
             )
29
 
30
    def __init__(self, level = LEVELS[0]):
31
        self.counter = 0
32
        self.current_note = None
33
        self.statistics = {}
34
 
35
        self.max_count = 0 # initialized from level
36
        self.notes = [] # initialized from level
37
        self.available_notes = [] # initialized from level
38
 
39
        self.init_notes(level)
40
 
41
    def init_notes(self, level):
42
        if level.start_note is None:
43
            self.notes = []
44
            self.available_notes = level.notes[:]
45
        else:
46
            self.notes = level.notes[:]
47
            self.available_notes = []
48
            while self.notes[0].tone != level.start_note:
49
                self.available_notes.append(self.notes.pop(0))
50
        self.max_count = level.counter
51
 
52
        self.current_note = random.choice(self.available_notes)
53
 
54
    def next_note(self):
55
        self.current_note = random.choice(self.available_notes)
56
 
57
        self.counter += 1
58
        if self.counter == self.max_count and self.notes:
59
            self.available_notes.append(self.notes.pop(0))
60
            self.counter = 0
61
            self.max_count = int(self.max_count * 1.5)
62
 
63
    def check_note(self, note):
64
        result = note == self.current_note.tone
65
 
66
        self.statistics.setdefault(self.current_note, []).append(result)
67
 
68
        if result:
69
            # ak uhadnem notu 10x po sebe a ma zvysenu pravdepodobnost
70
            if all(self.statistics[self.current_note][-10:]) and self.available_notes.count(self.current_note) > 1:
71
                self.available_notes.remove(self.current_note)
72
            return True
73
        else:
74
            self.available_notes.append(self.current_note)
75
            self.max_count = int(self.max_count * 1.5)
76
            return False
77
 
78
    def get_progress(self):
79
        if not self.notes:
80
            return "inf"
81
        else:
82
            return "%d/%d"%(self.counter + 1, self.max_count)
83
 
84
    def output_statistics(self, statistics):
85
        data = self.statistics.items()
86
        data.sort(key = lambda x: (x[0].clef, self.ALL_NOTES[x[0].clef].index(x[0])))
87
 
88
        for note, wins in data:
89
            statistics.add(note.clef, note.tone, wins.count(False), len(wins))