/** -=- MeasureBiM -=-
*
* This program is a counter aimed for the analysis of bimanual user
* interaction. This program reads a log file generated during user
* experiments, where some user actions are recorded. While reading
* the log file, this program calculates numerous time measures for
* two parallel actions executed by users when performing exercices
* and outputs results in CSV format.
*
* Copyright (C) 2007-2008 Guillaume RIVIERE
*
* MeasureBiM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MeasureBiM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
**/
// File: measurebim.c
// Version: 2.1
#include
#include
#include
typedef long unsigned int luint ;
luint time_to_seconds (const char* t) {
luint h, m, s ;
sscanf (t, "%*s %lu:%lu:%lu %*s", &h, &m, &s) ;
return s + m*60 + h*3600 ;
}
// Time values and counters to compute measures
luint evt1only_start=0, evt1only_time=0, // for T1s
evt2only_start=0, evt2only_time=0, // for T2s
evt1and2_start=0, evt1and2_time=0 ; // for T12
luint evt1_start=0, evt1_time=0, evt1_count=0, // for T1 and n1
evt2_start=0, evt2_time=0, evt2_count=0 ; // for T2 and n2
luint first_evt=0, last_evt=0 ; // for D
void print (char *user, char *ex) {
double avg_evt1 = (double)evt1_time / (double)evt1_count ; // Tm1
double avg_evt2 = (double)evt2_time / (double)evt2_count ; // Tm2
luint time = last_evt - first_evt ; // D
/* Print measures in CSV format for a subject and an exercise */
printf (";\"%s\";;\"%s\";;%lu;%lu;%lu;%lu;%lu;;%lu;%lu;%.1f;;%lu;%lu;%.1f;\n",
user, ex, time, // D
evt1only_time + evt2only_time + evt1and2_time, // T
evt1only_time, evt2only_time, evt1and2_time, // T1s, T2s, T12
evt1_time, evt1_count, avg_evt1, // T1, n1, Tm1
evt2_time, evt2_count, avg_evt2) ; // T2, n2, Tm2
}
int main (int argc, char* argv[]) {
char in_evt1only=0, in_evt2only=0, in_evt1and2=0, do_print=0 ; // States
FILE *desc ;
char buf[1024], ex[1024], user[1024], ex_print[1024], user_print[1024] ;
ex[0] = user[0] = '\0' ;
/* Check number of arguments */
if (argc != 6) {
fprintf(stderr, "%s \n", argv[0]) ;
exit(1) ;
}
char *log = argv[1] ;
char *key_evt1_start = argv[2] ;
char *key_evt1_end = argv[3] ;
char *key_evt2_start = argv[4] ;
char *key_evt2_end = argv[5] ;
int len_evt1_start = strlen(argv[2]) ;
int len_evt1_end = strlen(argv[3]) ;
int len_evt2_start = strlen(argv[4]) ;
int len_evt2_end = strlen(argv[5]) ;
/* Open the log file in read mode */
if ((desc=fopen (log, "r")) == NULL) {
fprintf(stderr, "Error: open file %s in read mode", log); perror(""); exit(1);
}
/* Print header in CSV format */
printf (";Sujet;;Exercice;;D;T;T1s;T2s;T12;;T1;n1;Tm1;;T2;n2;Tm2;\n") ;
while (!feof(desc)) {
fgets (buf, 1024, desc) ;
int len = strlen(buf) ;
if (len>0 && buf[len-1]=='\n')
buf[len-1] = '\0' ;
if (buf[0] == '*' && buf[1] == ' ') { /* NEW USER */
if (ex[0] != '\0') {
do_print = 1 ;
strcpy(user_print, user) ;
strcpy(ex_print, ex) ;
ex[0] = '\0' ;
}
strcpy (user, buf+2) ;
}
if (buf[0] == '#' && buf[1] == ' ') { /* NEW EXERCISE */
if (ex[0] != '\0') {
do_print = 1 ;
strcpy(user_print, user) ;
strcpy(ex_print, ex) ;
}
strcpy (ex, buf+2) ;
}
if (do_print) {
/* Print last exercise */
print(user_print, ex_print);
/* Reset values for the new exercise */
first_evt = last_evt = 0 ;
evt1only_time = evt2only_time = evt1and2_time = 0 ;
evt1_time = evt2_time = 0 ;
evt1_count = evt2_count = 0 ;
do_print = 0 ;
}
if (buf[0] == '=') {
luint time = time_to_seconds (buf) ;
if (!strncmp(buf+13, key_evt2_start, len_evt2_start)) { /* EVT2 START */
evt2_start = time ;
if (first_evt == 0)
first_evt = time ;
if (in_evt1only) {
/* Enter in evt1and2 state */
in_evt1and2 = 1 ;
evt1and2_start = time ;
/* Go out of evt1only state */
in_evt1only = 0 ;
evt1only_time += time - evt1only_start ;
}
else {
/* Enter in evt2only state */
in_evt2only = 1 ;
evt2only_start = time ;
}
}
else if (!strncmp(buf+13, key_evt2_end, len_evt2_end)) { /* EVT2 END */
evt2_count++ ;
evt2_time += time - evt2_start ;
last_evt = time ;
if (in_evt1and2) {
/* Go out of evt1and2 state */
in_evt1and2 = 0 ;
evt1and2_time += time - evt1and2_start ;
/* Enter in evt1only state */
in_evt1only = 1 ;
evt1only_start = time ;
}
else {
/* Go out of evt2only state */
in_evt2only = 0 ;
evt2only_time += time - evt2only_start ;
}
}
else if (!strncmp(buf+13, key_evt1_start, len_evt1_start)) { /* EVT1 START */
evt1_start = time ;
if (first_evt == 0)
first_evt = time ;
if (in_evt2only) {
/* Enter in evt1and2 state */
in_evt1and2 = 1 ;
evt1and2_start = time ;
/* Go out of evt2only state */
in_evt2only = 0 ;
evt2only_time += time - evt2only_start ;
}
else {
/* Enter in evt1only state */
in_evt1only = 1 ;
evt1only_start = time ;
}
}
else if (!strncmp(buf+13, key_evt1_end, len_evt1_end)) { /* EVT1 END */
evt1_count++ ;
evt1_time += time - evt1_start ;
last_evt = time ;
if (in_evt1and2) {
/* Go out of evt1and2 state */
in_evt1and2 = 0 ;
evt1and2_time += time - evt1and2_start ;
/* Enter in evt2only state */
in_evt2only = 1 ;
evt2only_start = time ;
}
else {
/* Go out of evt1only state */
in_evt1only = 0 ;
evt1only_time += time - evt1only_start ;
}
}
}
}
if (ex[0] != '\0')
/* Print last exercise */
print(user, ex);
fclose (desc) ;
return 0 ;
}