crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V  < 1 2 3 >  
Ответить в данную темуНачать новую тему
> Программа для создания тестов, Обсуждение программы и кода
xwicked
  опции профиля:
сообщение 26.1.2012, 20:15
Сообщение #11


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


0.4.3 - это новая версия программы.

Здравствуйте! :)

Цитата
- Добавлено шифрование и сжатие экспортируемого файла теста в формате xwt;
- Исправлена ошибка, когда пароль режима программы хранился и проверялся в открытом виде;
- Добавлена возможность работать с несколькими хранилищами тестов;
- Добавлена возможность резервировать хранилище тестов(со сжатием до 5-ти раз(!));
- Добавлена возможность запроса на сохранение теста, при его закрытии;

    QString RegimePassword;//Пароль режима
    QByteArray  baPassword;//Хеш пароля;
    RegimePassword = "Password";
    baPassword.append(RegimePassword);
    baPassword = baPassword.toBase64();
    baPassword = qCompress(baPassword, 9);
    baPassword = baPassword.toBase64();
    baPassword = qCompress(baPassword, 9);
    baPassword = baPassword.toBase64();
    RegimePassword.clear();
    RegimePassword.append(baPassword);
Для шифрования используется алгоритм Base64, для сжатия функция qCompress. Этот код может быть реверсирован и получен изначальный пароль фактически в 100%-ом виде. В будущем он будет заменён на md5 хеш или похожий.

А вот следующая проблема - это шифрование самого теста. Алгоритмы те же. При наличии у студента(/пользователя) кода все тесты предстают в абсолютно первозданном виде :( .
Шифрование по ключу думаю будет слишком хорошая защита, которую мне одному не реализовать. Найти другой вариант за ~2-а месяца у меня не получилось.

Какие есть варианты? Благодарю!
ЗЫ: Всего 25 изменений.

Сообщение отредактировал xwicked - 26.1.2012, 20:27
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 6.2.2012, 1:54
Сообщение #12


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


0.4.4. Исправлено 15 ошибок(!). Появились 2-е структуры:
//Структура файла свойств
struct sFileSettings
{
     bool gRegimeViewing,//true - Режим просмотра, false - Режим редактирования
  LanguageProgram,//Язык программы
  bStandardPanel,//Состояние показа стандартной панели
  bEditPanel,//Состояние показа панели редактирования
  bFormatPanel,//Состояние показа панели форматирования
  bTimePanel,//Состояние показа панели времени
  bPointPanel,//Состояние показа панели баллов
  bLimitTime,//Ограничение времени
  bAutoStartTest;//Автоматический запуск
     QString RegimePassword;//Пароль режима
};

//Структура теста
struct sShelkTestVar
{
     QString sNameTest,//Название теста
     sAllPoint,//Все баллы строкой
     sMidPoint,//Средний балл строкой
     sCurrentPoint,//Текущий балл строкой
     sTypeQuestion,//Тип вопроса
     TestPassword,//Пароль теста
     StatNameTest,//Имя пользователя в статистике
     sQuestion,//Текст вопроса
     sTimeStart;//Время начала

int CountQuestion,//Количество вопросов
iNumberQuestion,//Номер вопроса
iNumberTest,//Номер теста
AllPoint,//Общий балл
MidPoint,//Средний балл
CurrentPoint,//Текущий балл
AllPointCheck,//Общий балл для проверки
AllTime,//Общее время
MidTime,//Среднее время
CurrentTime,//Текущее время
i5First;//Номер прошлого выделенного ответа (установка последовательности)

     QVector<double> *iRangeFirst,//Начальное значение диапазона (ввод числа)
                     *iRangeLast;//Конечное значение диапазона (ввод числа)

     QStringList ListQuestions,//Список вопросов
                 slTableNumber,//Список номеров таблиц в базе тестов
                 slQuestionType,//Список типов вопросов
                 slPoint,//Список баллов
                 slTime;//Список времени

     QVector<QVariant> *ListRightAnswer,//Список правильных ответов
                       *ListCheckRightAnswer;//Список правильных ответов для проверки

     QVector<QStringList> *ListAnswers;//Список ответов
     QVector<QByteArray> *ListImages;//Список изображений
     QVector<QFont> *ListFonts;//Список шрифтов
     QSqlDatabase db;//База данных тестов

     QTimer TimerTest,
            TimerTestLabel;
     QTime TimeTestCurrent,
           TimeTestAll;
};
Их было решено использовать сразу, после выхода кроссворда за предел стека :lol:
Введение вектора типа QVariant позволило функцию проверки ответов максимально упростить и вынести отдельно:
bool ShelkTest::MakeCheckRightAnswer(int iIndex)
{
    int iTypeR;
    QString str1, str2;
    QByteArray ba1, ba2;

    iTypeR = vShelkTestVar->ListRightAnswer->at(iIndex).type();

        if(iTypeR == QVariant::Int)
            {
                if(vShelkTestVar->ListRightAnswer->at(iIndex).toInt()
                    == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toInt())
                    return true;
                else return false;
            }

        if(iTypeR == QVariant::Double)
            {
                if(vShelkTestVar->ListRightAnswer->at(iIndex).toDouble()
                    == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toDouble())
                    return true;
                else return false;
            }

        if(iTypeR == QVariant::String)
            {
                if(vShelkTestVar->ListRightAnswer->at(iIndex).toString()
                    == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toString())
                    return true;
                else return false;
            }

        if(iTypeR == QVariant::ByteArray)
            {
                ba1.append(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray());
                ba2.append(vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray());
                str1.append(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray());
                str2.append(vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray());

                if(vShelkTestVar->ListRightAnswer->at(iIndex).toByteArray()
                    == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toByteArray())
                    return true;
                else return false;
            }

        if(iTypeR == QVariant::StringList)
            {
                if(vShelkTestVar->ListRightAnswer->at(iIndex).toStringList()
                    == vShelkTestVar->ListCheckRightAnswer->at(iIndex).toStringList())
                    return true;
                else return false;
            }
        return false;
}
Несмотря на то, что QVariant не рекомендуется использовать из за большого потребления памяти, так как он позволяет хранить даже контейнеры(!), я решил сделать это. Использование один раз в масштабах простой программы для создания тестов показала свою рентабельность.
Скачать
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 6.2.2012, 8:24
Сообщение #13


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Цитата(xwicked @ 26.1.2012, 23:15) *
0.4.4. Исправлено 15 ошибок(!). Появились 2-е структуры:
//Структура файла свойств
struct sFileSettings
{
     bool gRegimeViewing,//true - Режим просмотра, false - Режим редактирования
  LanguageProgram,//Язык программы
  bStandardPanel,//Состояние показа стандартной панели
  bEditPanel,//Состояние показа панели редактирования
  bFormatPanel,//Состояние показа панели форматирования
  bTimePanel,//Состояние показа панели времени
  bPointPanel,//Состояние показа панели баллов
  bLimitTime,//Ограничение времени
  bAutoStartTest;//Автоматический запуск
     QString RegimePassword;//Пароль режима
};


ой ой! Исправлено 15 ошибок, а добавлено ещё 15 ;)

Совсем-совсем не советую так оформлять структуры. Более того - не только структуры, а даже просто так объявлять переменные!

Правильно так:

struct sFileSettings
{
     bool gRegimeViewing;//true - Режим просмотра, false - Режим редактирования
     bool LanguageProgram;//Язык программы
     bool bStandardPanel;//Состояние показа стандартной панели
     bool bEditPanel;//Состояние показа панели редактирования
     bool bFormatPanel;//Состояние показа панели форматирования
     bool bTimePanel;//Состояние показа панели времени
     bool bPointPanel;//Состояние показа панели баллов
     bool bLimitTime;//Ограничение времени
     bool bAutoStartTest;//Автоматический запуск
     QString RegimePassword;//Пароль режима

//КОНСТРУКТОР ОБЯЗАТЕЛЬНО
   sFileSettings()
   {
      gRegimeViewing=false;
      LanguageProgram=false;
      bStandardPanel=false;
      bEditPanel=false;
      bFormatPanel=false;
      bTimePanel=false;
      bPointPanel=false;
      bLimitTime=false;
      bAutoStartTest=false;
   }

};



Но у меня это всё выглядело бы так (не из стремления экономить, а для удобства обнуления флагов):
Раскрывающийся текст
struct sFileSettings
{
    union
    {
        UINT32 m_AllFlags;
        struct
        {
            UINT32 gRegimeViewing  :1;//true - Режим просмотра, false - Режим редактирования
            UINT32 LanguageProgram :1;//Язык программы
            UINT32 bStandardPanel  :1;//Состояние показа стандартной панели
            UINT32 bEditPanel      :1;//Состояние показа панели редактирования
            UINT32 bFormatPanel    :1;//Состояние показа панели форматирования
            UINT32 bTimePanel      :1;//Состояние показа панели времени
            UINT32 bPointPanel     :1;//Состояние показа панели баллов
            UINT32 bLimitTime      :1;//Ограничение времени
            UINT32 bAutoStartTest  :1;//Автоматический запуск
            UINT32 :23;//резерв
        };
    };

    QString RegimePassword;//Пароль режима

    sFileSettings()
    {
        m_AllFlags=0;
    }
};


Цитата(xwicked @ 26.1.2012, 23:15) *
    QString str1, str2;
    QByteArray ba1, ba2;


- та же мигня! Что экономишь то ?

а в структуре sShelkTestVar у тебя не инициализированные в конструкторе указатели - это вообще ахтунг )

Сообщение отредактировал Алексей1153 - 6.2.2012, 8:22
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 6.2.2012, 13:24
Сообщение #14


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


Алексей1153, благодарю, но конструкторы я буду осваивать для классов, с приходом полного ООП в эту программу :rolleyes:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 6.2.2012, 13:48
Сообщение #15


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


xwicked, да не, начинай уже осваивать ) Потом же исправлять и глюки вылавливать придётся.

Открою маленький секрет: для компилятора C++ нет разницы, class это, struct или union - у них всех всё одинаково работает, они имеют конструктор и деструктор. Тонкости в различии : union и struct по умолчанию устанавливают доступ public своему содержимому, а class - private. Ну и в union у объединённых переменных вроде не может быть явного конструктора/деструктора, но это уже к нашему случаю не относится, так как это внутренние данные, а не сама структура.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 14.2.2012, 23:03
Сообщение #16


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


Здравствуйте! Представляю новую версию программы 0.4.7. Добавился файл с константами:
//const.h
//Определение путей констант, в соответствии с системой
#if defined(Q_WS_WIN)

    #define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwst"
    #define PATH_SHARE_DOC QApplication::applicationDirPath()
    #define PATH_SHARE_APP QApplication::applicationDirPath()
    #define PATH_TMP QApplication::applicationDirPath()


#elif defined(Q_WS_X11)

    #define PATH_TMP_SET "/tmp/shelk-test-0.4.7/settings.xwst"
    #define PATH_SHARE_DOC "/usr/share/doc/shelk-test-0.4.7"
    #define PATH_SHARE_APP "/usr/share/shelk-test-0.4.7"
    #define PATH_TMP "/tmp/shelk-test-0.4.7"

#elif defined(Q_WS_MAC)

    #define PATH_TMP_SET QApplication::applicationDirPath() + "/settings.xwst"
    #define PATH_SHARE_DOC QApplication::applicationDirPath()
    #define PATH_SHARE_APP QApplication::applicationDirPath()
    #define PATH_TMP QApplication::applicationDirPath()


#endif

#define MODE_VIEW true
#define MODE_EDIT false

#define LANGUAGE_RUSSIAN true
#define LANGUAGE_ENGLISH false

#define TOOLBAR_SHOW true
#define TOOLBAR_HIDE false

#define STATISTICS_FIELD_SHOW true
#define STATISTICS_FIELD_HIDE false

#define VIEW_RUSSIAN 0
#define VIEW_ENGLISH 1
#define EDIT_RUSSIAN 2
#define EDIT_ENGLISH 3

//Типы вопросов
#define TYPE_ONE_ANSWER "1"
#define TYPE_MANY_ANSWERS "2"
#define TYPE_ENTER_WORD "3"
#define TYPE_ENTER_NUMBER "4"
#define TYPE_INSTALLATION_SEQUENCE "5"

Добавилась новая структура, но в коде она пока не задействована:
//Структура показа полей статистики
struct TStateFieldStatistics
{
     bool bUserName,//Имя пользователя
          bNameTest,//Название теста
          bTotalQuestions,//Всего вопросов
          bCorrectAnswers,//Правильных ответов
          bWrongAnswers,//Неправильных ответов
          bTotalPoints,//Всего баллов
          bScore,//Оценка
          bDate,//Дата
          bTimeBegin,//Время начала
          bTimeEnd,//Время окончания
          bElapsedTime;//Прошедшее время
};
Оптимизирована функция изменения шрифта(была 195 строк):
        bool Accept;
        QFont TextFont;
        TextFont = TextQuestion->textCursor().charFormat().font();
        TextFont = QFontDialog::getFont(&Accept, TextFont);

        if(Accept)
        {
            QTextCharFormat tcf;
            tcf.setFont(TextFont);
            TextQuestion->textCursor().setCharFormat(tcf);
            cbFont.setCurrentFont(TextFont);
        }
        else return 1;
Скачать
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 19.2.2012, 1:22
Сообщение #17


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


Новая и последняя на данный момент версия 1.0.0. Здесь я постарался конкретно. Изменения:
Цитата
- Добавились новые возможности: проверка наличия новой версии через интернет; печать теста; печать статистики; экспорт тестов в HTML, RTF, PDF, PostScript, простой текстовый формат;
- Добавлено использование системных временных каталогов для размещения временных файлов;
- Изменилось расположение файла статистики по-умолчанию на домашний каталог пользователя;
- Изменилась кодировка файла статистики на UTF-8:
- Изменилась кодировка импортируемого текстового файла на UTF-8;
//Новые константы
//Типы вопросов для определения содержимого переменной QVariant
#define V_TYPE_ONE_ANSWER QVariant::Int
#define V_TYPE_MANY_ANSWERS QVariant::ByteArray
#define V_TYPE_ENTER_WORD QVariant::String
#define V_TYPE_ENTER_NUMBER QVariant::Double
#define V_TYPE_INSTALLATION_SEQUENCE QVariant::StringList

//Перевод слов в rtf-unicode
QString ShelkTest::WordToUnicode(QString sWord)
{
    QString sTemp,
            sNum;
    sTemp.clear();
    for (int i = 0; i < sWord.length(); i++)
    {
        sNum.setNum(sWord.at(i).unicode());
        sTemp.append("\\u" + sNum + "?");
    }
    return sTemp;
}

Далее, задействовал webkit:
private: QWebView *wvUpdate;//Для обновления и печати :)
, так как QTextEdit и QTextBrowser не могут отображать элементы ввода(текст, переключатель, флажок), для формирования правильной html-ки. Раз уж было принято решение добавить новую зависимость от библиотеки QtWebkit, то на его же основе я сделал проверку наличия новой версии через интернет, смотрим:
void ShelkTest::slotCheckForUpdates()
{
    connect(wvUpdate, SIGNAL(loadFinished(bool)), SLOT(slotMakeCheckUpdates(bool)));
    wvUpdate->load(QUrl("http://labfreetech.org/shelk_1.0.0.html"));
}

void ShelkTest::slotMakeCheckUpdates(bool bError)
{
    if (bError && wvUpdate->page()->findText("new_version")) QMessageBox::information(0, tr("Information"), tr("On the official website available a new version!"));
    else QMessageBox::information(0, tr("Information"), tr("You have the latest version!"));
    disconnect(wvUpdate, SIGNAL(loadFinished(bool)), 0, 0);
}
Как видно - всё просто. Если текст "new_version" найден в загруженной html-ке, то есть новая версия :)
Чтобы сделать всё так, как я задумал - пришлось использовать новый метод disconnect, который я ранее не использовал и всё получилось.

Теперь за кодом можно наблюдать не дожидаясь релиза. В git создана новая ветка current. Скачать.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 17.11.2012, 18:42
Сообщение #18


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


1.5.2 - скачать
Цитата
- Теперь сохранение свойств программы происходит при каждом их изменении;
- Убрана чувствительность регистра ответа в вопросе типа "Ввод слова(предложения)";
- Исправлена ошибка ограничения количества вопросов в режиме редактирования;
- Добавлено новое поле статистики "Количество заданных вопросов из общего числа";
- Исправлена ошибка, когда нельзя было ввести вариант ответа, при увеличении и обратном уменьшении изображения, в вопросе "Ввод слова(предложения)";
- Изменено и отлажено автоматическое определение пропущенных вопросов, при тестировании;
- Добавлена дополнительная детализация к статистике протестировавшихся;
В следующей версии я хочу прикрутить веб-интрефейс тестируемого. Собираюсь использовать JavaScript(или Java? а возможно C++?) + свой простейший веб-сервер(на C++ для AJAX). Какие вопросы / проблемы меня могут поджидать?

Благодарю за ответы!

Сообщение отредактировал xwicked - 17.11.2012, 21:01
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
xwicked
  опции профиля:
сообщение 3.11.2013, 20:58
Сообщение #19


Студент
*

Группа: Участник
Сообщений: 66
Регистрация: 2.8.2011
Из: Старый Оскол
Пользователь №: 2781

Спасибо сказали: 0 раз(а)




Репутация:   0  


По-тихоньку идёт совершенствование программы. И сейчас от основного кода был отделён модуль Тестирование.

Пршу протестировать на наличие ошибок первую бета-версию: 1.6.2.0. Для полноценной проверки может потребоваться прошлая версия 1.5.2.

Благодарю за ответы!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_Гость_*
сообщение 5.11.2014, 8:26
Сообщение #20





Гости








    


если сделаешь возможность компиляции в exe, цены тебе не будет)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V  < 1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 23.11.2024, 23:31