protected void Page_Load(object sender, EventArgs e)
        {
            string command   = Request.Params["command"];
            string sessionid = Request.Params["session_id"];
            string aiccdata  = Request.Params["aicc_data"];

            Dictionary <string, string> parsed_dictionary = null;
            HACP_Parser hacpParser = new HACP_Parser();
            HACP_Logic  hacp       = new HACP_Logic();

            if (String.IsNullOrEmpty(command))
            {
                sendOutput(error_invalid_command);
            }
            if (String.IsNullOrEmpty(sessionid))
            {
                sendOutput(error_invalid_session_id);
            }

            switch (command.ToLower())
            {
            case "getparam":
                using (ComplianceFactorsEntities context = new ComplianceFactorsEntities())
                {
                    var enroll = (from en in context.e_tb_enrollments
                                  where en.e_enroll_system_id_pk == new Guid(sessionid)
                                  select en).FirstOrDefault();

                    if (enroll == null)     //no record found, invalid eid
                    {
                        sendOutput(error_invalid_session_id);
                    }

                    student_id   = enroll.e_enroll_user_id_fk.ToString();
                    student_name = enroll.u_tb_users_master.u_last_name + ", "
                                   + enroll.u_tb_users_master.u_first_name
                                   + " " + enroll.u_tb_users_master.u_middle_name;
                    lesson_location = enroll.e_enroll_lesson_location ?? "";
                    credit          = ((bool)(enroll.e_enroll_credit ?? true)) ? "credit" : "no-credit";

                    // Status
                    //  account for null/empty value
                    if (String.IsNullOrEmpty(enroll.e_enroll_lesson_status))
                    {
                        lesson_status = "not attempted";
                    }
                    // set status to 'incomplete'
                    if (enroll.e_enroll_lesson_status == "not attempted")
                    {
                        lesson_status = "incomplete";
                    }


                    vExit = enroll.e_enroll_exit;
                    if (vExit == "time-out" || vExit == "logout" || String.IsNullOrEmpty(vExit))
                    {
                        vEntry = "";
                    }
                    else if (vExit == "suspend")
                    {
                        vEntry = "resume";
                        //enroll.e_enroll_entry = true;
                    }
                    else
                    {
                        vEntry = "ab-initio";
                        //enroll.e_enroll_entry = false;
                    }

                    //vEntry = ((bool)(enroll.e_enroll_entry ?? false)) ? "resume" : "ab-initio"; // ab-initio, resume, or ""->neither of the former
                    suspend_data = enroll.e_enroll_suspend_data ?? "";
                    launch_data  = enroll.e_enroll_launch_data ?? "";

                    score_raw = Convert.ToString(enroll.e_enroll_score);
                    score_max = Convert.ToString(enroll.e_enroll_score_max);
                    score_min = Convert.ToString(enroll.e_enroll_score_min);

                    lesson_mode = (enroll.e_enroll_lesson_mode ?? "normal");     //for now...
                    total_time  = TimeSpan.FromSeconds((double)(enroll.e_enroll_time_spent ?? 0)).ToString(@"hh\:mm\:ss");

                    //context.SaveChanges();
                }

                responseString += no_error_output + "aicc_data=";
                responseString += "[Core]\r\n";
                responseString += "Student_ID=" + student_id + "\r\n";
                responseString += "Student_Name=" + student_name + "\r\n";
                responseString += "Lesson_Location=" + lesson_location + "\r\n";
                responseString += "Credit=" + credit + "\r\n";
                responseString += "Lesson_Status=" + lesson_status + ", " + vExit + "\r\n";;

                var score = score_raw;
                if (!String.IsNullOrEmpty(score_max))
                {
                    score += ", " + score_max;
                }
                if (!String.IsNullOrEmpty(score_min))
                {
                    score += ", " + score_min;
                }
                responseString += "Score=" + score + "\r\n";

                responseString += "Time=" + total_time + "\r\n";
                responseString += "Lesson_Mode=" + lesson_mode + "\r\n";
                responseString += "[Core_Lesson]\r\n";
                if (suspend_data != "")
                {
                    responseString += suspend_data + "\r\n";
                }
                responseString += "[Core_Vendor]\r\n" + launch_data + "\r\n";

                /*
                 * "[Evaluation]\r\nCourse_ID = {".."}\r\n";
                 * "[Student_Data]\r\n";
                 * 'Mastery_Score='.."\r\n";
                 * 'Max_Time_Allowed='.."\r\n";
                 * 'Time_Limit_Action='.."\r\n";
                 */

                sendOutput(responseString);

                break;

            case "putparam":
                //save passed parameters

                //parse putparam
                parsed_dictionary = hacpParser.parsePutParam(sessionid, HttpUtility.UrlDecode(aiccdata));
                parsed_dictionary.Add("cmi.terminate", "false");

                //persist values...
                hacp.ConsumeJSObj(parsed_dictionary);
                hacp.Persist(sessionid);

                sendOutput(no_error_output);

                break;

            case "putcomments":
                // parse CSV
                break;


            case "putinteractions":
                // parse CSV
                break;

            case "exitau":
                //parse putparam
                parsed_dictionary = hacpParser.parsePutParam(sessionid, HttpUtility.UrlDecode(aiccdata));
                parsed_dictionary.Add("cmi.terminate", "true");

                //persist values...
                hacp.ConsumeJSObj(parsed_dictionary);
                hacp.Persist(sessionid);

                sendOutput(no_error_output);

                break;

            default:
                sendOutput(error_invalid_command);
                break;
            }



            // TODO: handle 'running' and 'terminated'...
        }
        static void HACPParserTest()
        {
            /*
             * [Core]
             * Lesson_Location = 87
             * Lesson_Status = C
             * Score =
             * Time = 00:02:30
             * [CORE_LESSON]
             * my lesson state data – 1111111111111111111000000000000000001110000
             * 111111111111111111100000000000111000000000 – end my lesson state data
             * [COMMENTS]
             * <1><L.Slide#2> This slide has the fuel listed in the wrong units <e.1>
             *
             */


            string value = "[core]\r\nTime = 1002:34:05\r\n" +
                           "lesson_location = end\r\n" +
                           "Score = 8, 10 , 0\r\n" + // ; Raw score of 8 with a maximum possible of 10 and minimum of 0.

                                                     /*
                                                      * If Score.Raw is accompanied by Score.Max or Score.Min, it reflects the
                                                      *   performance of the learner relative to the max and min values.
                                                      *   If Score.Max accompanies Score.Raw with no Score.Min, Score.Min is
                                                      *   assumed to be “0”.
                                                      *   If Score.Min is included then Score.Max must be also be included.
                                                      */
                           "LessoN_Status = F\r\n" +
                                                     //One of the following vocabulary values: “passed” , “failed”, “complete”,
                                                     //  “incomplete”, “not attempted”, or “browsed”. All values are case
                                                     //  insensitive. Only the first character is significant.

                                                     /* ***Core.Exit***
                                                      *
                                                      * This element is appended to the keyword/value pair of Lesson_Status
                                                      *       with “,” (comma) preceding it. There may be spaces trailing and leading
                                                      *       this comma. The element value is case-insensitive with only the first
                                                      *       character being significant. If the element is not present, a normal exit
                                                      *       shall be assumed.
                                                      *
                                                      * The value must be one of the following: “time-out” , “logout” , “suspend”
                                                      *       or the empty string (“”).
                                                      *
                                                      * LESSON_Status = Passed, Logout
                                                      */
                           "\r\n" +
                           "\r\n" +
                           "\r\n" +
                           "\r\n" +
                           "[CORE_lesson]\r\n   9 00 001010101100110\r\n000 001010101100110\r\n000001010101100110" +
                           "\r\ngl’;sdfgl’;sdfhgl’;sdfhgls’;df  " +

                           /*
                            * Square brackets “[ ]” are not allowed.
                            * Leading and trailing whitespace (carriage-returns, tabs, spaces)
                            *  are not included.
                            * Embedded whitespace is allowed and must be included
                            */
                           "\r\n" +
                           "[COMMENTS]" +
                           "\r\n" +
                           "<1>The background color is too blue!<1.e><2>The CDU\r\n" +
                           "panel has the incorrect ‘way points’ displayed for\r\n" +
                           "this route. <2.e><3>The CDU panel has the incorrect\r\n" +
                           "‘way points’ displayed for this route. <3.e><4>The\r\n" +
                           "CDU panel has the incorrect ‘way points’ displayed\r\n" +
                           "for this route. <e.4>\r\n"
            ;

            Dictionary <string, string> parsed_dictionary = null;

            HACP_Parser hacpParser = new HACP_Parser();

            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary["cmi.core.session_time"] == "1002:34:05", "cmi.core.time is not correct");
            Debug.Assert(parsed_dictionary["cmi.core.lesson_location"] == "end");
            Debug.Assert(parsed_dictionary["cmi.core.score.raw"] == "8");
            Debug.Assert(parsed_dictionary["cmi.core.score.max"] == "10");
            Debug.Assert(parsed_dictionary["cmi.core.score.min"] == "0");
            Debug.Assert(parsed_dictionary["cmi.core.lesson_status"] == "f");
            Debug.Assert(parsed_dictionary["cmi.suspend_data"] == "9 00 001010101100110\r\n000 001010101100110\r\n000001010101100110\r\ngl’;sdfgl’;sdfhgl’;sdfhgls’;df");
            Debug.Assert(parsed_dictionary["cmi.comments"] == "<1>The background color is too blue!<1.e><2>The CDU\r\npanel has the incorrect ‘way points’ displayed for\r\nthis route. <2.e><3>The CDU panel has the incorrect\r\n‘way points’ displayed for this route. <3.e><4>The\r\nCDU panel has the incorrect ‘way points’ displayed\r\nfor this route. <e.4>");

            value             = "[core]\r\nScore = 8, 10\r\n";
            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary.ContainsKey("cmi.core.session_time") == false);
            Debug.Assert(parsed_dictionary.ContainsKey("cmi.core.lesson_location") == false);
            Debug.Assert(parsed_dictionary["cmi.core.score.raw"] == "8");
            Debug.Assert(parsed_dictionary["cmi.core.score.max"] == "10");
            Debug.Assert(parsed_dictionary.ContainsKey("cmi.core.score.min") == false);
            Debug.Assert(parsed_dictionary.ContainsKey("cmi.core.lesson_status") == false);
            Debug.Assert(parsed_dictionary.ContainsKey("cmi.suspend_data") == false);
            Debug.Assert(parsed_dictionary.ContainsKey("cmi.comments") == false);

            value             = "[core]\r\nlesson_location = 1,,,,,2\r\n";
            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_location"] == "1,,,,,2");

            value             = "[core]\r\nlesson_location =Page 1\r\n";
            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_location"] == "Page 1");

            value             = "[core]\r\nlesson_location = #$#&^%&^*$Q#)*%afgfg\r\n";
            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_location"] == "#$#&^%&^*$Q#)*%afgfg");

            value             = "[core]\r\nlesson_status = Passed, Logout";
            parsed_dictionary = hacpParser.parsePutParam("asdfasdf", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_status"] == "passed");
            //Debug.Assert(parsed_dictionary["cmi.core.exit"] == "Logout");

            value             = "[core]\r\nCredit = c";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.credit"] == "c");

            value             = "[core]\r\nCredit = Credit";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.credit"] == "credit");

            value             = "[core]\r\nCredit =N ";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.credit"] == "n");

            value             = "[core]\r\nSCORE= 0.654";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.score.raw"] == "0.654");

            value             = "[core]\r\nSCORE=1.3, 2";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.score.raw"] == "1.3");
            Debug.Assert(parsed_dictionary["cmi.core.score.max"] == "2");

            value             = "[core]\r\nSCORE= ";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.score.raw"] == "");

            value             = "[core]\r\nTime = 00:12:23.3";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.session_time"] == "00:12:23.3");

            value             = "[core]\r\nTime = 02:34:05";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.session_time"] == "02:34:05");

            value             = "[core]\r\nTime = 019:12:23.3";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.session_time"] == "019:12:23.3");

            value             = "[core]\r\nLesson_mode = Normal";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_mode"] == "normal");

            value             = "[core]\r\nLesson_MODE = r";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_mode"] == "r");

            value             = "[core]\r\nLESSON_MODE = browse";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.lesson_mode"] == "browse");

            value =
                "[core_lesson]\r\n1BookMark = Some book mark data\r\n2BookMark = Some more book mark data\r\n1StateData = Some state data\r\n2StateData = Some more state data.";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.suspend_data"] ==
                         "1BookMark = Some book mark data\r\n2BookMark = Some more book mark data\r\n1StateData = Some state data\r\n2StateData = Some more state data."
                         );

            value =
                "[CORE_Vendor]\r\nLaunchParam1 = Some launch stuff\r\nLaunchParam2 = Some more launch stuff\r\nLaunchParam3 = Some launch stuff";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.launch_data"] ==
                         "LaunchParam1 = Some launch stuff\r\nLaunchParam2 = Some more launch stuff\r\nLaunchParam3 = Some launch stuff");

            value             = "[Core]\r\nLESSON_Status=l, S";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.exit"] == "s");

            value             = "[Core]\r\nLESSON_Status=,S";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.exit"] == "s");

            value             = "[Core]\r\nLESSON_Status=,R";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.exit"] == "r");

            value             = "[Core]\r\nLESSON_Status=,L";
            parsed_dictionary = hacpParser.parsePutParam("", value);

            Debug.Assert(parsed_dictionary["cmi.core.exit"] == "l");
        }