Creating a TV Scheduler for Promotions between time breaks

Hi all!

Im relatively new in c++. I work at a TV provider and will soon start scheduling promos (between time breaks, for example every half hour or every hour according to the channel, there should be promotions or fillers).

I wanted to ask some advice as to how to start this program. My idea is to create an automatic scheduler that will smartly assign the promos or fillers respecting some parameters set.

I'll give you some examples:

The user should be able to define if the channel has 30 minutes or 1 hour breaks (in case of 30 minutes, 48 breaks in a day, 1 hour, 24).

Once defined, the user should input how many commercials have been booked (an should be able to apply a category to each one, for example: medicinal, cars, bank, etc, the time duration of the commercial and between with times it should be aired), for example a spot may be 40 seconds long, in category cars, and should air between 3 and 6.

Now comes the tricky part:

This scheduler should have priority for commercial spots (since they are a contract with the company that booked it and should be aired) but, in case there are empty time lapses, they should apply "fillers" (which are low priority time fillers to reach the ammount expected for the break).

So...

Each break lasts 2 minutes and, for the sake of the example, 80 seconds are booked by commercials and a filler should be scheduled of 40 seconds to fulfill the break.

But, 2 categories cant be one after the other (since it would cause competition between brands, for example audi and bmw cant promote one after the other because its a conflict of interest, so a filler should be applied in the middle to avoid is).

In summary:

The scheduler should allow the user to input how many breaks are in the day (since this varies between channels), how much the break lasts (for example, 2 minutes), how many commercials spots are there to be assigned (with their duration , category and the time interval in which it should air), and how many fillers are there and their category also (since there are marketing and pay per view fillers).

Also pay per view fillers should be applied between 0 a 7 am and marketing between 7 and 24.

Is this possible? How complicated is it really?

As I imagine it would go something as:

User inputs how many breaks and their duration, (example: 24 1 hour breaks)
User inputs how many promotions, their categories, and the expected air times. (example: promotion MKT102, category Cars, Should air between 2 and 5 am)
User inputs fillers and categories. (example FILLER02, category Pay Per View)

Scheduler runs with priority in assigning first commercial spots (checking no 2 categories are repeated and seeing that the time in the break is completely filled, if it is impossible to fill with non repeated commercials, add filler (if 0<CurrentTime<7 use filler Pay per view, if 7<CurrentTime<24 use filler Marketing). And, also, every time a filler is applied it should have a counter that goes +1 (as to avoid applying always the same filler and always apply the lowest number filler and vary the content).

If the spots are unplaceable (since categories are repeated and it cannot be avoided) it should say which spot couldn't be applied (since there might be overbooking).



Sorry for the huge text guys and thank you in advance if you read up to here and understood.

Any pointing me in the right direction will be much appreciated, and sorry if there are mispellings, im from Argentina :)
Last edited on
It looks pretty complicated (and also unrealistic, in my opinion: do tv advertisements all last the same time? Can programs be interrupted regardless what’s happening? I.e. can a film be interrupted while an high suspense scene is shown?), but the main point is: what’s your program supposed to do?
Should it perform a calculation and offer a rough summary?
If so, well, it requires a lot of calculation, but it’s not impossible. You could start by performing the basic (asking for number of advertisements and offering a basic summary) and, step by step, add new ‘parameters’ (advertisements of different length; later, different categories of advertisements... and so on).
You could start and see how long does it take you to perform the basic and then evaluate if it’s worth the time.

P.s. and sorry form my English too
Thank you for taking the time to answer.

Not all advertisements last the same time.

Up to now I'm working on a fstream input from a .txt file to a struct, creating the variables from the file (the advertisements) with the members; duration, id, client, category, limitA, limitB. (limit A is the lowest possible limit at which it can be placed and B the highest).

An example ad variable would be: ad1 with members: 20 seconds, 1, Audi, Cars, 09:00, 16:00.

Once this first part is finished (allowing users to paste the ads in a .txt in a certain format and the program imports them and assigns variables with struct to them) then I'll start working on the second part.

This consists of declaring the ammount of breaks in the day to be filled by the ads and then the placement of the imported ads respecting the following parameters:

- An ad must be placed between its members limitA and limitB, else skip to next ad.
- No 2 ads can be placed one after the other if they have the same client or category, if same category || client skip to next.
- No ads can be placed that last longer than the break, obviously.
- The break must be completely filled with ads before the program starts completing the next break.
- If no ad is available with the duration to fulfill the break, add a filler.
- The filler must be placed in the middle of the break.

I would need help with the following since I haven't figured it out yet:

> When importing from .txt file with fstream and getline, how do I get the program to assign different variables until all lines of the file have been assigned.
> Once variables ads have been created in struct, how do I tell the program to create the commercial breaks for the whole day and start filling out the breaks respecting the previous parameters.

Thanks!
The fact that you're trying to read this into a struct rather than a class suggests that you're not comfortable with C++ classes. Yes, structs and classes are the same except for default visibility, but classes are generally used when representing more that Plain Old Data (POD).

Before starting any code, I would lay this project out in pseudo-code. At a minimum, I would see an input file and class for breaks (when commercials can be scheduled), and a class for the commercials themselves. You will also need a class to represent times.

When importing from .txt file with fstream and getline, how do I get the program to assign different variables until all lines of the file have been assigned.

The easiest way is to use a stringstream. Read each record into a string, then create a stringstream from that string. Then you can use the input operator (>>) to pick out elements from the line.
1
2
3
4
5
6
7
8
9
  ifstream  ifs ("inputfile.txt");
  string line;
  
  while (getline (ifs,line))
  {  stringstream  ss (line);
      int duration;
      ss >> duration;
      // parse remaining elements
  }


Once variables ads have been created in struct, how do I tell the program to create the commercial breaks for the whole day and start filling out the breaks respecting the previous parameters.

You're going to need two vectors. One of commercials and one describing the breaks for the day. You will need to iterate through the breaks looking for commercials that fit.

Here's something to get you started:
// break.h
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

class Break
{   Time    time;
    double  duration;
    vector<Commercial>  scheduled;
    double  used;   // Time used in this break

public:
    Break ();
    static bool Load (vector<Break> & breaks);      
    bool fit_commercial (Commercial & commercial);
};


// commercial.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#pragma once
#include <string>
#include <vector>
#include "time.h"

class Commercial
{   double  duration;
    int     id;
    std::string  client;
    std::string  category;
    Time    limitA;
    Time    limitB;
    bool    scheduled;  //  true if this commercial has been scheduled
    
public:
    Commercial ();
    static bool Load (std::vector<Commercial> & commercials);
    //  Accessors
    bool is_scheduled() const;
    double get_duration () const;
    Time get_limitA() const;
    Time get_limitB() const;
    //  Mutators
    void set_schedule (bool state);
    //  I/O
    void Read (istream & is);
    friend istream & operator >> (istream & is, Commercial & commercial);
};


// time.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#pragma once

class Time
{   int hour;
    int minute;
    int second;

public:    
    Time ();
    Time (int hr, int min, int sec);
    
    void set_hour (int hr);
    void set_minute (int min);
    void set_second (int sec);
    
    bool operator > (const Time & rhs) const;
    bool operator < (const Time & rhs) const;
    bool operator == (const Time & rhs) const;
    bool operator != (const Time & rhs) const;
};


// time.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "time.h"

Time::Time() 
{   hour = 0;
    minute = 0;
    second = 0;
}

//standard constructor
Time::Time(int hr, int min, int sec)
{   hour = hr; 
    minute = min; 
    second = sec;
}

void Time::set_hour (int hr)
{   hour = hr;
}

void Time::set_minute (int min)
{   minute = min;
}

void Time::set_second (int sec)
{   second = sec;
}

bool Time::operator > (const Time & rhs) const
{   if (hour > rhs.hour)
        return true;
    if (hour == rhs.hour && minute > rhs.minute)
        return true;
    if (hour == rhs.hour && minute == rhs.minute && second > rhs.second)
        return true;
    return false;
}
            
bool Time::operator < (const Time & rhs) const
{   if (hour < rhs.hour)
        return true;
    if (hour == rhs.hour && minute < rhs.minute)
        return true;
    if (hour == rhs.hour && minute == rhs.minute && second < rhs.second)
        return true;
    return false;
}      

bool Time::operator == (const Time & rhs) const
{   return (hour == rhs.hour && minute == rhs.minute && second == rhs.second);
}

bool Time::operator != (const Time & rhs) const
{   return (hour != rhs.hour || minute != rhs.minute || second != rhs.second);
}


// break.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <vector>
using namespace std;

#include "commercial.h"
#include "break.h"

Break::Break ()
{   used = 0;
}

bool Break::Load (vector<Break> & breaks)
{   ifstream    inf ("breaks.txt");    
    string      line;
        
    if (! inf.is_open())
    {   cout << "Unable to open breaks.txt" << endl;
        return false;
    }
    while (getline (inf, line))
    {   Break       temp;
        //  *** Parse input line
        //  *** Set members of temp
        breaks.push_back (temp);
    }        
    return true;
}

bool Break::fit_commercial (Commercial & commercial)
{   if (commercial.is_scheduled())
        return false;   //  Already scheduled
    if (commercial.get_duration() > duration - used)
        return false;   //  Too long
    if (commercial.get_limitA() > time)
        return false;   //  Too early
    if (commercial.get_limitB() < time
        return false;   //  Too late        
    //  *** Check other exclude conditions
    //  We can schedule in this break
    commercial.set_scheduled(true);
    //  Add to the vector of commercials in this break    
    scheduled.push_back (commercial);
    //  Update the time scheduled so far in this break
    used += commercial.get_duration();
    return true;    //  Move to next commercial
}


// commercial.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
#include "commercial.h"

Commercial::Commercial ()
{   scheduled = false;
}

bool Commercial::is_scheduled () const
{   return scheduled;
}

//  Read the commercials into the vector
bool Commercial::Load (vector<Commercial> & commercials)
{   ifstream    inf ("commercials.txt");
    Commercial  temp;
    
    if (! inf.is_open())
    {   cout << "Unable to open commercials.txt" << endl;
        return false;
    }
    while (inf >> temp) 
        commercials.push_back (temp);    
    return true;
}

//  Read an input line from the commercials file
void Commercial::Read (istream & is)
{   string      line;

    if (! getline (is, line))
        return;
    //  *** Parse the input line
    //  *** Set the members of the instance    
}

//  Read a commercial from a stream
istream & operator >> (istream & is, Commercial & commercial)
{   commercial.Read (is);
    return is;
}    


// main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;

#include "time.h"
#include "commercial.h"
#include "break.h"

//  We will need to make multiple passes through this code 
//  until all commercials are scheduled, or all breaks are filled.                        
bool build_schedule (vector<Commercial> & commercials, vector<Break> & breaks)
{   vector<Break>::iterator         biter;
    vector<Commercial>::iterator    citer;
    
    //  Iterate through the breaks and try and find commercials to fit
    for (biter=breaks.begin(); biter!=breaks.end(); biter++)
    {   //  Iterate through the commercials and try and find one to fit
        for (citer=commercials.begin(); citer!=commercials.end(); citer++)
        {   if (biter->fit_commercial (*citer))
                break;
        }                
    }
    //  *** If all commercials scheduled or all breaks filled, return false
    return true;
}

int main ()
{   vector<Commercial>      commercials;
    vector<Break>           breaks;
    
    Commercial::Load (commercials);                
    Break::Load (breaks);
    while (build_schedule (commercials, breaks))
        ;
    //  *** Print the scheduled commercials from the breaks vector        
};    
Last edited on
That's really a great answer, AbstractionAnon!
I can't thank you enough AbstractionAno,

thanks for taking the time to explain this to me and for the perfect examples to get started.

You're right that I'm not comfortable with classes (because of my lack of experience). I'll definetly will use classes.

I'll get on it and, again, thank you! Will post the code once done.
Topic archived. No new replies allowed.