<commit_before>// Copyright (c) 2013 <NAME>

#include "profiling_gui/flowdiagram.hpp"

#include <QGraphicsLineItem>
#include <QGraphicsRectItem>

#include <QDebug>

namespace profiling_gui {

FlowDiagram::FlowDiagram(QObject *parent) :
    QObject(parent)
{
}

void FlowDiagram::loadFile(const QString& path, QGraphicsScene* scene)
{
    _scene = scene;
    profiling_reader::reader reader(path.toStdString());

    _ticksPerNs = reader.ticks_per_ns();

    // collect data
    reader.for_each_by_time([this](const profiling_reader::record_type& record)
    {
        this->onRecord(record);
    });

    // build items
    for(const ThreadData& thread : _threads)
    {
        auto* item = new QGraphicsLineItem(thread.minTime, thread.y, thread.maxTime, thread.y);
        QPen pen(Qt::black);
        pen.setCosmetic(true);
        item->setPen(pen);
        scene->addItem(item);
    }
}

double FlowDiagram::ticksToTime(qint64 ticks) const
{
    return ticks / _ticksPerNs;
}

static QColor idToColor(std::uintptr_t id)
{
    Qt::GlobalColor colors[] = { Qt::red, Qt::cyan, Qt::green, Qt::magenta, Qt::darkYellow, Qt::darkCyan, Qt::yellow, Qt::darkRed };
    std::size_t hash = std::hash<std::uintptr_t>()(id);

    return colors[(hash>>4) % 8];
}

void FlowDiagram::onRecord(const profiling_reader::record_type& record)
{
    static const double THREAD_Y_SPACING = 100.0;
    static const double CORO_H = 5;

    if (!_threads.contains(record.thread_id))
    {
        ThreadData newThread;
        newThread.minTime = ticksToTime(record.time);
        newThread.y = _threads.size() * THREAD_Y_SPACING;

        _threads.insert(record.thread_id, newThread);
    }

    ThreadData& thread = _threads[record.thread_id];
    thread.maxTime = ticksToTime(record.time);

    // coroutines
    if (record.object_type == "coroutine")
    {
        CoroutineData& coroutine = _coroutines[record.object_id];

        if (!coroutine.color.isValid())
            coroutine.color = idToColor(record.object_id);

        if (record.event == "created")
            coroutine.name = QString::fromStdString(record.data);

        if (record.event == "enter")
        {
            //qWarning() << "Corotuine: enter. id=" << record.object_id << ", time= " << record.time << ",thread=" << record.thread_id;
            coroutine.enters[record.thread_id] = ticksToTime(record.time);
        }

        if (record.event == "exit")
        {
            if(!coroutine.enters.contains(record.thread_id))
            {
                qWarning() << "Corotuine: exit without enter! id=" << record.object_id << ", time= " << record.time << ",thread=" << record.thread_id;
            }
            else
            {
                double enterX =  coroutine.enters[record.thread_id];
                coroutine.enters.remove(record.thread_id);<commit_msg>random colors instead hash-based ones used for coroutines<commit_after>// Copyright (c) 2013 <NAME>

#include "profiling_gui/flowdiagram.hpp"

#include <QGraphicsLineItem>
#include <QGraphicsRectItem>

#include <QDebug>

#include <random>

namespace profiling_gui {

FlowDiagram::FlowDiagram(QObject *parent) :
    QObject(parent)
{
}

void FlowDiagram::loadFile(const QString& path, QGraphicsScene* scene)
{
    _scene = scene;
    profiling_reader::reader reader(path.toStdString());

    _ticksPerNs = reader.ticks_per_ns();

    // collect data
    reader.for_each_by_time([this](const profiling_reader::record_type& record)
    {
        this->onRecord(record);
    });

    // build items
    for(const ThreadData& thread : _threads)
    {
        auto* item = new QGraphicsLineItem(thread.minTime, thread.y, thread.maxTime, thread.y);
        QPen pen(Qt::black);
        pen.setCosmetic(true);
        item->setPen(pen);
        scene->addItem(item);
    }
}

double FlowDiagram::ticksToTime(qint64 ticks) const
{
    return ticks / _ticksPerNs;
}

static QColor randomColor()
{
    static std::minstd_rand0 generator;

    int h = std::uniform_int_distribution<int>(0, 255)(generator);
    int s = 172;
    int v = 172;

    return QColor::fromHsv(h, s, v);
}

void FlowDiagram::onRecord(const profiling_reader::record_type& record)
{
    static const double THREAD_Y_SPACING = 100.0;
    static const double CORO_H = 5;

    if (!_threads.contains(record.thread_id))
    {
        ThreadData newThread;
        newThread.minTime = ticksToTime(record.time);
        newThread.y = _threads.size() * THREAD_Y_SPACING;

        _threads.insert(record.thread_id, newThread);
    }

    ThreadData& thread = _threads[record.thread_id];
    thread.maxTime = ticksToTime(record.time);

    // coroutines
    if (record.object_type == "coroutine")
    {
        CoroutineData& coroutine = _coroutines[record.object_id];

        if (!coroutine.color.isValid())
            coroutine.color = randomColor();

        if (record.event == "created")
            coroutine.name = QString::fromStdString(record.data);

        if (record.event == "enter")
        {
            //qWarning() << "Corotuine: enter. id=" << record.object_id << ", time= " << record.time << ",thread=" << record.thread_id;
            coroutine.enters[record.thread_id] = ticksToTime(record.time);
        }

        if (record.event == "exit")
        {
            if(!coroutine.enters.contains(record.thread_id))
            {
                qWarning() << "Corotuine: exit without enter! id=" << record.object_id << ", time= " << record.time << ",thread=" << record.thread_id;
            }
            else
            {
                double enterX =  coroutine.enters[record.thread_id];
                coroutine.enters.remove(record.thread_id);
{'fraction_non_alphanumeric': 0.13471045197740114, 'fraction_numerical': 0.006179378531073447, 'mean_word_length': 2.8854595336076816, 'pattern_counts': {'":': 0, '<': 62, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7365223', 'n_tokens_mistral': 1875, 'n_tokens_neox': 1816, 'n_words': 330}