Logo Search packages:      
Sourcecode: aldo version File versions  Download package

check.cpp

/***************************************************************************
                                 Aldo
                          --------------------
    begin                : Sun May 6 2001
    copyleft             : Giuseppe "denever" Martino
    email                : denever@users.sourceforge.net
***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *  This program 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, write to the Free Software            *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             *
 *  MA 02110-1301 USA                                                      *
 *                                                                         *
 ***************************************************************************/

#include "resources.h"
#include "classic.h"

#include <iostream>
#include <string>
#include <sstream>

// width of screen in characters
#define TERMINAL_WIDTH 80

// use less than max width of unsigned int for displaying counter
#define COUNTER_WIDTH 2

// character for marking mistakes
#define MISTAKE_MARKER '!'

using namespace std;

/*
 *
 */
void display_overall_rate(const unsigned int percentage)
{
    cout<<endl<<ovrmsg_title<<": ";
    cout.width(3);
    cout<<percentage<<'%'<<endl;
}

/*
 * This function displays the copy success rate per keyed symbol.
 */
void display_symbol_rate(const string& keyed_string, const string& copied_string)
{
    unsigned int total[256];
    unsigned int correct[256];

    for(unsigned int i=0; i<256; i++) 
      total[i]=correct[i]=0;

    for(unsigned int j=0; j<keyed_string.length(); j++)
    {
      total[(unsigned int)keyed_string[j]]++;
      if(keyed_string[j] == copied_string[j])
      {
          correct[(unsigned int)keyed_string[j]]++;
      }
    }

    // display feedback category "title"
    cout<<endl<<smbmsg_title<<':'<<endl;

    // display legend
    cout<<smbmsg_percentage<<"%-'"<<smbmsg_symbol<<"'-("
      <<smbmsg_copiedok<<'/'<<smbmsg_keyed<<')'<<endl;

    for(unsigned int i=0; i<256; i++)
    {
      if(total[i])
      {
          cout.width(3);
          cout<<100*correct[i]/total[i]<<"%-'"<<(char)i<<"'-("
            <<correct[i]<<'/'<<total[i]<<')'<<endl;
      }
    }
}

/*
 * This function takes a keyed sign group and a copied sign group and
 * generates a mistakes string of the same length. The mistakes string
 * contains mistake marker characters at the positions where the keyed
 * and the copied strings differ and unobtrusive spacer characters at
 * the other positions.
 */
string mark_mistakes(const unsigned int len,
                     const string keyed, const string copied)
{
    // start with empty string
    string mistakes;

    for(unsigned int i=0; i<len; i++)
    {
      // append to 'mistakes' a correctness marker
      if (keyed[i] == copied[i])
      {
          mistakes += '.';    // unobtrusive spacer
      }
      else
      {
          mistakes += MISTAKE_MARKER;
      }
    }
    return mistakes;
}

/*
 * This function displays the keyed sign groups and the copied sign groups
 * alongside each other, accompanied by markers which indicate the positions
 * of the copying mistakes.
 */
void display_comparison(const unsigned int num_groups, const unsigned int len_group,
                        const string& keyed_string, const string& copied_string)
{
    // how many feedback cells fit horizontally
    // The width of the feedback cell for one sign group consists of:
    //             1 empty position to separate the cells
    // COUNTER_WIDTH positions for the counter
    //             1 position between the counter and the sign group
    //        strlen positions for the sign group
    unsigned int columns = TERMINAL_WIDTH / (2+COUNTER_WIDTH+len_group);

    // indentation strings
    string indent = string(COUNTER_WIDTH + 2, ' ');
    string legend_indent = string( string(cmpmsg_group).length() + 2, ' ');

    // display feedback category "title"
    cout<<endl<<cmpmsg_title<<':'<<endl;

    // print feedback legend
    // e.g. ##:Mistakes - marked with '!'
    //         Keyed signs - what was transmitted
    //         Copied signs - what you have input
    cout<<' '<<cmpmsg_group<<':';
    cout<<cmpmsg_mistakes<<" '"<<MISTAKE_MARKER<<'\''<<endl;
    cout<<legend_indent<<cmpmsg_keyed<<endl;
    cout<<legend_indent<<cmpmsg_copied<<endl;
    cout<<endl;

    // temporary variables for manipulating sign groups
    string keyed_signs;
    string copied_signs;
    string mistaken_signs;

    // temporary variables for preparing output lines
    ostringstream keyed_row;
    ostringstream copied_row;
    ostringstream mistaken_row;

    // indices
    unsigned int n;     // tracks sign groups

    // process full feedback cell rows
    for(unsigned int i=0; i<num_groups/columns; i++)
    {
      for(unsigned int j=0; j<columns; j++)
      {
          n = i*columns + j;

          // retrieve sign groups
          keyed_signs  =  keyed_string.substr(n*len_group,len_group);
          copied_signs = copied_string.substr(n*len_group,len_group);
          // compute mistake pattern
          mistaken_signs = mark_mistakes(len_group, keyed_signs, copied_signs);

          // append cell to output lines
          mistaken_row << " ";
          mistaken_row.width(COUNTER_WIDTH);
          mistaken_row << (n+1) << ":" << mistaken_signs;
          keyed_row << indent << keyed_signs;
          copied_row << indent << copied_signs;
      }

      // display output lines
      // e.g. 12:!.!..!!
      //         eishtmo
      //         aibhtcd
      cout << mistaken_row.str() << endl;
      cout << keyed_row.str() << endl;
      cout << copied_row.str() << endl;
      cout << endl;

      // reset output lines
      keyed_row.clear();
      copied_row.clear();
      mistaken_row.clear();
    }

    // process leftover fedback cells
    for(n=num_groups-num_groups%columns; n<num_groups; n++)
    {
      // retrieve sign groups
      keyed_signs  =  keyed_string.substr(n*len_group,len_group);
      copied_signs = copied_string.substr(n*len_group,len_group);
      // compute mistake pattern
      mistaken_signs = mark_mistakes(len_group, keyed_signs, copied_signs);

      // append cell to output lines
      mistaken_row << " ";
      mistaken_row.width(COUNTER_WIDTH);
      mistaken_row << (n+1) << ":" << mistaken_signs;
      keyed_row << indent << keyed_signs;
      copied_row << indent << copied_signs;
    }

    // display any leftover feedback cells
    if(num_groups%columns)
    {
      // display rows
      cout << mistaken_row.str() << endl;
      cout << keyed_row.str() << endl;
      cout << copied_row.str() << endl;
      cout << endl;
    }
}

/*
 * This function displays information about how well an exercise was
 * completed. Its goal is to help the user discover the areas where
 * improvement is possible.
 */
void display_feedback(const unsigned int percentage,
                      const libexercises::Classic& current_exercise,
                      const string& copied_string)
{
    // introduce the feedback information
    // e.g. "Evaluation of your skills"
    cout<<endl<<fbkmsg_title << endl;

    // display overall success rate
    display_overall_rate(percentage);

    // the string that should have been copied
    string keyed_string = current_exercise.get_string();

    // display success rate per keyed symbol
    display_symbol_rate(keyed_string, copied_string);

    // how many sign groups there are in total
    unsigned int num_groups = current_exercise.len();

    // the number of sign groups that were keyed
    unsigned int group_len = current_exercise.string_len();

    // display comparison between keyed and copied sign groups
    display_comparison(num_groups, group_len, keyed_string, copied_string);
}

/*
 * This function lets the user input the copied sign groups and displays
 * feedback about how it went.
 */
unsigned int check(const libexercises::Classic& current_exercise)
{
    string catched_strings;

    cout<<endl<<chkmsg_1 << endl;
    cout<<chkmsg_2 << endl;

    for(unsigned int i=0; i<current_exercise.len(); i++)
    {
      string tmp;
      cout.width(COUNTER_WIDTH);
      cout<<(i+1) << ": ";
      cin>>tmp;
      catched_strings += tmp;
    }

    unsigned int catched = current_exercise.verify(catched_strings);

    // show results to the user
    display_feedback(catched, current_exercise, catched_strings);

    return catched;
}

Generated by  Doxygen 1.6.0   Back to index