CCCPaste

csv-create-graph

# ----------------------------------------------------------------------------------------------------------------------

# Python-модуль для построения графиков на основе csv-файлов.

# ----------------------------------------------------------------------------------------------------------------------
import matplotlib.pyplot as plt
import csv
import os

plt.rcParams["figure.figsize"] = (7,5)

def count_file_in_folder(path, str_in_file_name):
    """
    Подсчитывает кол - во файлов в директории.

    :param path:
        Путь до директории, где мы проверяем кол - во файлов.
    :param str_in_file_name:
        Строка, которая должна содержаться в имени файла.
    :return:
        Возвращает кол - во таких файлов в директории.
    """

    str_in_file_name, count_file = str(str_in_file_name), 0
    for i in range(len(os.listdir(path))):
        if str_in_file_name in str(os.listdir(path)[i]):
            count_file += 1

    return count_file + 1


def convert_date_to_time(list_date):
    """
    Преобразовывает дату во время.

    :param list_date:
        Строка с датой прохождения теста.
    :return:
        Возвращает список списков ЧЧ.ММ.СС.МСМС.
    """

    list_result = []

    for date_tmp in list_date:
        if date_tmp == '__EMPTY__':
            list_result.append([date_tmp])
            continue
        str_tmp = ''
        flag = False

        for char in date_tmp:
            if flag:
                if char.isdigit():
                    str_tmp += char
                else:
                    str_tmp += '_&&_'
            elif char == 'T':
                flag = True

        list_result.append(str_tmp.split('_&&_')[:-1])

    print(list_result, file=open('list_result.txt', 'a'))

    if not list_result:
        return None
    else:
        return list_result


def arithmetic_sum(path, question, response):
    """
    Вычисляет общее время ответа на вопрос.

    :param path:
        Путь до файла.
    :param question:
        Ключ вопроса.
    :param response:
        Ключ ответа.
    :return:
        Возвращает общее время ответа на вопрос.
    """

    with open(path) as f:
        list_keys = str(f.readline()).replace('"', '').split(',')

    list_keys = list_keys[1:]

    with open(path) as f:
        reader = csv.DictReader(f)
        dict_reader_tmp = {}
        for i in range(len(list_keys)):
            dict_reader_tmp[list_keys[i]] = []

        for row in reader:
            for i in range(len(list_keys)):
                if question in list_keys[i] or response in list_keys[i]:
                    if row[list_keys[i]] == '':
                        dict_reader_tmp[list_keys[i]].append('__EMPTY__')
                    else:
                        dict_reader_tmp[list_keys[i]].append(row[list_keys[i]])

    dict_reader = {}
    dict_reader_cleared = {}
    for i in range(len(list_keys)):
        dict_reader[list_keys[i]] = []

    for key in dict_reader.keys():
        dict_reader[key] = convert_date_to_time(dict_reader_tmp[key])

    list_keys.clear()
    for key in dict_reader.keys():
        if dict_reader[key] is not None:
            list_keys.append(key)
            dict_reader_cleared[key] = dict_reader[key]

    dif = difference(dict_reader_cleared)
    # print('arithmetic_mean = ', sum(dif) / len(dif))
    return sum(dif)


def convert_str_to_int(list_from):
    """
    Конвертирует список строк в список чисел.

    :param list_from:
        Принимает список строк.
    :return:
        Возвращает результирующий список.
    """

    list_int_converted = []
    for element in list_from:
        if element == '__EMPTY__':
            list_int_converted.append(element)
            continue
        list_int_converted.append(int(element))

    return list_int_converted


def sum_time(list_time):
    """
    Сумма времени ответов на вопросы.

    :param list_time:
        Принимает список с данными по времени на каждый вопрос.
    :return:
        Возвращает сумму, в виде кортежа, времени ответов на вопросы и индексы где, была пустая строка.
    """

    result = []
    list_pop_index = []

    for (offset, element) in enumerate(list_time):
        if '__EMPTY__' in element:
            list_pop_index.append(offset)
            result.append('__EMPTY__')
            continue
        else:
            result.append((element[0] * ((60 ** 2) * 1000)) + (element[1] * (60 * 1000))
                          + (element[2] * 1000) + element[3])

    return result, list_pop_index


def difference(dict_date):
    """
    Находит разность времени начала и конца ответа на вопросы.

    :param dict_date:
        Принимает словарь времени начала и конца ответа на вопросы.
    :return:
        Возвращает разность времени начала и конца ответа на вопросы.
    """

    list_result_question = []
    list_result_response = []

    for (offset, key) in enumerate(dict_date):
        if offset % 2 == 0:
            for i in range(len(dict_date[key])):
                list_result_question.append(convert_str_to_int(dict_date[key][i]))
        else:
            for i in range(len(dict_date[key])):
                list_result_response.append(convert_str_to_int(dict_date[key][i]))

    result_question_tmp = sum_time(list_result_question)
    result_response_tmp = sum_time(list_result_response)

    list_result_difference = []

    for tuple_of_elements in zip(result_response_tmp[0], result_question_tmp[0]):
        if tuple_of_elements[0] == '__EMPTY__':
            continue
        elif tuple_of_elements[1] == '__EMPTY__':
            continue
        else:
            list_result_difference.append(tuple_of_elements[0] - tuple_of_elements[1])

    return list_result_difference


def graph(path_to_csv_file, type_test, len_test, write_result='off'):
    """
    Строит график по запросу.

    :param path_to_csv_file:
        Путь до папки с csv-файлами.
    :param type_test:
        Тип теста.
    :param len_test:
        Длина теста.
    :param write_result:
        Нужно ли выводить процесс работы функции на экран(не график, а именно процесс работы.).
    :return:
        Ничего не возвращает.
    """

    if write_result != 'on' and write_result != 'off':
        print('invalid arg!')
        return

    dict_result_tmp = {}

    for i in range(1, count_file_in_folder(path_to_csv_file, "csv")):
        list_result = []
        for j in range(1, len_test + 1):
            if i == 1:
                dict_result_tmp['{}{}'.format(type_test, j)] = 0
            question = '{}{}.firstQuestionDisplayTime'.format(type_test, j)
            response = '{}{}.firstResponseTime'.format(type_test, j)
            if write_result == 'on':
                print('{}.csv'.format(i), ' - ', '{}{}'.format(type_test, j), ' arithmetic_sum = ',
                      arithmetic_sum(r'{}/{}.csv'.format(path_to_csv_file, i, type_test, j), question, response))

                list_result.append(arithmetic_sum(r'{}/{}.csv'.format(path_to_csv_file, i, type_test, j)
                                                  , question, response))
                dict_result_tmp['{}{}'.format(type_test, j)] += list_result[j - 1]
            elif write_result == 'off':
                list_result.append(arithmetic_sum(r'{}/{}.csv'.format(path_to_csv_file, i, type_test, j)
                                                  , question, response))
                dict_result_tmp['{}{}'.format(type_test, j)] += list_result[j - 1]

    #     print(dict_result_tmp)
    list_result = []
    x = []
    y = []
    for key in dict_result_tmp:
        list_result.append(dict_result_tmp[key] / len_test)

    #     print(list_result)

    for i in range(len_test):
        x.append(str(type_test) + str(i))

    #     print(x)
    y = list_result

    plt.xlabel('Номер вопроса')
    plt.ylabel('Время ответа на вопрос, мсек')
    plt.plot(x, y)


def main():
    """
    Главная функция - точка входа. Она же управляет остальными.

    :return:
        Ничего не возвращает.
    """

    graph('CSV_FILE', 'A', 12, write_result='on')


if __name__ == "__main__":
    main()