1999-10-20 15:27:08 +00:00
|
|
|
|
// check_answers.cgi: applicazione per controllare i punteggi e memorizzare le risposte
|
|
|
|
|
// dei test.
|
|
|
|
|
|
|
|
|
|
#include <libpq++.h>
|
|
|
|
|
#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:
|
2000-03-02 15:26:30 +00:00
|
|
|
|
Check_answers_Application()
|
|
|
|
|
{
|
|
|
|
|
_db = NULL;
|
|
|
|
|
}
|
1999-10-20 15:27:08 +00:00
|
|
|
|
virtual ~Check_answers_Application() {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Check_answers_Application::create()
|
|
|
|
|
{
|
|
|
|
|
String separator, ws;
|
|
|
|
|
String qs[3];
|
|
|
|
|
char answers[MAXQUESTIONS][MAXANSWERS];
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<MAXQUESTIONS; i++)
|
|
|
|
|
for (int j=0; j<MAXANSWERS; j++)
|
|
|
|
|
answers[i][j] = 'F';
|
|
|
|
|
|
|
|
|
|
_user_answers = "";
|
|
|
|
|
separator = "_";
|
|
|
|
|
_dbname = POSTGRES_DB;
|
|
|
|
|
_environment.Port(POSTGRES_PORT);
|
|
|
|
|
_environment.Host(POSTGRES_HOST);
|
|
|
|
|
print_header("Controllo punteggi");
|
|
|
|
|
_utente = getenv("REMOTE_USER");
|
|
|
|
|
_blank_test = FALSE;
|
|
|
|
|
char *t1, *t2;
|
|
|
|
|
char *ccc = getenv("CONTENT_LENGTH");
|
|
|
|
|
int cl = ccc != NULL ? atoi(ccc) : 0;
|
|
|
|
|
|
|
|
|
|
#ifdef DBG
|
|
|
|
|
cout << "<BR>Lunghezza del buffer: " << cl << "<BR>" << 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_<numero_domanda>_<numero_risposta>
|
|
|
|
|
// 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; i<MAXQUESTIONS; i++) {
|
|
|
|
|
_user_answers += "Q_";
|
|
|
|
|
_user_answers += itoa(i+1);
|
|
|
|
|
_user_answers += "=";
|
|
|
|
|
for (int j=0; j<MAXANSWERS; j++)
|
|
|
|
|
_user_answers += answers[i][j];
|
|
|
|
|
_user_answers += ";";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Debug stuff, useful in many wayz
|
|
|
|
|
#ifdef DBG
|
|
|
|
|
cout << "<H2>Risposte fornite</H2><BR><BR>" << endl;
|
|
|
|
|
for (int j = 0; j < MAXQUESTIONS; j++) {
|
|
|
|
|
cout << "Domanda " << j+1 << ":<BR>";
|
|
|
|
|
for (int k = 0; k < MAXANSWERS; k++)
|
|
|
|
|
if (answers[j][k] == 'V')
|
|
|
|
|
cout << "VERO ";
|
|
|
|
|
else
|
|
|
|
|
cout << "FALSO ";
|
|
|
|
|
cout << "<BR>" << endl;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
cout << "<H2>Troppi dati inviati</H2><BR><BR>" << endl;
|
|
|
|
|
cout << "<P>L'applicazione ha ricevuto troppi dati sul buffer d'ingresso.</P><BR>" << 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 << "<H2>Correttore inesistente</H2><BR><BR>" << endl;
|
|
|
|
|
cout << "<P>Impossibile caricare il correttore per il test immesso.</P>";
|
|
|
|
|
cout << "<P>Rivolgersi al docente della lezione odierna.</P>";
|
|
|
|
|
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<70> "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'<27> 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cout << "<H2>Risultato del test</H2><BR><BR>" << endl;
|
|
|
|
|
if (!_blank_test)
|
|
|
|
|
_questionario.dump_html(corso, atoi(_modulo), _testnum[0]);
|
|
|
|
|
else
|
|
|
|
|
cout << "<P>Test consegnato <STRONG> in bianco </STRONG><BR><BR><BR>";
|
|
|
|
|
|
|
|
|
|
cout << "<TABLE><TR><TD><FORM METHOD=\"POST\" ACTION=";
|
|
|
|
|
cout << GET_MODULE_CGI << ">";
|
|
|
|
|
cout << "Cliccate sull'icona qui sotto per ritornare all'area formativa del modulo.";
|
|
|
|
|
cout << "<BR><BR><INPUT TYPE=HIDDEN NAME=\"MODULO\" VALUE=\"" << _modulo << "\">";
|
|
|
|
|
cout << "<INPUT TYPE=\"IMAGE\" SRC=\"/images/area_" << mod_int;
|
|
|
|
|
cout << ".gif\" ALIGN=top ALT=\"Accesso al modulo\" BORDER=0>";
|
|
|
|
|
cout << "</FORM></TD></TR></TABLE></P>" << endl;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else { // Se il test <20> gi<67> stato eseguito, nega l'aggiornamento il calcolo punteggio e tutto il resto
|
|
|
|
|
cout << "<H2>Test gi<67> eseguito</H2><BR><BR>" << endl;
|
|
|
|
|
cout << "<P>Il test selezionato risulta gi<67> eseguito.</P>";
|
|
|
|
|
cout << "<P>Si prega di riselezionare l'area corretta dalla pagina di <A HREF=\"";
|
|
|
|
|
cout << LOGIN_CGI << "\">selezione moduli.</A></P>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else { // Se non trova i dati dell'utente indicato
|
|
|
|
|
// visualizza la mancanza di informazioni per completare la pagina.
|
|
|
|
|
cout << "<H2>Mancanza di informazioni</H2><BR><BR>" << endl;
|
|
|
|
|
cout << "<P>Impossibile reperire le informazioni relative al percorso formativo dell'utente " << _utente;
|
|
|
|
|
cout << ".</P><P>Controllare l'esattezza delle informazioni inserite.</P>";
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Check_answers_Application::print_access_error()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
cout << "<H2>Errore di accesso</H2><BR><BR>";
|
|
|
|
|
cout << "<P>Utilizzare la normale procedura di <A HREF=\"";
|
|
|
|
|
cout << LOGIN_CGI << "\">accesso</A> ai corsi.</P><BR>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 <20> 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|