<commit_before>#include <sdl/SDLWindow.hpp>
#include <Assets.hpp>
#include <gl/Program.hpp>
#include <gl/VAO.hpp>
#include <boost/any.hpp>

#include <array>
#include <exception>

using namespace std;
using namespace tetra;

class Sink
{
public:
    virtual bool canHandle(boost::any msg) = 0;
    virtual void receive(boost::any msg) = 0;

    template <class SType>
    SType& addSink(SType&& sink)
    {
        auto mysink = unique_ptr<Sink>(new SType(move(sink)));
        observers.push_back(move(mysink));
        return (SType&)*observers[observers.size()-1];
    }

protected:
    void dispatch(boost::any msg)
    {
        for (auto& observer: observers)
        {
            if (observer->canHandle(msg))
            {
                observer->receive(msg);
            }
        }
    }

    vector<unique_ptr<Sink>> observers;
};

template <class T>
class TypedSignal : public Sink
{
public:
    T& value()
    {
        return lastValue;
    }

    virtual bool canHandle(boost::any msg) override
    {
        return msg.type() == boost::typeindex::type_id<T>();
    }

    virtual void receive(boost::any msg) override
    {
        lastValue = boost::any_cast<T>(msg);
    }

private:
    T lastValue;
};

class Observable : public Sink
{
public:
    using Handler = function<boost::any(boost::any)>;

    virtual bool canHandle(boost::any msg) override { return true; }

    virtual void receive(boost::any msg) override
    {
        dispatch(msg);
    }
};

template <class In, class Out>
class Map : public Sink
{
public:
    using Func = function<Out(In)>;

    Map(Func func)
    {
        myfunc = func;
    }

    virtual bool canHandle(boost::any msg) override
    {
        return true;
    }

    virtual void receive(boost::any msg) override
    {
        if (msg.type() == boost::typeindex::type_id<In>())
        {
            auto typedMsg = boost::any_cast<In>(msg);
            auto result = boost::any{myfunc(typedMsg)};
            dispatch(result);
        }
        else
        {
            dispatch(msg);
        }
    }

private:
    Func myfunc;
};

struct Vertex
{
    array<float, 2> pos;

    Vertex() = default;
    Vertex(float x, float y) : pos{x, y} {}
};

void sdlmain()
{
    auto pump = Observable{};
    auto& signal = pump
        .addSink(Map<int, string>{[](int i) { return to_string(i); }})
        .addSink(Map<float, string>{[](float f) { return "turbo float " + to_string(f); }})
        .addSink(TypedSignal<string>{});

    auto& otherSig = pump
       .addSink(TypedSignal<int>{});

    pump.receive({3});
    pump.receive({string("aoeu")});
    pump.receive({3.12f});

    cout << signal.value() << endl;
    cout << otherSig.value() << endl;

    return ;
    auto sdl = SDL{};
    auto window = SDLWindow::Builder{}.build();
    auto gl = window.contextBuilder()
        .majorVersion(3)
        .minorVersion(3)
        .build();

    auto vertex = Shader{ShaderType::VERTEX};
    auto fragment = Shader{ShaderType::FRAGMENT};
    fragment.compile(loadShaderSrc("identity.frag"));<commit_msg>things happening<commit_after>#include <sdl/SDLWindow.hpp>
#include <Assets.hpp>
#include <gl/Program.hpp>
#include <gl/VAO.hpp>
#include <boost/any.hpp>

#include <array>
#include <exception>

using namespace std;
using namespace tetra;

class Transform
{
public:
    virtual bool applies(boost::any& msg) { return true; };
    virtual boost::any apply(boost::any& msg) { return msg; };
};

template <class T>
class Signal : public Transform
{
public:
    virtual bool applies(boost::any& msg)
    {
        return boost::typeindex::type_id<T>() == msg.type();
    }

    virtual boost::any apply(boost::any& msg)
    {
        lastValue = boost::any_cast<T>(msg);
        return msg;
    }

    T& get()
    {
        return lastValue;
    }

private:
    T lastValue;
};

class Stream
{
public:
    void push(boost::any msg)
    {
        for (auto& downstream : downstreams)
        {
            auto& transform = downstream.first;
            auto& stream = downstream.second;

            if (transform.applies(msg))
            {
                auto transformed = transform.apply(msg);
                if (!transformed.empty())
                {
                    stream->push(transformed);
                }
            }
            else
            {
                stream->push(msg);
            }
        }
    }

    Stream& transform(Transform& transform)
    {
        unique_ptr<Stream> downstream;
        Stream* streamPtr = downstream.get();

        downstreams.push_back({transform, move(downstream)});
        return *streamPtr;
    }
private:
    vector<pair<Transform, unique_ptr<Stream>>> downstreams;
};

struct Vertex
{
    array<float, 2> pos;

    Vertex() = default;
    Vertex(float x, float y) : pos{x, y} {}
};

void sdlmain()
{
    return ;
    auto sdl = SDL{};
    auto window = SDLWindow::Builder{}.build();
    auto gl = window.contextBuilder()
        .majorVersion(3)
        .minorVersion(3)
        .build();

    auto vertex = Shader{ShaderType::VERTEX};
    auto fragment = Shader{ShaderType::FRAGMENT};
    fragment.compile(loadShaderSrc("identity.frag"));
{'fraction_non_alphanumeric': 0.13970588235294118, 'fraction_numerical': 0.0025154798761609907, 'mean_word_length': 2.3895081967213114, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 46, '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': '4198794', 'n_tokens_mistral': 1675, 'n_tokens_neox': 1613, 'n_words': 363}