multiautocook.cpp 4.91 KB
#include "multiautocook.h"

#include "oven.h"

MultiAutoCook::MultiAutoCook(QObject *parent) : MultiCook(parent)
{
    name_ = "";
    mode_ = Define::InvalidMode;
    state = Idle;
    isModifying = false;
    increasedTimeCount = 6;
    decreasedTimeCount = 6;

    checkTimer.setInterval(100);
    connect(&checkTimer, SIGNAL(timeout()), SLOT(check()));
}

QString MultiAutoCook::name()
{
    return name_;
}

Define::Mode MultiAutoCook::mode()
{
    return mode_;
}

int MultiAutoCook::temperature()
{
    if (steps.isEmpty())
        return 30;

    return steps.first().temperature;
}

int MultiAutoCook::humidity()
{
    if (steps.isEmpty())
        return 0;

    return steps.first().humidity;
}

int MultiAutoCook::remainingTime()
{
    if (steps.isEmpty())
        return 0;

    if (isModifying)
    {
        int t = 0;
        foreach (const Step &s, modifiedSteps)
            t += s.time;

        return t;
    }

    if (state == Running)
        updateTime();

    int t = 0;
    foreach (const Step &s, steps)
        t += s.time;

    return t;
}

void MultiAutoCook::increaseTime()
{
    if (state == Finished)
        return;

    if (!isModifying)
    {
        isModifying = true;
        updateTime();
        modifiedSteps = steps;
    }

    modifiedSteps.last().time += 60 * 1000;
}

void MultiAutoCook::decreaseTime()
{
    if (state == Finished)
        return;

    if (!isModifying)
    {
        isModifying = true;
        updateTime();
        modifiedSteps = steps;
    }

    Step &s = modifiedSteps.last();
    s.time = qMax(30 * 1000, s.time - 60 * 1000);
}

void MultiAutoCook::setTime()
{
    if (state == Finished)
        return;

    if (!isModifying)
        return;

    isModifying = false;
    elapsed.start();
    steps = modifiedSteps;
}

void MultiAutoCook::start()
{
    state = Running;
    elapsed.start();
    decreasedTime.start();

    checkTimer.start();
}

void MultiAutoCook::stop()
{
    state = Finished;
    checkTimer.stop();
}

void MultiAutoCook::pause()
{
    if (state != Running)
        return;

    state = Paused;
    decreasedTime.pause();
    if (increasedTime.isValid())
        increasedTime.pause();

    updateTime();

    checkTimer.stop();
}

void MultiAutoCook::resume()
{
    if (state != Paused)
        return;

    state = Running;
    steps.last().time += 30 * 1000;
    elapsed.start();
    decreasedTime.resume();
    if (increasedTime.isValid())
        increasedTime.resume();
}

MultiCook *MultiAutoCook::clone(QObject *parent)
{
    MultiAutoCook *c = new MultiAutoCook(parent);
    c->name_ = name_;
    c->mode_ = mode_;
    c->steps = steps;

    return (MultiCook *) c;
}

bool MultiAutoCook::equals(MultiCook *other)
{
    MultiAutoCook *o = qobject_cast<MultiAutoCook *>(other);
    if (o == Q_NULLPTR)
        return false;

    if (o->name_ != name_)
        return false;

    if (o->mode_ != mode_)
        return false;

    if (o->steps != steps)
        return false;

    return true;
}

void MultiAutoCook::setName(QString name)
{
    name_ = name;
}

void MultiAutoCook::setMode(Define::Mode mode)
{
    mode_ = mode;
}

void MultiAutoCook::append(int temperature, int humidity, int time)
{
    if (temperature < 30 || temperature > 300)
        return;

    if (humidity < 0 || humidity > 100)
        return;

    if (time < 0 || time > 24 * 60 * 60)
        return;

    steps.append(Step{temperature, humidity, time * 1000});
}

void MultiAutoCook::updateTime()
{
    int e = elapsed.restart();

    while (steps.size() > 0)
    {
        Step &s = steps.first();
        if (s.time > e)
        {
            s.time -= e;
            break;
        }

        e -= s.time;
        steps.removeFirst();
    }
}

void MultiAutoCook::check()
{
    if (state != Running)
        return;

    int dt = Oven::getInstance()->currentTemp() - temperature();

    // checking under temperature
    if ((remainingTime() < 10 * 60 * 1000 && increasedTime.isNull())
            || (increasedTime.isValid() && increasedTime.elapsed() > 3 * 60 * 1000))
    {
        increasedTime.start();
        if (dt < -20 && increasedTimeCount > 0)
        {
            increasedTimeCount--;

            steps.last().time += remainingTime() * 0.1;
        }
    }

    // checking over temperature
    if (decreasedTime.elapsed() > 2 * 60 * 1000)
    {
        decreasedTime.start();
        if (dt > 20 && decreasedTimeCount > 0)
        {
            decreasedTimeCount--;

            Step &s = steps.last();
            if (s.time > 30 * 1000)
            {
                s.time -= remainingTime() * 0.2;
                if (s.time < 30 * 1000)
                    s.time = 30 * 1000;
            }
        }
    }

    if (remainingTime() <= 0)
        stop();
}

bool MultiAutoCook::Step::operator==(const MultiAutoCook::Step &other)
{
    if (other.temperature != temperature)
        return false;
    if (other.humidity != humidity)
        return false;
    if (other.time != time)
        return false;

    return true;
}