blob: 6208e6ffd4750c1eda19435930ba4c1da73b2761 [file] [log] [blame]
/*
* Copyright (C) 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.voicedialer;
import android.content.Intent;
import android.util.Log;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
/**
* This class represents a person who may be called via the VoiceDialer app.
* The person has a name and a list of phones (home, mobile, work).
*/
public class VoiceDialerTester {
private static final String TAG = "VoiceDialerTester";
private final WavFile[] mWavFiles;
private final File[] mWavDirs;
// these indicate the current test
private int mWavFile = -1; // -1 so it will step to 0 on first iteration
private static class WavFile {
final public File mFile;
public int mRank;
public int mTotal;
public String mMessage;
public WavFile(File file) {
mFile = file;
}
}
/**
* Sweep directory of directories, listing all WAV files.
*/
public VoiceDialerTester(File dir) {
if (false) {
Log.d(TAG, "VoiceDialerTester " + dir);
}
// keep a list of directories visited
Vector<File> wavDirs = new Vector<File>();
wavDirs.add(dir);
// scan the directory tree
Vector<File> wavFiles = new Vector<File>();
for (int i = 0; i < wavDirs.size(); i++) {
File d = wavDirs.get(i);
for (File f : d.listFiles()) {
if (f.isFile() && f.getName().endsWith(".wav")) {
wavFiles.add(f);
}
else if (f.isDirectory()) {
wavDirs.add(f);
}
}
}
// produce a sorted list of WavFiles
File[] fa = wavFiles.toArray(new File[wavFiles.size()]);
Arrays.sort(fa);
mWavFiles = new WavFile[fa.length];
for (int i = 0; i < mWavFiles.length; i++) {
mWavFiles[i] = new WavFile(fa[i]);
}
// produce a sorted list of directories
mWavDirs = wavDirs.toArray(new File[wavDirs.size()]);
Arrays.sort(mWavDirs);
}
public File getWavFile() {
return mWavFiles[mWavFile].mFile;
}
/**
* Called by VoiceDialerActivity when a recognizer error occurs.
*/
public void onRecognitionError(String msg) {
WavFile wf = mWavFiles[mWavFile];
wf.mRank = -1;
wf.mTotal = -1;
wf.mMessage = msg;
}
/**
* Called by VoiceDialerActivity when a recognizer failure occurs.
* @param msg Message to display.
*/
public void onRecognitionFailure(String msg) {
WavFile wf = mWavFiles[mWavFile];
wf.mRank = 0;
wf.mTotal = 0;
wf.mMessage = msg;
}
/**
* Called by VoiceDialerActivity when the recognizer succeeds.
* @param intents Array of Intents corresponding to recognized sentences.
*/
public void onRecognitionSuccess(Intent[] intents) {
WavFile wf = mWavFiles[mWavFile];
wf.mTotal = intents.length;
String utter = wf.mFile.getName().toLowerCase().replace('_', ' ');
utter = utter.substring(0, utter.indexOf('.')).trim();
for (int i = 0; i < intents.length; i++) {
String sentence =
intents[i].getStringExtra(RecognizerEngine.SENTENCE_EXTRA).
toLowerCase().trim();
// note the first in case there are no matches
if (i == 0) {
wf.mMessage = sentence;
if (intents.length > 1) wf.mMessage += ", etc";
}
// is this a match
if (utter.equals(sentence)) {
wf.mRank = i + 1;
wf.mMessage = null;
break;
}
}
}
/**
* Called to step to the next WAV file in the test set.
* @return true if successful, false if no more test files.
*/
public boolean stepToNextTest() {
mWavFile++;
return mWavFile < mWavFiles.length;
}
private static final String REPORT_FMT = "%6s %6s %6s %6s %6s %6s %6s %s";
private static final String REPORT_HDR = String.format(REPORT_FMT,
"1/1", "1/N", "M/N", "0/N", "Fail", "Error", "Total", "");
/**
* Called when the test is complete to dump a summary.
*/
public void report() {
// report for each file
Log.d(TAG, "List of all utterances tested");
for (WavFile wf : mWavFiles) {
Log.d(TAG, wf.mRank + "/" + wf.mTotal + " " + wf.mFile +
(wf.mMessage != null ? " " + wf.mMessage : ""));
}
// summary reports by file name
reportSummaryForEachFileName();
// summary reports by directory name
reportSummaryForEachDir();
// summary report for all files
Log.d(TAG, "Summary of all utterances");
Log.d(TAG, REPORT_HDR);
reportSummary("Total", null);
}
private void reportSummaryForEachFileName() {
Set<String> set = new HashSet<String>();
for (WavFile wf : mWavFiles) {
set.add(wf.mFile.getName());
}
String[] names = set.toArray(new String[set.size()]);
Arrays.sort(names);
Log.d(TAG, "Summary of utternaces by filename");
Log.d(TAG, REPORT_HDR);
for (final String fn : names) {
reportSummary(fn,
new FileFilter() {
public boolean accept(File file) {
return fn.equals(file.getName());
}
});
}
}
private void reportSummaryForEachDir() {
Set<String> set = new HashSet<String>();
for (WavFile wf : mWavFiles) {
set.add(wf.mFile.getParent());
}
String[] names = set.toArray(new String[set.size()]);
Arrays.sort(names);
Log.d(TAG, "Summary of utterances by directory");
Log.d(TAG, REPORT_HDR);
for (File dir : mWavDirs) {
final String dn = dir.getPath();
final String dn2 = dn + "/";
reportSummary(dn,
new FileFilter() {
public boolean accept(File file) {
return file.getPath().startsWith(dn2);
}
});
}
}
private void reportSummary(String label, FileFilter filter) {
if (!false) return;
// log cumulative stats
int total = 0;
int count11 = 0;
int count1N = 0;
int countMN = 0;
int count0N = 0;
int countFail = 0;
int countErrors = 0;
for (WavFile wf : mWavFiles) {
if (filter == null || filter.accept(wf.mFile)) {
total++;
if (wf.mRank == 1 && wf.mTotal == 1) count11++;
if (wf.mRank == 1 && wf.mTotal >= 1) count1N++;
if (wf.mRank >= 1 && wf.mTotal >= 1) countMN++;
if (wf.mRank == 0 && wf.mTotal >= 1) count0N++;
if (wf.mRank == 0 && wf.mTotal == 0) countFail++;
if (wf.mRank == -1 && wf.mTotal == -1) countErrors++;
}
}
String line = String.format(REPORT_FMT,
countString(count11, total),
countString(count1N, total),
countString(countMN, total),
countString(count0N, total),
countString(countFail, total),
countString(countErrors, total),
"" + total,
label);
Log.d(TAG, line);
}
private static String countString(int count, int total) {
return total > 0 ? "" + (100 * count / total) + "%" : "";
}
}