<!--
<?php

/*Οι παρακάτω γραμμές διαβάζουν κάποια από τα δεδομένα αυτού του SCO για αυτό το μαθητή και τα διαθέτουν στο script μέσα στη μεταβλητή $LMSToSCOValues.*/
$result = eF_getTableData("scorm_data", "*", "users_LOGIN = '".$_SESSION['s_login']."' AND content_ID = '".$_GET['view_unit']."'");
$LMSToSCOValues = $result[0];

/*Οι παρακάτω γραμμές διαβάζουν τα καθολικά δεδομένα αυτού του SCO και τα διαθέτουν στο script μέσα στη μεταβλητή $SCOValues.*/
$result = eF_getTableData("scorm_data", "*", "users_LOGIN is null AND content_ID = '".$_GET['view_unit']."'");
$SCOValues = $result[0];

$SCOState = 'var SCOState = new Array();';
foreach ($SCOValues as $key => $value)
{
    $SCOState .= "SCOState['$key'] = '$value';";//echo "alert('LMS User Set: SCOState[$key] = $value');";
}
foreach ($LMSToSCOValues as $key => $value)
{
    //Το σκορ πρέπει να μηδενίζεται κάθε φορά που κάνουμε το SCO: O καθηγητής έχει άλλες μεθόδους να το δει.
    if ($key == 'score')
        $value = 0;
    $SCOState .= "SCOState['$key'] = '$value';";//echo "alert('LMS Set: SCOState[$key] = $value');";
}

echo $SCOState;

?>

//for (x in SCOState) {
  //alert('x: '+x+' SCOState: '+SCOState[x]);
//}

/*Αρχικοποιήσεις του LMS. Εκτός των άλλων, αναθέτουμε τις συναρτήσεις LMS στο API adapter και αρχικοποιούμε
  το data model (cmi).*/
var _DEBUG = 0;
var _TEMP  = '';
var _TEMP2  = '';

myInitError();
myCurrentState = -1;
commitArray    = new Array();
window.API     = API;
cmi            = new myCmi();


API.LMSInitialize     = LMSInitialize;
API.LMSFinish         = LMSFinish;
API.LMSGetValue       = LMSGetValue;
API.LMSSetValue       = LMSSetValue;
API.LMSCommit         = LMSCommit;
API.LMSGetLastError   = LMSGetLastError;
API.LMSGetErrorString = LMSGetErrorString;
API.LMSGetDiagnostic  = LMSGetDiagnostic;

/**
* Η συνάρτηση αυτή είναι ο API adapter. Σε αυτόν ανατίθενται οι συναρτήσεις του LMS,
* οι οποίες ορίζονται παρακάτω, έτσι ώστε το περιεχόμενο να μπορεί να τις προσπελάσει.
*/
function API(){}

/*
########################## LMS Functions ################################

Οι συναρτήσεις αυτές αποτελούν υλοποίηση των συναρτήσεων του πρωτοκόλλου.
Ωστόσο, οι περισσότερες αναθέτουν την πραγματική λειτουργία σε βοηθητικές
συναρτήσεις με παρόμοιο όνομα. Όλες καλούν αρχικά τη myInitError(), η οποία
θέτει τον κωδικό σφάλματος του LMS σε 0. Αυτό γίνεται γιατί κάθε νέα κλήση
σε μία συνάρτηση του LMS, θέτει ένα νέο κωδικό σφάλματος. Αυτός παραμένει 0
αν δεν συμβεί κάτι στραβό στην πορεία.

#########################################################################
*/

/**
* Αρχικοποίηση του μαθήματος.
*/
function LMSInitialize(parameter)
{
    myInitError();

    try {
        return_value  = myInitialize(parameter);
    } catch(e) {
        myErrorHandler(e);
    } finally {
        if (_DEBUG) alert("Function: LMSInitialize \nArgument: '"+parameter+"' \nReturnes: '"+return_value+"'");
        //alert('LMSInitialize Error code: '+myErrorNumber);
        return return_value;
    }
}

/**
* Τερματισμός του μαθήματος.
*/
function LMSFinish(parameter)
{
    myInitError();

    try {
        return_value  = myFinish(parameter);
    } catch(e) {
        myErrorHandler(e);
    } finally {
        if (_DEBUG) alert("Function: LMSFinish \nArgument: '"+parameter+"' \nReturnes: '"+return_value+"'");
        //alert('LMSFinish Error code: '+myErrorNumber);
        return return_value;
    }
}

/**
* Επιστρέφει την τιμή της παραμέτρου.
*/
function LMSGetValue(parameter)
{
    myInitError();

    return_value  = myGetValues(parameter);

    if (_DEBUG) alert("Function: LMSGetValue \nArgument: '"+parameter+"' \nReturns: '"+return_value+"'");
    //alert('LMSGetValue Error code: '+myErrorNumber);
    return return_value;
}

/**
* Θέτει την τιμή της παραμέτρου parameter σε value.
*/
function LMSSetValue(parameter, value)
{
    //if (parameter == 'cmi.interactions.2.latency' && value = '03:01:39:52') _DEBUG = 1;
    myInitError();

    return_value  = mySetValues(parameter, value);

    if (_DEBUG) alert("Function: LMSSetValue \nArgument: '"+parameter+"' \nSet Value: '"+value+"' \nReturns: '"+return_value+"'");
    //alert('LMSSetValue Error code: '+myErrorNumber);
    return return_value;
}

/**
* Δίνει εντολή στο LMS να καταχωρίσει όλες τις παραμέτρους του μαθήματος.
*/
function LMSCommit(parameter)
{
    myInitError();
    return_value = myCommit(parameter);

    if (_DEBUG) alert("Commit! Parameter: "+parameter+" Returnes value: "+return_value);
    //alert('LMSCommit Error code: '+myErrorNumber);
    return return_value;
}

/**
* Επιστρέφει τον κωδικό αριθμό του τελευταίου σφάλματος.
*/
function LMSGetLastError()
{
    if (_DEBUG) alert("GetLastError: "+myErrorNumber);
    return myErrorNumber;
}

/**
* Επιστρέφει μία περιγραφή του σφάλματος με κωδικό errorNumber.
*/
function LMSGetErrorString(errorNumber)
{
    if (_DEBUG) alert("GetErrorString");
    return myGetErrorString(errorNumber);
}

/**
* Επιστρέφει μία αναλυτικότερη περιγραφή του σφάλματος errorNumber.
*/
function LMSGetDiagnostic(errorNumber)
{
    if (_DEBUG) alert("LMSGetDiagnostic with errorNumber: "+errorNumber);

    if (errorNumber == "") {
        return myErrorDiagnostic;
    } else {
        return myGetDiagnostic(errorNumber);
    }
}


/*
########################## Συναρτήσεις my* ##############################

Οι παρακάτω συναρτήσεις υλοποιούν τη λειτουργικότητα των αντίστοιχων συναρτήσεων
του LMS. Κάθε συνάρτηση ελέγχει καταρχάς την κατάσταση του LMS. Οι δυνατές
καταστάσεις είναι "Δεν έχει εκκινηθεί", "Έχει εκκινηθεί", "Έχει τερματίσει" με
διαφορετικές έγκυρες κλήσεις συναρτήσεων η κάθε μία.

#########################################################################
*/

/**
* Αρχικοποίηση του LMS. Θέτει την κατάσταση του LMS (myCurrentState) σε 0 (Έχει εκκινηθεί).
* Η μόνη έγκυρη παράμετρος είναι η "". Επιστρέφει true/false.
*/
function myInitialize(parameter)
{
    return_value = "false";

    if (parameter != '')
    {
        throw new myError ('201', 'Non-Empty parameter');
    }

    if (myCurrentState != -1 & myCurrentState != 1)
    {
        throw new myError('101', 'LMS not initialized');
    }
    else
    {
        myCurrentState = 0;
        return_value  = "true";
    }

    return return_value;
}

/**
* Τερματισμός του LMS. Θέτει την κατάσταση του LMS σε 1 (Έχει τερματίσει).
* Δέχεται μόνο την παράμετρο "" και επιστρέφει true/false
*/
function myFinish(parameter)
{
    //alert(myCurrentState);
    return_value = "false";


    if (parameter != '')                    //*edw kati san setDiagnostic
    {
        throw new myError ('201', 'Non-Empty parameter');
    }

    if (myCurrentState != 0 && myCurrentState != 1)
    {
        throw new myError('301', 'LMS not initialized');
    }
    else                                    //*edw kati san setDiagnostic
    {
        /*1. καθορισμός του cmi.core.lesson_status*/
        if (!(SCOState['lesson_status']))
        {
            if (SCOState['masteryscore'])
            {
                if (cmi.core.score.raw.get() < SCOState['masteryscore'])
                {
                    SCOState['lesson_status'] = 'failed';
                    cmi.core.lesson_status.set('failed');
                }
                else
                {
                    SCOState['lesson_status'] = 'passed';
                    cmi.core.lesson_status.set('passed');
                }
            }
            else
            {
                SCOState['lesson_status'] = 'completed';
                cmi.core.lesson_status.set('completed');
            }
        }

        /*2. καθορισμός του cmi.core.entry.*/
        var exit = SCOState['exit'];
        switch (exit)
        {
            case 'time-out':
                SCOState['entry'] = '';
                break;
            case 'suspend':
                SCOState['entry'] = 'resume';
                break;
            case 'logout':
                SCOState['entry'] = '';
                break;
            case '':
                SCOState['entry'] = '';
                break;
            default:
                SCOState['entry'] = '';
                break;
        }

        /*3, Καθορισμός cmi.core.total_time*/
        if (SCOState['session_time'] && SCOState['session_time'] != '' )
        {
            SCOState['total_time'] = SCOState['session_time'];          //ΠΡΟΣΟΧΗ: Αυτή η τιμή δεν αντιστοιχεί πλέον στο total_time. Απλώς βολεύει να την πάρουμε εδώ. μόλις λοιπόν κληθεί η LMSFinish() (και ανεξάρτητα από το αν έχει κληθεί προηγουμένως η LMSCommit()), παίρνουμε το τρέχον session time Και το βάζουμε σε αυτήν τη μεταβλητή. Στη συνέχεια, αυτή στέλνετε στο LMSCommitpage.php, το οποίο τη χειρίζεται ανάλογα
        }

        myCommit('finish');
        myCurrentState = 1;
        return_value  = "true";
    }



    return return_value;
}

/**
* Επιστρέφει την τιμή της παραμέτρου property, ή false αν συμβεί κάποιο σφάλμα.
*/
function myGetValues(property)
{
    var return_value = "";
    try {
        checkState();
        property = checkParameter(property);//alert("PROPERTY: "+property);
        eval('return_value = ' + property + '.get()');
    } catch (e) {
        myErrorHandler(e);
    } finally {
        return return_value;
    }
}

/**
* Θέτει την τιμή της παραμέτρου property σε value. Επιστρέφει true/false
*/
function mySetValues(property, value)   //throw new myError(0);
{
//
    var return_value = "false";

    try {
        checkState();
        property = checkParameter(property);
//      alert('property: '+property+' value: '+ value); //alert('return_value = ' + property + '.set('+value+')');
        eval('return_value = ' + property + '.set(value)')
    } catch (e) {
        myErrorHandler(e);
    } finally {
        return return_value;
    }
}

/**
* Δίνει εντολή στο LMS να αποθηκεύσει τις τιμές των παραμέτρων.
* Δέχεται μόνο την παράμετρο "" και επιστρέφει true/false.
*/
function myCommit(parameter)
{
    var return_value = "false";

    if (parameter != '' && parameter != 'finish')                                   //'finish' parameter indicates that myCommit was called from myFinish, so it may persist total_time as well
    {
        myErrorHandler(new myError('201', 'Non-Empty parameter'));
        return return_value;
    }
    else
    {
        try {
            checkState();

            /*Αποθηκεύουμε δεδομένα;*/
            SCOState['credit'] = cmi.core.credit.get();

            commitArray = SCOState;

            commitParameters = '';
            /*O commitArray περιέχει τις μεταβλητές που πρέπει να γίνουν commit. Αυτές γίνονται μία σειρά από get parameters, οι οποίες μεταφέρονται στη σελίδα LMSCommitPage.php*/
            for (mykey in commitArray)
            {
                //alert('key: '+mykey+' value: '+commitArray[mykey]);
                //alert(parent.document.getElementById('lesson_status'));
                //if (mykey == 'total_time' && myCurrentState != 1) {
                //  continue;
                //}

                if (mykey != 'total_time' || parameter == 'finish') {
                    parent.document.getElementById(mykey).value = commitArray[mykey];
                }

                //commitParameters += '&' + mykey + '=' + commitArray[mykey];
            }
            //alert('myCurrentState: '+myCurrentState+' caller: '+myCommit.arguments+' total_time: '+commitArray['total_time']+ ' session time: '+commitArray['session_time']);
            <?php
                if ( $_GET['view_unit'] ) {
                    echo "parent.document.getElementById('content_ID').value = ".$_GET['view_unit'].";";
                }
            ?>
            parent.document.scorm_form.submit();

            //commitParameters += '&' +'content_ID=' <?php if ( $_GET['content_ID'] ) echo '+'.$_GET['content_ID'];?>;
            //alert(commitParameters);
            /*Άνοιξε ένα παράθυρο και στείλε τα δεδομένα με GET για να αποθηκευθούν στη βάση*/
            //commitPage = window.open("/LMSCommitPage.php?" + commitParameters, "commitPage", 'scrollbars=no, resizable=no, toolbar=no, menubar=no, status=no, location=no, height=5,width=5');

            //commitPage = window.open("/LMSCommitPage.php?" + commitParameters, "commitPage", 'scrollbars=yes, resizable=yes, toolbar=no, menubar=no, status=no, location=no, height=700,width=300');

            /*Κλείσε το παράθυρο αυτό*/
            //commitPage.blur();
            //commitPage.close();

            return_value = "true";
        } catch (e) {
			//alert(e);
            myErrorHandler(e);
        } finally {
            return return_value;
        }
    }
}


/**
* Επιστρέφει το μήνυμα που αντιστοιχεί στο errrorNumber.
*/
function myGetErrorString(errorNumber)
{
    var errorStrings    = new Array();
    errorStrings['0']   = 'No Error';
    errorStrings['101'] = 'General exception';
    errorStrings['201'] = 'Invalid argument error';
    errorStrings['202'] = 'Element cannot have children';
    errorStrings['203'] = 'Element not an array - cannot have count';
    errorStrings['301'] = 'Not initialized';
    errorStrings['401'] = 'Not implemented error';
    errorStrings['402'] = 'Invalid set value, element is a keyword';
    errorStrings['403'] = 'Element is read only';
    errorStrings['404'] = 'Element is write only';
    errorStrings['405'] = 'Incorrect Data Type';

    if (errorNumber == '') {                                                    //No arguments were given, so no error is reported (this is basically to comply with the case where the function is called before LMSInitialize())
        return '';
    } else if ((typeof errorStrings[errorNumber]) == 'undefined') {             //If the error code is not valid, do nothing really
        return errorStrings[0];
    } else {
        return errorStrings[errorNumber];
    }

}

/**
* Επιστρέφει ένα custom μήνυμα που αντιστοιχεί στο errorNumber, ή το μήνυμα που αντιστοιχεί στο τρέχον σφάλμα, αν η παράμετρος είναι το "".
*/
function myGetDiagnostic(errorNumber)
{
    var errorDiagnostic    = new Array();
    errorDiagnostic['0']   = 'Succesful operation. There were no errors';
    errorDiagnostic['101'] = 'A general fault occured - General exception';
    errorDiagnostic['201'] = 'You cannot set such value - Invalid argument error';
    errorDiagnostic['202'] = 'This element cannot have children - Element cannot have children';
    errorDiagnostic['203'] = 'This element is not an array - Element not an array - cannot have count';
    errorDiagnostic['301'] = 'System has to be initialized - Not initialized';
    errorDiagnostic['401'] = 'This property is not implemented - Not implemented error';
    errorDiagnostic['402'] = 'You cannot set a value to a keyword - Invalid set value, element is a keyword';
    errorDiagnostic['403'] = 'You can only read this element\'s value - Element is read only';
    errorDiagnostic['404'] = 'You can only write this element\'s value - Element is write only';
    errorDiagnostic['405'] = 'You cannot set this element to this value - Incorrect Data Type';

    if (errorNumber == "") errorNumber = myErrorNumber;

    return errorDiagnostic[errorNumber];
}


/*
######################## Βοηθητικές Συναρτήσεις #########################

Οι συναρτήσεις αυτές υλοποιούν επιπλέον λειτουργίες που απαιτεί το LMS.
Σχετίζονται κυρίως με τη διαχείριση σφαλμάτων.

#########################################################################
*/

/**
* Ελέγχει την κατάσταση του LMS. Αν δεν είναι 0, δηλαδή αρχικοποιημένο, τότε πετάει λάθος.
*/
function checkState()
{
    if (myCurrentState != 0)
    {
        throw new myError('301');
    }
}

/**
* Ελέγχει αν υλοποιείται η συγκεκριμένη παράμετρος.
*/
function checkParameter(property)
{
    /*Παρακάτω γίνεται η κατάλληλη διαχείριση του property ώστε να μπορεί να αντιμετωπίσει strings του στυλ "cmi.interactions.1.objectives.0.id" */
    str = property;
    str_split = property.split(".");

    if (!isNaN(parseInt(str_split[2])))
    {
        k = 3;      //To k χρησιμοποιείται για να διαχωριστεί η περίπτωση του cmi.interactions.1.objectives.0.id από το cmi.interactions.1.id
        str = str_split[0]+'.'+str_split[1]+'['+str_split[2]+']';
        /*Αν έχει οριστεί ήδη το object, μην το ξαναορίσεις*/

        if (eval('typeof '+str_split[0]+'.'+str_split[1]) == 'undefined')
        {
            throw new myError('201');
        }
        _TEMP = str_split[2];                                                       //This is used to signify globally the current index

        if (!(eval(str)))
        {
            var current_length = eval(str_split[0]+'.'+str_split[1]+'.length');     //Check if the siginified index is sequential (e.g. if the last array index is 3, the designated array index must be at most 4)
            if (str_split[2] > current_length)
            {
                throw new myError('201');
            }
            else
            {
                eval(str+'= new '+str_split[1]+'Object()');
            }
        }

        if (!isNaN(parseInt(str_split[4])))
        {
            if (eval('typeof '+str+'.'+str_split[3]) == 'undefined')
            {
                throw new myError('201');
            }
            _TEMP2 = str_split[4];                                                  //This is used to signify globally the current index

            var current_length = eval(str+'.'+str_split[3]+'.length');              //Check if the siginified index is sequential (e.g. if the last array index is 3, the designated array index must be at most 4)

            str+='.'+str_split[3]+'['+str_split[4]+']';

            if (str_split[4] > current_length)
            {
                throw new myError('201');
            }
            else
            {
                eval(str+'= new '+str_split[3]+'Object()');
            }
            k = 5;
        }

        for (var i = k; i < str_split.length; i++)
        {
            str += '.'+str_split[i];
        }

        property = str;
    }

    str_split    = property.split(".");
    var temp_str = str_split[0];
    for (var i = 1; i < str_split.length; i++) {
        //alert('temp_str: '+temp_str);
        if (eval('typeof ' + temp_str) == 'undefined') {
            throw new myError('201');
        }
        temp_str = temp_str + '.' + str_split[i];
    }

    /*Έλεγξε αν η παράμετρος υπάρχει*/
    if (property == null || eval('typeof '+property) == 'undefined')
    {
        var last_element = str_split.pop();                         //Take the last element in the array
        if (last_element == '_children') {
            throw new myError('202');
        } else if (last_element == '_count') {
            throw new myError('203');
        } else {
            throw new myError('201');                               //Προσοχή γενικά με τα lists, γιατί αυτή η υλοποίηση δεν θα δουλέψει. Ίσως θα μπορούσα, για οποιοδήποτε δεν υλοποιώ, να έχω μόνο τον ορισμό του και να επιστρέφω 401 απευθείας
        }
    }

    //alert("checkParameter returned: "+property);

    return property;
}

/**
* This function checks parameters against regular expressions to verify their compliance with the data model.
* Parameter is the string to check. data_model is the model to check the parameter against, i.e. CMIDecimal.
* type is an argument used only in cases where the data model can be one of a number of different enumerations.
*/
function checkDataType(parameter, data_model, type)
{
    switch (data_model) {
        case 'CMIBlank':
            return match = /^$/.test(parameter);                        //empty string
            break;

        case 'CMIBoolean':
            return match = /^(true|false)$/.test(parameter);                //boolean, true or false
            break;

        case 'CMIDecimal':
            return match = /^-?\d+(\.\d+)?$/i.test(parameter);          //positive or negative number that may be decimal
            break;

        case 'CMIFeedback':
            switch (type) {
                case 'true-false':
                    return match = /^(0|1|t|f)$/.test(parameter);                   // Can be one of: "0", "1", "t", "f"
                    break;
                case 'choice':
                    return match = /^[a-z0-9](,[a-z0-9])*$/i.test(parameter);       //i.e. a,f,4,2,d
                    break;
                case 'fill-in':
                    return match = /^\s*.{1,255}$/i.test(parameter);                //Anything of up to 255 characters, but the spaces before the first character won't count
                    break;
                case 'numeric':
                    return match = /^-?\d+(\.\d+)?$/i.test(parameter);              //CMIDecimal
                    break;
                case 'likert':
                    return match = /^[0-9a-z]?$/i.test(parameter);                  //Single character or digit
                    break;
                case 'matching':
                    return match = /^[a-z0-9].[a-z0-9](,[a-z0-9].[a-z0-9])*$/i.test(parameter);             //Pair of identifiers, i.e. 2.s,4.2
                    break;
                case 'performance':
                    return match = /^.{0,255}$/i.test(parameter);                   //A string of at most 255 characters
                    break;
                case 'sequencing':
                    return match = /^[a-z0-9](,[a-z0-9])*$/i.test(parameter);       //same as 'choice' above
                    break;
                default:
                    return false;
                    break;
            }
            break;

        case 'CMIIdentifier':
            return match = /^\S{1,255}$/i.test(parameter);                              //A string with no white spaces
            break;

        case 'CMIInteger':
            return match = (/^[0-9]{1,5}$/i.test(parameter) && parameter <=65536);              //Integer less than or equal to 65536
            break;

        case 'CMISInteger':
            return match = (/^(\-|\+)?[0-9]{1,5}$/i.test(parameter) && parameter <= 32768 && parameter >= -32768);      //Signed integer ranging from -32768 to +32768
            break;

        case 'CMIString255':
            return match = /^.{0,255}$/i.test(parameter);               //Any character string with length at most 255
            break;

        case 'CMIString4096':
            return match = /^.{0,4096}$/i.test(parameter);              //Any character string with length at most 4096
            break;

        case 'CMITime':
            match = (/^(\d\d):(\d\d):(\d\d)(.\d{1,2})?$/i.exec(parameter));             //A point in a 24-hour clock, with an optional 1 or 2 digit decimal part in seconds
            if (match && match[1] < 24 && match[2] < 60 && match[3] < 60)
            {
                return true;
            }
            else
            {
                return false;
            }
            break;

        case 'CMITimespan':
            return match = /^\d{2,4}:\d\d:\d\d(.\d{1,2})?$/i.test(parameter);           //A timespan, in the form HHHH:MM:SS.SS
            break;

        case 'CMIVocabulary':
            switch (type) {
                case 'Mode':
                    return match = /^(normal|review|browse)$/.test(parameter);
                    break;
                case 'Status':
                    return match = /^(passed|completed|failed|incomplete|browsed|not attempted)$/.test(parameter);
                    break;
                case 'Exit':
                    return match = /^(time-out|suspend|logout|^)$/.test(parameter);
                    break;
                case 'Credit':
                    return match = /^(credit|no-credit)$/.test(parameter);
                    break;
                case 'Entry':
                    return match = /^(ab-initio|resume|^)$/.test(parameter);
                    break;
                case 'Interaction':
                    return match = /^(true-false|choice|fill-in|matching|performance|likert|sequencing|numeric)$/.test(parameter);
                    break;
                case 'Result':
                    return match = /^(correct|wrong|unanticipated|neutral|(-?\d+(\.\d+)?))$/.test(parameter);
                    break;
                case 'TimeLimitAction':
                    return match = /^(exit,message|exit,no message|continue,message|continue,no message)$/.test(parameter);
                    break;
                default:
                    return false;
                    break;
            }

        default:
            return false;
            break;
    }

}

/**
* Η συνάρτηση αυτή παράγει τα αντικείμενα λάθους.
*/
function myError(errorNumber, errorMessage)
{
    this.errorNumber = errorNumber;
    this.errorMessage = errorMessage;
}

/**
* Χειρίζεται τα σφάλματα, θέτοντας τα κατάλληλα μηνύματα και κωδικούς λαθών.
*/
function myErrorHandler(err)
{
    if (err instanceof myError)
    {
        myErrorNumber = err.errorNumber;
        if (err.errorMessage)
        {
            myErrorDiagnostic = err.errorMessage;
        }
        else
        {
            myErrorDiagnostic = myGetDiagnostic(err.errorNumber);
        }
    }
    else throw err;
}

/**
* Αρχικοποιεί τον κωδικό και το μήνυμα σφάλματος.
*/
function myInitError()
{
    myErrorNumber = '0';
    myErrorDiagnostic = myGetDiagnostic(myErrorNumber);
}

/*
######################### Data Model ####################################

Η παρακάτω συναρτήσεις υλοποιούν το μοντέλο δεδομένων του scorm. Κάθε
συνάρτηση αρχικοποιείται σε ένα αντικείμενο, έτσι ώστε η προσπέλαση να
γίνεται κατά τρόπο συνεπή με τη σημειολογία του scorm. Για παράδειγμα,
αν θέλουμε την τιμή της παραμέτρου cmi.core.student_name, μπορούμε να
την προσπελάσουμε με ακριβώς αυτόν τον τρόπο, αφού τόσο το cmi όσο και
το core (αλλά και το student_name) είναι αντικείμενα.

#########################################################################
*/

/**
* Cmi data model
*/
function myCmi()
{
    /**
    * To cmi.core αποτελείται από αντικείμενα στα οποία όλα τα SCOs βασίζονται και πρέπει να υλοποιούνται από όλα τα LMSs.
    */
    this.core = new function()
    {
        /**
        * Το cmi.core._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το LMS.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMIString255
        * Read Only
        *
        * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα ζχωρισμένη με κόμματα.
        */
        var _children = function()
        {
            this.get = function()      { return value;           }
            this.set = function(param) { throw new myError('402'); }

            var value = 'student_id, student_name, lesson_location, credit, lesson_status, entry, score, total_time, lesson_mode, exit, session_time';
        }

        /**
        * Το cmi.core.student_id είναι ένας identifier το οποίο περιέχει το id του χρήστη - μαθητή.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMIIdentifier
        * Read Only
        *
        * Initialization: To θέτει το LMS στο id του μαθητή.
        */
        var student_id = function()
        {
            this.get = function()      { return value;           }
            this.set = function(param) { throw new myError('403'); }

            var value = "<?php $student_id=$_SESSION['s_login']; echo $student_id; ?>";
        }

        /**
        * Το cmi.core.student_name είναι το πλήρες όνομα του χρήστη.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMIString255
        * Read Only
        *
        * Initialization: To θέτει το LMS στο όνομα του μαθητή.
        */
        var student_name = function()
        {
            this.get = function()      { return value;           }
            this.set = function(param) { throw new myError('403'); }

            <?php
                /*Πάρε το όνομα του χρήστη από τη βάση*/
                $result       = eF_getTableData('users', 'name, surname, father_name', 'login="' .$_SESSION['s_login']. '"');
                $student_name = $result[0]['surname'].', '.$result[0]['name'].' '.$result[0]['father_name'][0];
            ?>
            var value = "<?php echo $student_name; ?>";
        }

        /**
        * Το cmi.core.lesson_location είναι το σημείο όπου άφησε ο μαθητής την τελευταία φορά το SCO. Το LMS οφείλει να αποθηκεύει
        * αυτήν την τιμή και να την επιστρέφει στο SCO όταν ο μαθητής επιστρέφει στο μάθημα, αν το SCO την ζητήσει.
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: YES
        * Data Type: CMIString255
        * Read / Write
        *
        * Initialization: To LMS to θέτει στο ''. Η χρήση του είναι ευθύνη του SCO.
        */
        var lesson_location = function()
        {
            this.get = function()
            {
                //<?php /* if ( isset($LMSToSCOValues['lesson_location']) ) echo "value = '".$LMSToSCOValues['lesson_location']."';"; */ ?>
                //if (SCOState['lesson_location'] && SCOState['lesson_location'] != '' && typeof SCOState['lesson_location'] != 'undefined')
                if (typeof SCOState['lesson_location'] != 'undefined')
                {
                    value = SCOState['lesson_location'];
                }
                return value;
            }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMIString255', false))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    //commitArray['lesson_location'] = value;
                    SCOState['lesson_location'] = value;

                    return "true";
                }
            }

            var value = '';
        }

        /**
        * Το cmi.core.credit υποδεικνύει αν ο μαθητής παρακολουθείται από το LMS κατά τη διάρκεια αυτού του SCO. Αν δηλαδή το SCO
        * θα στείλει δεδομένα στο LMS τα οποία θα αποθηκευθούν.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMIVocabulary "credit" , "no-credit"
        * Read Only
        *
        * Initialization: Είναι ευθύνη του LMS.
        */
        var credit = function()
        {
            this.get = function()
            {
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            var value = '';
            <?php                                               //Αν το μάθημα το βλέπει ο καθηγητής, είμαστε σε no-credit mode
                if ($_SESSION['s_type'] == 'professor')
                    echo "value = 'no-credit';";
                else
                    echo "value = 'credit';";
            ?>
        }

        /**
        * Το cmi.core.lesson_status είναι η κατάσταση του μαθητή.
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: YES
        * Data Type: CMIVocabulary 'passed', 'completed', 'failed', 'incomplete', 'browsed', 'not attempted'
        * Read / Write
        *
        * Initialization: Είναι ευθύνη του LMS.
        */
        var lesson_status   = function()        //+++ πρέπει με το που φεύγει ο μαθητής να γίνεται completed  (??? πώς ???) -> mia synarthsh sto iframe pou 8a kalei thn commitPage me tn parametro afth.
        {
            this.get = function()
            {
                if (SCOState['lesson_status'])
                {
                    value = SCOState['lesson_status'];
                }
                return value;
            }
            this.set = function(param)
            {
                count = 0;

                if (!checkDataType(param, 'CMIVocabulary', 'Status') || param == 'not attempted')
                {
                    throw new myError('405');
                }
                else
                {
                    //while (param != legal_values[count] && count++ < legal_values.length );
                    //if (count >= legal_values.length)
                    value = param;
                    SCOState['lesson_status'] = value;
                    return "true";
                }
            }

            var value        = 'not attempted';
            var legal_values = new Array('passed', 'completed', 'failed', 'incomplete', 'browsed', 'not attempted');
            //allowable values : 'passed', 'completed', 'failed', 'incomplete', 'browsed', 'not attempted'
        }

        /**
        * Το cmi.core.entry υποδεικνύει αν ο μαθητής έχει ξαναβρεθεί στο SCO.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMIVocabulary "ab-initio" , "resume", ""
        * Read Only
        *
        * Initialization: Είναι ευθύνη του LMS.
        */
        var entry = function()
        {
            this.get = function()
            {
                if ((typeof SCOState['entry']) != 'undefined')                          //Καθώς το entry μπορεί να είναι απλώς '', πρέπει να ελέγξουμε αν είναι ορισμένο
                {
                    value = SCOState['entry'];
                }
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            var value = 'ab-initio';
        }

        /*Οι επιδόσεις του μαθητή*/
        var score = function()
        {
            /**
            * Το cmi.core.score._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.core.score
            *
            * Supported API calls: LMSGetValue()
            * LMS Mandatory: YES
            * Data Type: CMIString255
            * Read Only
            *
            * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα χωρισμένη με κόμματα.
            */
            var _children = function()
            {
                this.get = function()      { return value;            }
                this.set = function(param) { throw new myError('402'); }

                var value = 'raw,min,max';
            }

            /**
            * Το cmi.core.score.raw είναι η απόδοση του μαθητή σε αυτό το SCO και αναπαρίσταται με έναν αριθμό από 0 έως 100.
            *
            * Supported API calls: LMSGetValue(), LMSSetValue()
            * LMS Mandatory: YES
            * Data Type: CMIDecimal or CMIBlank
            * Read / Write
            *
            * Initialization: Το κενό string ''
            */
            var raw = function()
            {
                this.get = function() { return value; }
                this.set = function(param)
                {
                    if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                    {
                        throw new myError('405');
                    }
                    else
                    {
                        value = param;
                        SCOState['score'] = value;
                        return "true";
                    }
                }

                var value = '';
            }

            /**
            * Το cmi.core.score.max είναι ο μέγιστος βαθμός που θα μπορούσε να επιτύχει ο μαθητής.
            *
            * Supported API calls: LMSGetValue(), LMSSetValue()
            * LMS Mandatory: ΝΟ
            * Data Type: CMIDecimal or CMIBlank
            * Read / Write
            *
            * Initialization: Το κενό string ''
            */
/*
Uncomment this and comment below to make it non-implemented
            var max = function()
            {
                this.get = function()      { throw new myError('401')}
                this.set = function(param) { throw new myError('401')}
            }
*/
            var max = function()
            {
                this.get = function()      { return value;           }
                this.set = function(param)
                {
                    if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                    {
                        throw new myError('405');
                    }
                    else
                    {
                        value = param;
                        SCOState['maxscore'] = value;
                        return "true";
                    }
                }

                var value = '';
            }

            /**
            * Το cmi.core.score.min είναι ο ελάχιστος βαθμός που θα μπορούσε να επιτύχει ο μαθητής.
            *
            * Supported API calls: LMSGetValue(), LMSSetValue()
            * LMS Mandatory: ΝΟ
            * Data Type: CMIDecimal or CMIBlank
            * Read / Write
            *
            * Initialization: Το κενό string ''
            */
/*
Uncomment this and comment below to make it non-implemented
            var min = function()
            {
                this.get = function()      { throw new myError('401')}
                this.set = function(param) { throw new myError('401')}
            }
*/
            var min = function()
            {
                this.get = function()      { return value;           }
                this.set = function(param)
                {
                    if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                    {
                        throw new myError('405');
                    }
                    else
                    {
                        value = param;
                        SCOState['minscore'] = value;
                        return "true";
                    }
                }

                var value = '';
            }

            this._children = new _children();
            this.raw       = new raw();
            this.max       = new max();
            this.min       = new min();
        }

        /**
        * Το cmi.core.total_time είναι ο συνολικός (αθροιστικός) χρόνος που έχει αφιερώσει ο μαθητής στο SCO. Ο χρόνος είναι στη μορφή HHHH:MM:SS.SS
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: YES
        * Data Type: CMITimeSpan
        * Read Only
        *
        * Initialization: Στo 0000:00:00.00
        */
        var total_time = function()
        {
            this.get = function()
            {
                if (SCOState['total_time'])
                {
                    value = SCOState['total_time'];
                }

                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            var value = '0000:00:00.00';
        }

        /**
        * Το cmi.core.lesson_mode είναι η κατάσταση του SCO.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: No
        * Data Type: CMIVocabulary "browse", "normal", "review"
        * Read Only
        *
        * Initialization: Στo normal
        */
/*
Uncomment this and comment below to make it non-implemented
        var lesson_mode = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var lesson_mode = function()
        {
            this.get = function()
            {
                if (SCOState['lesson_mode'])
                {
                    value = SCOState['lesson_mode'];
                }
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            var value = 'normal';
            //allowable values : 'browse', 'normal', 'review'
        }

        /**
        * Το cmi.core.exit υποδεικνύει πώς ή γιατί έφυγε ο μαθητής από το SCO.
        *
        * Supported API calls: LMSSetValue()
        * LMS Mandatory: YES
        * Data Type: CMIVocabulary "time-out", "suspend", "logout", ""
        * Write Only
        *
        * Initialization: Not needed
        */
        var exit = function()
        {
            this.get = function()      { throw new myError('404'); }
            this.set = function(param)
            {
                count = 0;

                if (!checkDataType(param, 'CMIVocabulary', 'Exit'))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    SCOState['exit'] = value;
                    return "true";
                }
            }

            var value        = '';
            var legal_values = new Array('time-out', 'suspend', 'logout', '');
            //allowable values : 'time-out', 'suspend', 'logout', ''
        }

        /**
        * Το cmi.core.session_time είναι η ώρα που έχει ξοδέψει αυτήν τη φορά ο μαθητής στο SCO (σε αντίθεση με το total_time).
        *
        * Supported API calls: LMSSetValue()
        * LMS Mandatory: YES
        * Data Type: CMITimespan
        * Write Only
        *
        * Initialization: Στo 0000:00:00.00
        */
        var session_time = function()
        {
            this.get = function()      { throw new myError('404'); }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMITimespan', false))            //edw 8elei ena RE
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    SCOState['session_time'] = value;
                    return "true";
                }
            }

            var value = '';
        }

        this._children       = new _children();
        this.student_id      = new student_id();
        this.student_name    = new student_name();
        this.lesson_location = new lesson_location();
        this.credit          = new credit();
        this.lesson_status   = new lesson_status();
        this.entry           = new entry();
        this.score           = new score();
        this.total_time      = new total_time();
        this.lesson_mode     = new lesson_mode();
        this.exit            = new exit();
        this.session_time    = new session_time();
    }

    /**
    * To cmi.suspend_data περιλαμβάνει πληροφορίες γενικής φύσης τις οποίες θέλει το SCO να αποθηκεύσει στο LMS. Αυτές μετά
    * πρέπει να είναι διαθέσιμες μόνο όποτε ξαναξεκινάει (σε restart).
    *
    * Supported API calls: LMSGetValue(), LMSSetValue()
    * LMS Mandatory: YES
    * Data Type: CMIString4096
    * Read / Write
    *
    * Initialization: Στo ''
    */
    this.suspend_data = new function()
    {
        this.get = function()
        {
            if (SCOState['suspend_data'])
            {
                value = SCOState['suspend_data'];
            }

            return value;
        }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIString4096', false))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                SCOState['suspend_data'] = value;
                return "true";
            }
        }

        var value = '';
    }

    /**
    * To cmi.launch_data περιλαμβάνει πληροφορίες γενικής φύσης οι οποίες είναι απαραίτητες κατά την εκκίνηση ενός SCO.
    * Το LMS διαβάζει αυτές τις πληροφορίες από το πεδίο "adlcp:datafromlms" του μανιφέστου.
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: YES
    * Data Type: CMIString4096
    * Read Only
    *
    * Initialization: Στo ''
    */
    this.launch_data = new function()
    {
        this.get = function()
        {
            if (SCOState['datafromlms'])
            {
                value = SCOState['datafromlms'];
            }

            return value;
        }
        this.set = function(param) { throw new myError('403'); }

        var value = '';
    }

    /**
    * To cmi.comments χρησιμοποιείται για να αποστέλλει ο μαθητής σχόλια στο LMS σχετικά με το SCO αυτό.
    *
    * Supported API calls: LMSGetValue(), LMSSetValue()
    * LMS Mandatory: NO
    * Data Type: CMIString4096
    * Read / Write
    *
    * Initialization: Στo ''
    */
/*
    this.comments = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.comments = new function()
    {
        this.get = function()      { return value; }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIString4096', false))
            {
                throw new myError('405');
            }
            else
            {
                value += param;
                SCOState['comments'] = value;
                return "true";
            }
        }

        var value = '';
    }

    /**
    * To cmi.comments_from_lms χρησιμοποιείται για να βλέπει ο μαθητής σχόλια που έχει θέσει το LMS στο SCO αυτό.
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: NO
    * Data Type: CMIString4096
    * Read Only
    *
    * Initialization: Στo ''
    */
/*
    this.comments_from_lms = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.comments_from_lms = new function()
    {
        this.get = function()
        {
            if (SCOState['comments_from_lms'])
            {
                value = SCOState['comments_from_lms'];
            }
            return value;
        }
        this.set = function(param) { throw new myError('403'); }

        var value = '';
    }

    /*
    * Αναλαμβάνει την προσαρμογή του SCO ανάλογα με τις επιδόσεις του μαθητή.
    */
    this.student_data = new function()
    {
        /**
        * Το cmi.student_data._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.student_data
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: NO
        * Data Type: CMIString255
        * Read Only
        *
        * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα χωρισμένη με κόμματα.
        */
/*
        var _children = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var _children = function()
        {
            this.get = function()      { return value;            }
            this.set = function(param) { throw new myError('402'); }

            var value = 'mastery_score,max_time_allowed,time_limit_action';
        }

        /**
        * Το cmi.student_data.mastery_score είναι το σκορ που πρέπει να επιτύχει ο μαθητής προκειμένου να θεωρηθεί ότι πέρασε την ενότητα.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: NO
        * Data Type: CMIDecimal
        * Read Only
        *
        * Initialization: Τίθεται από το LMS
        */
/*
        var mastery_score = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var mastery_score = function()
        {
            this.get = function()
            {
                if (SCOState['masteryscore'])
                {
                    value = SCOState['masteryscore'];
                }
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            value = '';
        }

        /**
        * Το cmi.student_data.max_time_allowed είναι ο μέγιστος χρόνος που διαθέτει ο μαθητής μέχρι να ολοκληρώσει την ενότητα.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: NO
        * Data Type: CMITimespan
        * Read Only
        *
        * Initialization: Τίθεται από το LMS
        */
/*
        var max_time_allowed = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var max_time_allowed = function()
        {
            this.get = function()
            {
                if (SCOState['maxtimeallowed'])
                {
                    value = SCOState['maxtimeallowed'];
                }
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            value = '';
        }

        /**
        * Το cmi.student_data.time_limit_action είναι η ενέργεια που διενεργείται όταν τελειώσει ο χρόνος του μαθητή στην ενότητα.
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: NO
        * Data Type: CMIVocabulary 'exit,message', 'exit,no message', 'continue,message', 'continue,no message'
        * Read Only
        *
        * Initialization: Τίθεται από το LMS
        */
/*
        var time_limit_action = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var time_limit_action = function()
        {
            this.get = function()
            {
                if (SCOState['timelimitaction'])
                {
                    value = SCOState['timelimitaction'];
                }
                return value;
            }
            this.set = function(param) { throw new myError('403'); }

            value = '';
            //legal values = 'exit,message', 'exit,no message', 'continue,message', 'continue,no message'
        }

        this._children         = new _children();
        this.mastery_score     = new mastery_score();
        this.max_time_allowed  = new max_time_allowed();
        this.time_limit_action = new time_limit_action();
    }

    /*Επιλογές που ενδέχεται να χρειαστούν σε επόμενα SCOs*/
    this.student_preference = new function()
    {
        /**
        * Το cmi.student_preference._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.student_preference
        *
        * Supported API calls: LMSGetValue()
        * LMS Mandatory: NO
        * Data Type: CMIString255
        * Read Only
        *
        * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα χωρισμένη με κόμματα.
        */
/*
        var _children = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var _children = function()
        {
            this.get = function()      { return value;            }
            this.set = function(param) { throw new myError('402'); }

            var value = 'language,speech,audio,speed,text';
        }

        /**
        * Το cmi.student_preference.audio καθορίζει την ένταση του ήχου.
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: NO
        * Data Type: CMIInteger
        * Read / Write
        *
        * Initialization: Τίθεται από το LMS στην τιμή 0
        * ΣΗΜΕΙΩΣΗ: ΔΕΝ ΥΠΟΣΤΗΡΙΖΕΤΑΙ (ΒΛΕΠΕ ΚΑΙ _CHILDREN) - αλλά υπάρχει υποστήριξη.
        */
/*
        var audio = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var audio = function()
        {
            this.get = function()      { return value; }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMISInteger', false) || param < -1 || param > 100)
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    return "true";
                }
            }
            var value = '';
        }

        /**
        * Το cmi.student_preference.language καθορίζει την επιθυμητή γλώσσα για το χρήστη.
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: NO
        * Data Type: CMIString255
        * Read / Write
        *
        * Initialization: Τίθεται από το LMS στην τιμή ''
        * ΣΗΜΕΙΩΣΗ: ΥΠΟΣΤΗΡΙΖΕΤΑΙ ΜΕΡΙΚΩΣ. Συγκεκριμένα, το getValue επιστρέφει την τρέχουσα ρύθμιση του μαθητή, αλλά το set value δεν έχει επίδραση στο LMS
        */
/*
        var language = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var language = function()
        {
            this.get = function()       { return value; }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMIString255', false))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    return "true";
                }
            }
            var value = '<?php echo $_SESSION["s_language"]?>';
        }

        /**
        * Το cmi.student_preference.speed καθορίζει το ρυθμό του περιεχομένου
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: NO
        * Data Type: CMISInteger
        * Read / Write
        *
        * Initialization: Τίθεται από το LMS στην τιμή ''
        */
/*
        var speed = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var speed = function()
        {
            this.get = function()      { return value; }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMISInteger', false) || param < -100 || param > 100)
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    return "true";
                }
            }
            var value = '0';
        }

        /**
        * Το cmi.student_preference.text καθορίζει την επιθυμητή γλώσσα για το χρήστη.
        *
        * Supported API calls: LMSGetValue(), LMSSetValue()
        * LMS Mandatory: NO
        * Data Type: CMISInteger
        * Read / Write
        *
        * Initialization: Τίθεται από το LMS στην τιμή ''
        */
/*
        var text = function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        var text = function()
        {
            this.get = function()      { return value; }
            this.set = function(param)
            {
                if (!checkDataType(param, 'CMISInteger', false) || (param != "1" && param != "0" && param != "-1"))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    return "true";
                }
            }
            var value = '0';
        }

        this._children = new _children();
        this.audio     = new audio();
        this.language  = new language();
        this.speed     = new speed();
        this.text      = new text();
    }

    /*
    * Υποδεικνύει πώς τα πήγε ο μαθητής στους στόχους του SCO
    */
    var objectives = new Array();

    /**
    * Το cmi.objectives._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.objectives
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: NO
    * Data Type: CMIString255
    * Read Only
    *
    * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα ζχωρισμένη με κόμματα.
    */
/*
    objectives._children = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    objectives._children = new function()
    {
        this.get = function()      { return value;            }
        this.set = function(param) { throw new myError('402'); }
        var value = 'id,score,status';
    }

    /**
    * Το cmi.objectives._count είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.objectives
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: NO
    * Data Type: CMIString255
    * Read Only
    *
    * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα ζχωρισμένη με κόμματα.
    */
/*
    objectives._count = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    objectives._count = new function()
    {
        this.get = function()      { return cmi.objectives.length; }
        this.set = function(param) { throw new myError('402'); }
    }

    //Assign objectives to cmi object
    this.objectives = objectives;


    /**
    * Το cmi.interactions είναι χειρίζεται δεδομένα που προέρχονται από το χρήστη.
    */
    var interactions = new Array();

    /**
    * Το cmi.interactions._children είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.interactions
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: NO
    * Data Type: CMIString255
    * Read Only
    *
    * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα χωρισμένη με κόμματα.
    */
/*
    interactions._children = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    interactions._children = new function()
    {
        this.get = function()      { return value;            }
        this.set = function(param) { throw new myError('402'); }
        var value = 'id,objectives,time,type,correct_responses,weighting,student_response,result,latency';
    }

    /**
    * Το cmi.interactions._count είναι ένα string το οποίο περιέχει μία λίστα όλων των στοιχείων που υποστηρίζει το cmi.interactions
    *
    * Supported API calls: LMSGetValue()
    * LMS Mandatory: NO
    * Data Type: CMIInteger
    * Read Only
    *
    * Initialization: Το σύνολο των παιδιών του LMS, έτσι ώστε μία LMSGetValue να επιστρέφει μία λίστα ζχωρισμένη με κόμματα.
    */
/*
    interactions._count = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    interactions._count = new function()
    {
        this.get = function()      { return cmi.interactions.length; }
        this.set = function(param) { throw new myError('402'); }
    }

    //Assign interactions to cmi object
    this.interactions = interactions;

}   //end of cmi

objectivesObject = function()
{
/*
    this.id = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.id = new function()
    {
        this.get = function()
        {
            if (value === null)         //means that is not initialized yet
            {
                value = '';             //Return empty string and throw error
                throw new myError('201');
            }
            return value;
        }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIIdentifier', false))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = null;
    }

    this.score = new function()
    {
/*
        this._children = new function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        this._children = new function()
        {
            this.get = function()      { return value;            }
            this.set = function(param) { throw new myError('402'); }
            var value = 'raw,min,max';
        }
/*
        this.raw = new function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        this.raw = new function()
        {
            this.get = function() { return value; }
            this.set = function(param)
            {
                if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    SCOState['score'] = value;
                    return "true";
                }
            }

            var value = '';
        }
/*
        this.max = new function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        this.max = new function()
        {
            this.get = function()      { return value;           }
            this.set = function(param)
            {
                if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    SCOState['maxscore'] = value;
                    return "true";
                }
            }

            var value = '';
        }
/*
        this.min = new function()
        {
            this.get = function()      { throw new myError('401')}
            this.set = function(param) { throw new myError('401')}
        }
*/
        this.min = new function()
        {
            this.get = function()      { return value;           }
            this.set = function(param)
            {
                if ((!checkDataType(param, 'CMIDecimal', false) || param < 0 || param > 100) && !checkDataType(param, 'CMIBlank', false))
                {
                    throw new myError('405');
                }
                else
                {
                    value = param;
                    SCOState['minscore'] = value;
                    return "true";
                }
            }

            var value = '';
        }

    }
/*
    this.status = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.status = new function()
    {
        this.get = function()
        {
            if (SCOState['lesson_status'])
            {
                value = SCOState['lesson_status'];
            }
            return value;
        }
        this.set = function(param)
        {
            count = 0;

            if (!checkDataType(param, 'CMIVocabulary', 'Status'))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                SCOState['lesson_status'] = value;
                return "true";
            }
        }

        var value        = 'not attempted';
        var legal_values = new Array('passed', 'completed', 'failed', 'incomplete', 'browsed', 'not attempted');
    }

}

interactionsObject = function()
{
/*
    this.id = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.id = new function()
    {
        this.get = function()      { throw new myError('404');        }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIIdentifier', false))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                SCOState['score'] = value;
                return "true";
            }
        }

        var value = '';
    }

    var objectives = new Array();
/*
    objectives._count = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    objectives._count = new function()
    {
    //  this.get = function()      { return 1000; }
        this.set = function(param) { throw new myError('402'); }
    }
    objectives._count.get = function()     { return objectives.length; }
    this.objectives = objectives;
/*
    this.time = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.time = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMITime', false))            //edw 8elei ena RE
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }
/*
    this.type = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.type = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIVocabulary', 'Interaction'))          //edw 8elei ena RE
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        this.getValue = function() {
            return value;
        }

        var value = '';
    }

    var correct_responses = new Array();
/*
    correct_responses._count = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    correct_responses._count = new function()
    {
    //  this.get = function()      { return cmi.objectives.length; }
        this.set = function(param) { throw new myError('402'); }
    }
    correct_responses._count.get = function()      { return correct_responses.length; }
    this.correct_responses = correct_responses;
/*
    this.weighting = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.weighting = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIDecimal', false))         //edw 8elei ena RE
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }
/*
    this.student_response = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.student_response = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIFeedback', cmi.interactions[_TEMP].type.getValue()))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }
/*
    this.result = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.result = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIVocabulary', 'Result'))           //edw 8elei ena RE
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }
/*
    this.latency = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.latency = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMITimespan', false))            //edw 8elei ena RE
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }

}

correct_responsesObject = function()
{
/*
    this.pattern = new function()
    {
        this.get = function()      { throw new myError('401')}
        this.set = function(param) { throw new myError('401')}
    }
*/
    this.pattern = new function()
    {
        this.get = function()      { throw new myError('404'); }
        this.set = function(param)
        {
            if (!checkDataType(param, 'CMIFeedback', cmi.interactions[_TEMP2].type.getValue()))
            {
                throw new myError('405');
            }
            else
            {
                value = param;
                return "true";
            }
        }

        var value = '';
    }
}


-->