1 # -*- coding: utf-8 -*-
3 Module d'analyse des fichiers de log minwii.
9 from minwii
.logfilereader
import LogFileReader
10 from pprint
import pprint
11 from minwii
.musicxml
import musicXml2Song
12 from statlib
import stats
14 DEFAULT_STATS
= ('geometricmean',
31 def computeList(self
):
34 for name
in DEFAULT_STATS
:
35 ret
[name
] = getattr(stats
, name
)(l
)
39 class LogFileAnalyser(LogFileReader
) :
41 POSSIBLE_ANALYSES
= {'BEGINNER' : ('songDuration',
43 'noteEndNoteOnLatency',
45 ,'EASY' : ('songDuration',
47 'noteEndNoteOnLatency',
50 ,'NORMAL' : ('songDuration',
54 ,'ADVANCED' : ('songDuration',
58 ,'EXPERT' : ('songDuration',
68 self
.mode
= mode
= self
.getMode()
69 results
.append(('Mode de jeu', mode
))
70 for name
in self
.POSSIBLE_ANALYSES
[mode
] :
71 meth
= getattr(self
, name
)
72 results
.append((meth
.__doc
__, meth()))
78 def playingDuration(self
) :
80 #retourne la durée écoulée entre le premier et de dernier message
81 #de type événement : correspond à la durée d'interprétation.
83 last
= self
.getLastEventTicks()
84 first
= self
.getFirstEventTicks()
87 def songDuration(self
) :
89 #retourne la durée de référence de la chanson
90 #en prenant en compte le tempo présent dans la transcription
91 #et en effectuant toutes les répétitions des couplets / refrains.
93 songFile
= self
.getSongFile()
94 song
= musicXml2Song(songFile
)
96 for note
, verseIndex
in song
.iterNotes() :
97 duration
= duration
+ note
.duration
98 return duration
* song
.quarterNoteDuration
101 def noteEndNoteOnLatency(self
) :
103 eIter
= self
.getEventsIterator()
107 for ticks
, eventName
, message
in eIter
:
108 if eventName
== 'NOTEEND':
110 if eventName
== 'NOTEON' and lastnoteEndT
:
111 latencies
.append(ticks
- lastnoteEndT
)
115 def noteOnCount(self
) :
116 "retourne le nombre d'événements NOTEON"
118 eIter
= self
.getEventsIterator()
121 for ticks
, eventName
, message
in eIter
:
122 if eventName
== 'NOTEON' :
127 def realisationRate(self
) :
128 'Taux de réalisation'
129 #taux de réalisation en nombre de note
130 #peut être supérieur à 100 % car la chanson
133 songFile
= self
.getSongFile()
134 song
= musicXml2Song(songFile
)
136 for note
, verseIndex
in song
.iterNotes() :
137 songNoteCpt
= songNoteCpt
+ 1
139 return int(round(self
.noteOnCount() / float(songNoteCpt
) * 100, 0))
141 def missCount(self
) :
143 eIter
= self
.getEventsIterator()
145 if self
.mode
in ('EASY', 'NORMAL') :
147 for ticks
, eventName
, message
in eIter
:
148 if eventName
== 'COLDOWN' :
149 colState
= message
.split(None, 2)[1]
150 colState
= colState
== 'True'
156 elif eventName
== 'NOTEON' :
158 elif eventName
== 'COLUP' and catchColUp
:
161 for ticks
, eventName
, message
in eIter
:
162 if eventName
== 'COLDOWN' :
163 colState
= message
.split(None, 2)[1]
164 colState
= colState
== 'True'
175 from optparse
import OptionParser
176 usage
= "%prog logfile"
177 op
= OptionParser(usage
)
178 options
, args
= op
.parse_args()
180 op
.error("incorrect number of arguments")
183 lfa
= LogFileAnalyser(args
[0])
184 pprint(lfa
.analyse())
186 if __name__
== "__main__" :
187 from os
.path
import realpath
, sep
189 minwiipath
= realpath(__file__
).split(sep
)
190 minwiipath
= minwiipath
[:-2]
191 minwiipath
= sep
.join(minwiipath
)
192 sys
.path
.insert(1, minwiipath
)