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
13 from datetime
import timedelta
15 DEFAULT_STATS
= ('geometricmean',
32 def computeList(self
):
35 for name
in DEFAULT_STATS
:
36 ret
[name
] = getattr(stats
, name
)(l
)
40 class LogFileAnalyser(LogFileReader
) :
42 POSSIBLE_ANALYSES
= {'BEGINNER' : ('songDuration',
44 'noteEndNoteOnLatency',
46 ,'EASY' : ('songDuration',
48 'noteEndNoteOnLatency',
51 ,'NORMAL' : ('songDuration',
55 ,'ADVANCED' : ('songDuration',
59 ,'EXPERT' : ('songDuration',
69 self
.mode
= mode
= self
.getMode()
70 results
.append(('Mode de jeu', mode
))
71 for name
in self
.POSSIBLE_ANALYSES
[mode
] :
72 meth
= getattr(self
, name
)
73 results
.append((meth
.__doc
__, meth()))
79 def _toTimeDelta(self
, milliseconds
) :
80 duration
= milliseconds
/ 1000.
81 duration
= int(round(duration
, 0))
82 return str(timedelta(seconds
=duration
))
84 def playingDuration(self
) :
86 #retourne la durée écoulée entre le premier et de dernier message
87 #de type événement : correspond à la durée d'interprétation.
89 last
= self
.getLastEventTicks()
90 first
= self
.getFirstEventTicks()
91 return self
._toTimeDelta
(last
- first
)
94 def songDuration(self
) :
95 'Durée de référence de la chanson'
96 #retourne la durée de référence de la chanson
97 #en prenant en compte le tempo présent dans la transcription
98 #et en effectuant toutes les répétitions des couplets / refrains.
100 songFile
= self
.getSongFile()
101 song
= musicXml2Song(songFile
)
103 for note
, verseIndex
in song
.iterNotes() :
104 duration
= duration
+ note
.duration
105 duration
= duration
* song
.quarterNoteDuration
# en milisecondes
106 return self
._toTimeDelta
(duration
)
109 def noteEndNoteOnLatency(self
) :
111 eIter
= self
.getEventsIterator()
115 for ticks
, eventName
, message
in eIter
:
116 if eventName
== 'NOTEEND':
118 if eventName
== 'NOTEON' and lastnoteEndT
:
119 latencies
.append(ticks
- lastnoteEndT
)
123 def noteOnCount(self
) :
124 "retourne le nombre d'événements NOTEON"
126 eIter
= self
.getEventsIterator()
129 for ticks
, eventName
, message
in eIter
:
130 if eventName
== 'NOTEON' :
135 def realisationRate(self
) :
136 'Taux de réalisation'
137 #taux de réalisation en nombre de note
138 #peut être supérieur à 100 % car la chanson
141 songFile
= self
.getSongFile()
142 song
= musicXml2Song(songFile
)
144 for note
, verseIndex
in song
.iterNotes() :
145 songNoteCpt
= songNoteCpt
+ 1
147 return round(self
.noteOnCount() / float(songNoteCpt
) * 100, 1)
149 def missCount(self
) :
151 eIter
= self
.getEventsIterator()
153 if self
.mode
in ('EASY', 'NORMAL') :
155 for ticks
, eventName
, message
in eIter
:
156 if eventName
== 'COLDOWN' :
157 colState
= message
.split(None, 2)[1]
158 colState
= colState
== 'True'
164 elif eventName
== 'NOTEON' :
166 elif eventName
== 'COLUP' and catchColUp
:
169 for ticks
, eventName
, message
in eIter
:
170 if eventName
== 'COLDOWN' :
171 colState
= message
.split(None, 2)[1]
172 colState
= colState
== 'True'
183 from optparse
import OptionParser
184 usage
= "%prog logfile"
185 op
= OptionParser(usage
)
186 options
, args
= op
.parse_args()
188 op
.error("incorrect number of arguments")
191 lfa
= LogFileAnalyser(args
[0])
192 pprint(lfa
.analyse())
194 if __name__
== "__main__" :
195 from os
.path
import realpath
, sep
197 minwiipath
= realpath(__file__
).split(sep
)
198 minwiipath
= minwiipath
[:-2]
199 minwiipath
= sep
.join(minwiipath
)
200 sys
.path
.insert(1, minwiipath
)