HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Scheduling a task into a period within a day, depending on whether or not it is a weekend

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
schedulingperiodintoweekendwithindependingwhetherdaytasknot

Problem

I have a function which needs to detect part of the day depending on whether it's the weekend or not (the weekend affects the lunch time indication). The method is quite long and I'd like to know how it can be better.

```
double PartOfDayRule::ExtractFeature(dto::ActionableItem & item) {
double morning, firstWorkPart, lunch, secondWorkPart, afterWork, beforeSleep, sleepTime;
morning = 0;
firstWorkPart = 1;
lunch = 2;
secondWorkPart = 3;
afterWork = 4;
beforeSleep = 5;
sleepTime = 6;

double result = -1;
dto::DateTime itemTime = item.scheduledStart;
if(util::time::inRange(item.ctx->sleepTimeEnd, item.ctx->workTimeStart, itemTime)){
result = morning;
goto result;
}

dto::DateTime lunchStart;
dto::DateTime lunchStop;
if(!item.ctx->isWorkingDay){
lunchStart = item.ctx->workTimeStart;
lunchStop = item.ctx->workTimeFinished;
}else{
long firstWorkPartLength = util::time::between(item.ctx->workTimeStart, item.ctx->workTimeFinished) / 2;
lunchStart = item.ctx->workTimeStart + std::chrono::hours{firstWorkPartLength};
lunchStop = lunchStart + std::chrono::hours{1};
}
if(util::time::inRange(lunchStart, lunchStop, itemTime)){
result = lunch;
goto result;
}

if(util::time::inRange(item.ctx->workTimeStart, lunchStart, itemTime)){
result = firstWorkPart;
goto result;
}

if(util::time::inRange(lunchStop, item.ctx->workTimeFinished, itemTime)){
result = secondWorkPart;
goto result;

Solution

You return what is effectively an enum as a double. Why? create the enum and return that it's much clearer that way wat the return value means:

If you still want a single point of return (for whatever reason) then you can use an if-else chain:

enum PartOfDay{
    morning = 0,
    firstWorkPart = 1,
    lunch = 2,
    secondWorkPart = 3,
    afterWork = 4,
    beforeSleep = 5,
    sleepTime = 6
}

PartOfDay PartOfDayRule::ExtractFeature(dto::ActionableItem & item) {

    dto::DateTime lunchStart;
    dto::DateTime lunchStop;
    if(!item.ctx->isWorkingDay){
        lunchStart = item.ctx->workTimeStart;
        lunchStop = item.ctx->workTimeFinished;
    }else{
        long firstWorkPartLength = util::time::between(item.ctx->workTimeStart, item.ctx->workTimeFinished) / 2;
        lunchStart = item.ctx->workTimeStart + std::chrono::hours{firstWorkPartLength};
        lunchStop = lunchStart + std::chrono::hours{1};
    }

    dto::DateTime itemTime = item.scheduledStart;
    dto::DateTime sleepPreparationTime = item.ctx->sleepTimeStart - std::chrono::hours{1};
    PartOfDay result = sleepTime;

    if(util::time::inRange(item.ctx->sleepTimeEnd, item.ctx->workTimeStart, itemTime)){
        result = morning;
    } else if(util::time::inRange(item.ctx->workTimeStart, lunchStart, itemTime)){
        result = firstWorkPart;
    } else if(util::time::inRange(lunchStart, lunchStop, itemTime)){
        result = lunch;
    } else if(util::time::inRange(lunchStop, item.ctx->workTimeFinished, itemTime)){
        result = secondWorkPart;
    }else if(util::time::inRange(item.ctx->workTimeFinished, sleepPreparationTime, itemTime)){
        result = afterWork;
    }else if(util::time::inRange(sleepPreparationTime, item.ctx->sleepTimeStart, itemTime)){
        result = beforeSleep;
    }else {
        result = sleepTime;
    }
    return result;

}


Or you can sort the ranges and then use std::find to get the range you want.

Code Snippets

enum PartOfDay{
    morning = 0,
    firstWorkPart = 1,
    lunch = 2,
    secondWorkPart = 3,
    afterWork = 4,
    beforeSleep = 5,
    sleepTime = 6
}

PartOfDay PartOfDayRule::ExtractFeature(dto::ActionableItem & item) {

    dto::DateTime lunchStart;
    dto::DateTime lunchStop;
    if(!item.ctx->isWorkingDay){
        lunchStart = item.ctx->workTimeStart;
        lunchStop = item.ctx->workTimeFinished;
    }else{
        long firstWorkPartLength = util::time::between<std::chrono::hours>(item.ctx->workTimeStart, item.ctx->workTimeFinished) / 2;
        lunchStart = item.ctx->workTimeStart + std::chrono::hours{firstWorkPartLength};
        lunchStop = lunchStart + std::chrono::hours{1};
    }

    dto::DateTime itemTime = item.scheduledStart;
    dto::DateTime sleepPreparationTime = item.ctx->sleepTimeStart - std::chrono::hours{1};
    PartOfDay result = sleepTime;

    if(util::time::inRange(item.ctx->sleepTimeEnd, item.ctx->workTimeStart, itemTime)){
        result = morning;
    } else if(util::time::inRange(item.ctx->workTimeStart, lunchStart, itemTime)){
        result = firstWorkPart;
    } else if(util::time::inRange(lunchStart, lunchStop, itemTime)){
        result = lunch;
    } else if(util::time::inRange(lunchStop, item.ctx->workTimeFinished, itemTime)){
        result = secondWorkPart;
    }else if(util::time::inRange(item.ctx->workTimeFinished, sleepPreparationTime, itemTime)){
        result = afterWork;
    }else if(util::time::inRange(sleepPreparationTime, item.ctx->sleepTimeStart, itemTime)){
        result = beforeSleep;
    }else {
        result = sleepTime;
    }
    return result;

}

Context

StackExchange Code Review Q#146676, answer score: 4

Revisions (0)

No revisions yet.