// etabench
// Copyright (C) 2022 xaizek <xaizek@posteo.net>
//
// This file is part of etabench.
//
// etabench is free software: you can redistribute it and/or modify
// it under the terms of version 3 of the GNU General Public License
// as published by the Free Software Foundation.
//
// etabench is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with etabench. If not, see <https://www.gnu.org/licenses/>.
#ifndef ETABENCH__ALGS_HPP__
#define ETABENCH__ALGS_HPP__
#include <functional>
#include <map>
#include <memory>
#include <vector>
#include "core.hpp"
class Window
{
using weight_f = std::function<float(int idx, float lastWeight)>;
public:
// Pass in negative size for unlimited window size.
Window(int size, weight_f weight) : size(size), weight(weight)
{ }
public:
void clear()
{ data.clear(); }
void extend(float datum)
{
// Emulating circular buffer.
data.push_back(datum);
if ((int)data.size() == size) {
data.erase(data.cbegin());
}
}
float getValue() const
{
float v = 0.0f;
float totalWeight = 0.0f;
float w = 0;
for (int i = 0; float datum : data) {
w = weight(i++, w);
v += w*datum;
totalWeight += w;
}
v /= totalWeight;
return v;
}
float update(float datum)
{
extend(datum);
return getValue();
}
private:
int size;
weight_f weight;
std::vector<float> data;
};
class AverageAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "Average"; }
virtual void reset() override
{ }
virtual int estimate(int current, int total, int time) override;
};
class ImmediateAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "Immediate"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
};
class CombinedAlg : public EtaAlg
{
public:
explicit CombinedAlg(std::vector<std::unique_ptr<EtaAlg>> algs);
public:
virtual std::string getName() const override;
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
std::vector<std::unique_ptr<EtaAlg>> algs;
};
// Immediage speed whose next value is clamped by its previous value times +-2%.
class ImmChangeLimitAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "ImmChangeLimit"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
float lastSpeed;
};
// Average speed whose next value is clamped by its previous value times +-2%.
class AveChangeLimitAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "AveChangeLimit"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
float lastSpeed;
};
// Limited average that looks back `delay` seconds.
class LookBackAlg : public EtaAlg
{
struct Point {
int time;
int current;
};
public:
explicit LookBackAlg(int delay);
public:
virtual std::string getName() const override
{ return "LookBack " + std::to_string(delay); }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int delay;
std::vector<Point> points;
};
class AccelerationAlg : public EtaAlg
{
public:
AccelerationAlg();
public:
virtual std::string getName() const override
{ return "Acceleration"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
int lastEta;
float lastV;
Window speeds;
Window etas;
};
class SwitchAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "Switch"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
std::map<int, int> history;
int lastProgress;
};
class GravityAlg : public EtaAlg
{
public:
GravityAlg();
public:
virtual std::string getName() const override
{ return "Gravity"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
float avgProgressRate;
float avgSeekRate;
Window speeds;
};
class FirefoxAlg : public EtaAlg
{
public:
virtual std::string getName() const override
{ return "Firefox"; }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastTime;
int lastProgress;
float lastEta;
float speed;
};
class SmoothingAlg : public EtaAlg
{
public:
explicit SmoothingAlg(int alpha) : alpha(alpha)
{ }
public:
virtual std::string getName() const override
{ return "Smoothing 0." + std::to_string(alpha); }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastTime;
int lastProgress;
int lastEta;
int alpha;
float speed;
};
class SlownessAlg : public EtaAlg
{
public:
explicit SlownessAlg(int decay) : decay(decay)
{ }
public:
virtual std::string getName() const override
{ return "Slowness " + std::to_string(decay); }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
int lastEta;
float totalEta;
int decay;
};
class WindowAlg : public EtaAlg
{
public:
WindowAlg(int windowSize, float alpha);
public:
virtual std::string getName() const override;
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int windowSize;
float alpha;
int lastTime;
int lastProgress;
int lastEta;
Window speeds;
};
class ExponentialAlg : public EtaAlg
{
public:
explicit ExponentialAlg(int decay) : decay(decay)
{ }
public:
virtual std::string getName() const override
{ return "Exponential " + std::to_string(decay); }
virtual void reset() override;
virtual int estimate(int current, int total, int time) override;
private:
int lastProgress;
int lastTime;
int lastEta;
float rateEst;
int decay;
};
#endif // ETABENCH__ALGS_HPP__
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/etabench
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/etabench
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master