// check_answers.cgi: applicazione per controllare i punteggi e memorizzare le risposte
// dei test.
#include
#include "applicat.h"
#include "questionnaire.h"
class Check_answers_Application : public Application
{
private:
String _dbname;
String _utente; // Utente corrente
String _modulo; // Numero del modulo del quale controllare le risposte
String _testnum; // Numero del test del quale controllare le risposte
PgEnv _environment;
bool _blank_test;
String _user_answers;
Questionnaire _questionario;
PgTransaction *_db;
protected:
virtual bool create();
virtual bool destroy();
virtual void main_func();
void check_answers();
void print_access_error();
bool load_corrector();
public:
Check_answers_Application()
{
_db = NULL;
}
virtual ~Check_answers_Application() {};
};
bool Check_answers_Application::create()
{
String separator, ws;
String qs[3];
char answers[MAXQUESTIONS][MAXANSWERS];
for (int i=0; iLunghezza del buffer: " << cl << "
" << endl;
#endif
if (cl < 8192) { // Evita di ricevere troppa roba sullo stdin (8kb sono abbastanza??)
for (int x = 0; cl && (!feof(stdin)); x++) {
t1 = fmakeword(stdin, '&', &cl);
t2 = makeword(t1, '=');
unescape_url(t1);
unescape_url(t2);
if (!strcmp(t2,"MODULO"))
_modulo = t1;
if (!strcmp(t2,"TESTNUM"))
_testnum = t1;
if (!strcmp(t2,"BLANK_TEST"))
_blank_test = !strcmp(t1,"ON");
// Carica le risposte fornite
if (t2[0] == 'Q') { // Si tratta di una risposta del test; formato Q__
// Estrae il numero relativo alla domanda ed il numero della risposta
ws = t2;
const int e = split(ws, qs, 3, separator);
if (e == 3) {
const int qnum = atoi(qs[1]) - 1; // riferimento alla domanda
const int anum = atoi(qs[2]) - 1; // riferimento alla risposta
if (qnum < MAXQUESTIONS && anum < MAXANSWERS)
if (!strcmp(t1,"ON"))
answers[qnum][anum] = 'V';
}
}
}
// Compone _user_answers
for (int i=0; iRisposte fornite
" << endl;
for (int j = 0; j < MAXQUESTIONS; j++) {
cout << "Domanda " << j+1 << ":
";
for (int k = 0; k < MAXANSWERS; k++)
if (answers[j][k] == 'V')
cout << "VERO ";
else
cout << "FALSO ";
cout << "
" << endl;
}
return FALSE;
#endif
}
else {
cout << "Troppi dati inviati
" << endl;
cout << "L'applicazione ha ricevuto troppi dati sul buffer d'ingresso.
" << endl;
return FALSE;
}
return TRUE;
}
bool Check_answers_Application::destroy()
{
print_footer();
return TRUE;
}
bool Check_answers_Application::load_corrector()
{
bool loaded = FALSE;
String command, correct_answers, separator;
separator = ";";
command = "SELECT * FROM CORRETTORI WHERE modulo=";
command += _modulo;
command += " AND testnum='";
command += _testnum;
command += "'";
_db->ExecCommandOk(command);
const int tuples = _db->Tuples();
if (tuples > 0) {
correct_answers = _db->GetValue(0, "risposte");
loaded = _questionario.load(correct_answers, _user_answers);
}
return loaded;
}
void Check_answers_Application::check_answers()
{
if (!load_corrector()) {
cout << "Correttore inesistente
" << endl;
cout << "Impossibile caricare il correttore per il test immesso.
";
cout << "Rivolgersi al docente della lezione odierna.
";
return;
}
// 1 of theze dayz I'll fall to pieces anywayz
String command, verifiche, corso;
// Compone la stringa di selezione utente.
command = "SELECT * FROM UTENTI WHERE loginname='";
command += _utente;
command += "' AND logged='t'";
// Esegue il comando SQL, dovrebbe venir ritornata una sola tupla
// al limite se ne vengono ritornate piu' di una verranno ignorate
_db->ExecCommandOk(command);
const int tuples = _db->Tuples();
if (tuples > 0) {
// Aggiorna lo stato dei test effettuati per modulo sulla tabella UTENTI
verifiche = _db->GetValue(0, "verifiche");
corso = _db->GetValue(0, "course");
trim(corso);
const unsigned int mod_int = atoi(_modulo);
const unsigned int l = verifiche.length();
if ((l < mod_int || verifiche[mod_int-1] != _testnum[0]) && mod_int <= MAXMODULES) {
if (l< mod_int)
for (unsigned int j=l; j < mod_int; j++)
verifiche += ' ';
verifiche[mod_int-1] = _testnum[0];
command = "UPDATE UTENTI SET verifiche='";
command += verifiche;
command += "' WHERE loginname='";
command += _utente;
command += "'";
_db->ExecCommandOk(command);
// Controlla i punteggi inseriti nella matrice con quelli memorizzati nel correttore
// Compone le risposte fornite da memorizzare sulla tabella VERIFICHE in un formato più "umano"
Rational punteggio;
punteggio = _blank_test ? ZERO : _questionario.calc_score();
long progressivo = 0L;
// Blocca la tabella dei progressivi e prende il progressivo
command = "LOCK PROGRESSIVI";
_db->ExecCommandOk(command);
command = "SELECT * FROM PROGRESSIVI";
if (_db->ExecTuplesOk(command) && _db->Tuples() > 0){
progressivo = atol(_db->GetValue(0, "progverifiche"));
}
else { // Se non c'è nessuna riga viene aggiunta
command = "INSERT INTO PROGRESSIVI VALUES(0,0)";
_db->ExecCommandOk(command);
}
progressivo++;
command = "UPDATE PROGRESSIVI SET progverifiche=progverifiche+1"; // Incrementa il progressivo
_db->ExecCommandOk(command); // Aggiorna la tabella PROGRESSIVI
// Memorizza il punteggio e le risposte fornite sulla tabella VERIFICHE
command = "INSERT INTO VERIFICHE VALUES (";
command += ltoa(progressivo);
command += ",'";
command += _utente;
command += "',current_timestamp,";
command += _modulo;
command += ",'";
command += _testnum;
command += "','";
if (_blank_test)
command += " " ;
else
command += _user_answers; // Risposte fornite in formato "umano"
command += "',";
command += dtoa((double) punteggio); // Punteggio sottoforma di double
command += ")";
_db->ExecCommandOk(command);
if (_modulo=="1") // (23/01/01) Il modulo 1 é "speciale" in quanto non ha alcun test; é il modulo di
cout << "" << endl; // formazione del tecnico contabile di Eurocampo
else
cout << "Risultato del test
" << endl;
if (!_blank_test)
_questionario.dump_html(corso, atoi(_modulo), _testnum[0]);
else
{
if(_modulo=="1") // (23/01/01) solito modulo 1 speciale
cout << "Benvenuti nel modulo per la formazione del TECNICO CONTABILE
";
else
cout << "
Test consegnato in bianco
";
}
cout << "
" << endl;
}
else { // Se il test è già stato eseguito, nega l'aggiornamento il calcolo punteggio e tutto il resto
cout << "Test già eseguito
" << endl;
cout << "Il test selezionato risulta già eseguito.
";
cout << "Si prega di riselezionare l'area corretta dalla pagina di selezione moduli.
";
}
}
else { // Se non trova i dati dell'utente indicato
// visualizza la mancanza di informazioni per completare la pagina.
cout << "Mancanza di informazioni
" << endl;
cout << "Impossibile reperire le informazioni relative al percorso formativo dell'utente " << _utente;
cout << ".
Controllare l'esattezza delle informazioni inserite.
";
}
return;
}
void Check_answers_Application::print_access_error()
{
cout << "Errore di accesso
";
cout << "Utilizzare la normale procedura di accesso ai corsi.
";
}
void Check_answers_Application::main_func()
{
// Controllo utente: se il CGI viene chiamato senza tutte le indicazioni necessarie
// visualizza l'errore
if (_utente.empty() || _modulo.empty() || _testnum.empty() || _user_answers.empty()) {
print_access_error();
return;
}
// Se tutto è OK...
// Inizia la transazione
_db = new PgTransaction(_environment, _dbname);
if ( _db->ConnectionBad() )
print_database_error();
else
check_answers();
delete _db; // Termina la transazione
return;
}
int main(int argc, char* argv[])
{
Check_answers_Application* a = new Check_answers_Application();
a->run(argc, argv);
delete a;
exit(0);
}