see general ideas in the end of this file too!



**************************************
******************* IN VERSION 1.1
**************************************

===================  TIMING of QUESTIONS/ training for speed =======
1. decreasing time of pauses between questions and leave only limited
	(and decreasing) time for an answer

questions have to vanish after a timeout; otherwise a user can answer slowly,
and there is no motivation for speeding

to make pauses shorter and shorter, and notes vanish:
LOOP
question -> show -> start a regular timer

1-> growtime; if time not too big time++
		if time too big hide question, say too_long 
		* another note's parameter: numTooLong -
		  should make note more frequent, but not force-scheduled
=> check (printInDebug) onetimes before erasing (is 1st really so big; why?
 	what eats up the time?)
2-> answer; checkanswer etc. 

count-down rather then time spent on 1 question;
maybe: onetime--  would be clearer (in the code) than onetime++?

maybe: part of checkanswer and overtime could be outsourced to another
	function
maybe: add another togglebutton: progressive time (each questions the
	time4answer gets 0.5% shorter; this means after 140 questions 
	you have about half the time: (0.995)^140=0.496
	NO: see extra exe-type combo idea below!
if one sets up a speedgoal we start with 2x longer questions and after
	140 questions we are there;
if one is not able to answer that fast time is increased; 
if one makes too many mistakes either time is increaserd or user is turned
	to no-time-limit exercises;
then one can train with a steady speed;
(again: an automatic after-test personal new test suggestions would be
	desirable;
	maybe even whole course:
	0. introductory, no-times-limit tests to train notes names
	only then we start training for speed:
	1. program remembers your answering speed from no-time-limit tests
	   - this is a starting point for few time-regression tests 
	2. when maximum user's speed is settled there is a series of
	   fixed speed and regression speed tests; is there speed progress?
	3. this is done until the user achieves his speed goal
	or
	3'. if user slows down because of particular notes or errs about 
	   particular notes a special forced test can be prepared
)
possible modification: a test without errors - user has to eventually
answer right (clicking a wrong answer would simply slow down answering speed)

Speeding up should make both time for answer and pauses between questions
shorter. A comments window seems inevitable; a list of QStrings + listview?

Timing might be calculated each time based on number of right/wrong answers
and times or based on previous speed; The first way should be preferred (this
way the program can e.g. gauge speed on the slowest answered note speed);
Note: each note needs, apart from overall speed, a last-answer speed - let
us hope, the user would make some progress.

Maybe a forced question: each 5 question the slowest not is chosen; then
user gets: once a question about this note, once about a random from others.
Statusbar should display current test mode. Another combo and menu with
list of tests
* choose a note tests [IN FUTURE: 1.2]
* no-time-limit test (make a reminder that one should first play with
	notes/buttons and remember correspondence)
* low speed exercises
* speed progression exercises
* keep-high-speed exercises (come back to this one once a while; if you
	can't do it go back to the speed-progression)
One variable: speedProgress
* = -1 	=> no time limit
* = 0  	=> no speed change
* = 1	=> progression by a factor 0.995 after each in-time answer
		maybe: wiser choice based on individual notes' speeds
		maybe: the slowest note most important
		time the user has should never be shorter then 1.2* time
	       of his fastest answer; we don't want a mission impossible tests!

Remember user statistics for each exercise in -/.kln.

Because there would be no sequence, t->hide should be run by nextnote() 
(rather then redraw).

maybe: only few runs and easy goals for all levels except from 10/20/30/40
(with all notes in particular range)? at least make such suggestion in 
helpfiels





======
1'. make comments textbox with permanent info about results
2.  individual testnotes selection and individually auto-design test

	* wrong answer should slow things down (i.e. make pauses longer)
	+ add a widget for comments log; do not erase between tests;
	  make statistics comments in the end : the slowest notes; the fastest
	  ; do they need training (they do if are 2x slower and there are more
	  then 4 notes active) + a button "Make custom exercise" (which
	  should set both proper notes/ranges and speed goals)
	note, that "custom exercise" could even ignore sliders (it has to
	  turn right buttons on though) - just turn them disabled and set
	  some variable disabling setupActiveNotes

	maybe: the faster user does the shorter pauses? this would add
	  some dynamics (right now (1.0) due to long pauses between
	  questions, tests go in steady pace even for fast-answering user
	  which doesn't encourage speeding :( )


====================== DEFAULT NUMBER OF QUESTIONS ========
3. calculate default length of test based on number of testnotes


for for-speed exercises this is constantly 140 which would ideally increase
speed by a factor 2;

but for introductory tests (without time limits) there should be shorter
and longer tests: if there are only 4 testnotes of which only 2 are
new to the user there can be less questions (ca. 40-50), for 23-notes 
exercise 200 questions test seem reasonable;

Note: there may be not only test-length but also a frequency influence in
 notes' draw probability, e.g. the C-E-G test is to teach the E note (all 
others have been already tested before) and it should be almost every 2nd
question asked!
CHECK how long will it take. If too long, this should be calculated only 
	ONCE and saved in users -/.kln file.
Each aNote needs 2 variables: numTreble and numBass - a number of appearances
of this note in all treble and all bass clef exercises except from
10/20/30/40;
Note: I will not make any distinction between aNote's appearance in upper/
mid/lower region exercises - if a note is not frequently trained in upper
region and not frequently in mid, it can still altogether be better 
trained, then a different note which is more frequent but only in mid-region
exercises.
+ 4 functions: setNumTreble, setNumBass, getNumTreble, getNumBass
In the beginning: if there is -/.kln load all numTre/Bass for all notes;
otherwise:
*** add to setupActiveNotes a parameter: setupActiveNotes(visible=true);
* loop through clefs
	* loop through exercises except for 10/20/30/40:
		run setupActiveNotes with a parameter visible=false (so that 
		notes didn't appear in canvas), and then for each activeNote
		numTreble or Bass++
Then make gauging debug: show this info for all notes; then 
* for each exercise show:
exeNum	numActNotes	sumOfNotesONEOVERNumTre/Bass	listOfAllNotesNumTre/Bass
	based on this decide on weight on test-lengths (note that it shouldn't be
	longer then 200 nor shorter then 40);
* for each note show:
noteNum	cName	numTre	numBass
	based on this decide on notes probab weights; notes weight factors 
	coming form this probably should not differ by more then a factor 5




**************************************
******************* IN VERSION 1.2
**************************************
COMPLETELY NEW EXERCISES' IDEAS  but based on similar interface

=======
1. add exercise in another direction: 

INI:
* all testnotes reset and visible
* not-so-random name choice: note, that it should also know about nubmer
	of notes of a fiven name (really????? if one doesn't know a note
	and makes mistakes this note will be repeated anyway; if one 
	answers right and fast the fact, that the note is rare should not
	matter)
* one namebutton highlighted; clock starts

ANSWER CHECK:
-> click a note	-> if it's already maked (non-black colored) - NOP
		|
		-> otherwise:
			stop clock
			-> if it's right name OK++, change note's color 2 green
			|
			-> if wrong, WR++, change it to red...
		|
		loop through all testnotes: 
			-> if exists black of the name wait for next click
			|
			-> otherwise reset and draw a new question

=======
2. add sequence reading exercise: 

new display necessery: x-positions of notes;
let's assume that no note can be repeated in a sequence: number of aNotes
will not have to change

NO: in future one may need a sequenc-of-chords exercise; in such a case
a note on the same line can need to be displayed twice; it may be
better to make already here a matrix of notes: each note has few (4-5)
copies of different x-positions; maybe new class: sameNotes
(because some features,e.g. midi pitches may be outsorced; if one would
like to use shared (static?) properties one would have to distinguish
between different notes heights anyway...


x-position step: 5*SC
because if note's are shifted (moveit-ed) they take 2*SC to the left/right
from central position

new param.LOS: defLengthOfStaff = number of notes that can fit into the staff

aNote* questions[defLOS]

LOOP:
--> choose aNote ("normal" wise random) into questions[] untill filled
|
|   numAns=0
|   while(numAns++<defLOS)
|	answer	-> show CORRECT answer under the staff in red or green
|
|   show some stats about a series
|   if numQue not too big loopback (choose a new sequence)
\--/


=======
3. idea (2.) the other way around:
4. like (1.) but without testnotes shown

both would require splitting the range into octaves:
CDEFGAHCDEFGAHCDEFGAHCDEFGA
<-----><-----><-----><---->
   <-----><-----><----->

aNote* octaves[7][8];
                  ^ how many 1/2-separation octaves may fit into the staff?
int numOctaves=0;
int numNotesInOctave[8];
int octaveFill=0;
for(i=minRange; i<maxRange ; i++)
	octaveFill++; // octave should be shifted after 7 notes
			// no matter how many of them were added
        if(octaveFill==8)
                octaveFill=0
                numOctaves++
                if(numOctaves is even)
			i-=3;
		else
			i-=4;

       if(aNote[i] is active)
		octaves[noteNumber][numOctaves]==aNote[i];
		numNotesInOctave[numOctaves]++;

if(numNotesInOctave[numOctave]<2) numOctave--;
	// there range ecceded last octave, but, even after an 'i'
	// back shift there were either no o 1 activenote in the last
	// octave - don't use it for draws

if(numOctave<1) =>  bail out
	NOTE: for ==1 there should be no octave-draw



The rest goes in a standard way:
* we random-draw an octave and change color of a region of the staff
* we random-draw a sequence of notes within an octave

question=button lit
answer=click in the staff (maybe an animation: a note going down/up to the
	right position)



**************************************
******************* IN VERSION 2.0
**************************************
NEW INTERFACE EXERCISES (sharps, flats, exe based not-on-notes)

=======
1. teach key signatures

=======
2. teach major/minor chords writing in staff & recognition

=======
3. design somehow common interface to all kinds of exercises

=======
4. theory help (what is the order of sharps/flats etc.)


********************************************************
********************************************************
********************************************************
***********
***********       GENERAL IDEAS/QUESTIONS:
***********
********************************************************
********************************************************
********************************************************

- maybe simple "update" of an action or a menu would get rid of fancyAction?

- there are so many things random-drawn: make a parent class
Class RandomObject
with stat properties (WR,OK,...) in one public struct 
and methods (updateProbabWeights)
Each of the objects (aNote, button, octave) would inherit these.


Hmm. Now, one can make eg.
* an array of aNotes (testnotes)
* an array of statProps* array2draw[numberOfTestNotes]

now a random function draws a number in (0,numOfTestNotes) based on 
the array2draw, and the result of the draw is number of the aNote


To draw a button: one makes
* an array of active buttons
* an array of their statProps* array2draw[numberOfActiveButtons]
and use the same random function to make draws! :)


Simpler idea (but I don't know if possible):
maybe, if some objects inherit the same properities one can make
array of pointers to any of them, provided one uses only the 
inherited properties?

aNote inherits randomObject
aButton inherits randomObject
randomObject* anArray[];

can in such a case anArray be filled once with aNotes, then with 
aButtons?
say,
    aNote* newNote=new aNote();
    anArray[0]= (randomObject*) newNote;
???????????
If it is possible it would be easier, because randomDraw would use
an array of pointers-to-objects rather then extracted-from-objects
structs.


