Hi everyone
I wonder if anyone can help me with this problem. I have been trying - with various levels of success - for a couple of weeks
Basically I would like to write a Perl script that would dynamically create a staff rota for a [red]restaurant[/red] each week
I have a friend - Sophia - who is a manager at a restaurant and she is responsible for this task. I went through the procedure with her and it is not easy by any means!
As an interim I have written an Excel spreadsheet to assist with the task - implementing conditional formatting, etc.
I hope to eventually create a dynamic script that will churn away and come up with the 'best' option - if this is possible... nothing is impossible, right?
The script - to be adaptable - will require the following:-
Variable number of shifts over the week - each shift having a required number of staff [tt]e.g. [blue]@quota = qw(7 7 7 7 7 8 8 8 8 9 9 9 9 7);[/blue][/tt]
This would set up a main loop with 14 shifts, each reflecting the number of staff required
Variable numbers of staff
Staff aptitude scores - once the script has come up with a potential rota these scores can be used to calculate the suitability of the rota
(i.e. if a poor member of staff is on the floor on a Saturday night it will score that far worse than if it was a more competent member of staff)
Definite & Requested days off - requested days off are not necessarily actioned
This is a tabulated example of Sophia's restaurant, with the staff quotas:-
[tt]shift 00 => 7 00 01 02 03 04 05 06 07
shift 01 => 7 00 01 02 03 04 05 06 07
shift 02 => 7 00 01 02 03 04 05 06 07
shift 03 => 7 00 01 02 03 04 05 06 07
shift 04 => 7 00 01 02 03 04 05 06 07
shift 05 => 8 00 01 02 03 04 05 06 07 08
shift 06 => 8 00 01 02 03 04 05 06 07 08
shift 07 => 8 00 01 02 03 04 05 06 07 08
shift 08 => 8 00 01 02 03 04 05 06 07 08
shift 09 => 9 00 01 02 03 04 05 06 07 08 09
shift 10 => 9 00 01 02 03 04 05 06 07 08 09
shift 11 => 9 00 01 02 03 04 05 06 07 08 09
shift 12 => 9 00 01 02 03 04 05 06 07 08 09
shift 13 => 7 00 01 02 03 04 05 06 07[/tt]
I have taken the current listing of MVP's (and others) from the Perl forum and given them all aptitude scores:-
Please don't be offended by the scores - they are not an actual indication of suitability to be a waiter!
PaulTEG[red],100[/red]
rharsh[red],90[/red]
duncdude[red],80[/red]
dchoulette[red],70[/red]
nawlej[red],60[/red]
mikevh[red],50[/red]
TomThumbKP[red],40[/red]
parkers[red],30[/red]
Rieekan[red],20[/red]
MikeLacey[red],10[/red]
ag5t[red],5[/red]
hermes1[red],5[/red]
pwils025[red],5[/red]
rab54[red],5[/red]
timgerr[red],5[/red]
peacecodotnet[red],5[/red]
nix45[red],5[/red]
Ramnarayan[red],5[/red]
Valerie[red],5[/red]
TheGenius22[red],5[/red]
Now i'll output some potential rotas and their scores (the number of people required on the shift is also used in governing the suitability of the member of staff in that slot
It makes more sense visually - here are 3 examples:-
[tt]
00 parkers|30*7 nixFourtyFive|5*7 dchoulette|70*7 rabFiftyFour|5*7 Ramnarayan|5*7 Valerie|5*7 mikevh|50*7
01 hermes|5*7 Rieekan|20*7 pwils|5*7 Valerie|5*7 nixFourtyFive|5*7 rharsh|90*7 dchoulette|70*7
02 ag5t|5*7 nixFourtyFive|5*7 mikevh|50*7 TheGenius|5*7 Rieekan|20*7 nawlej|60*7 Valerie|5*7
03 peacecodotnet|5*7 mikevh|50*7 nawlej|60*7 duncdude|80*7 TheGenius|5*7 pwils|5*7 dchoulette|70*7
04 dchoulette|70*7 Valerie|5*7 MikeLacey|10*7 TomThumbKP|40*7 pwils|5*7 Rieekan|20*7 Ramnarayan|5*7
05 hermes|5*8 MikeLacey|10*8 Valerie|5*8 ag5t|5*8 peacecodotnet|5*8 Rieekan|20*8 nixFourtyFive|5*8 Ramnarayan|5*8
06 ag5t|5*8 Ramnarayan|5*8 TomThumbKP|40*8 rabFiftyFour|5*8 MikeLacey|10*8 Valerie|5*8 rharsh|90*8 Rieekan|20*8
07 TheGenius|5*8 rharsh|90*8 nixFourtyFive|5*8 nawlej|60*8 parkers|30*8 hermes|5*8 mikevh|50*8 rabFiftyFour|5*8
08 dchoulette|70*8 nixFourtyFive|5*8 ag5t|5*8 Ramnarayan|5*8 TheGenius|5*8 nawlej|60*8 duncdude|80*8 pwils|5*8
09 duncdude|80*9 pwils|5*9 parkers|30*9 ag5t|5*9 Rieekan|20*9 Ramnarayan|5*9 nixFourtyFive|5*9 timgerr|5*9 dchoulette|70*9
10 Valerie|5*9 TomThumbKP|40*9 timgerr|5*9 parkers|30*9 Ramnarayan|5*9 nawlej|60*9 mikevh|50*9 MikeLacey|10*9 nixFourtyFive|5*9
11 rabFiftyFour|5*9 Ramnarayan|5*9 parkers|30*9 TheGenius|5*9 Rieekan|20*9 rharsh|90*9 hermes|5*9 timgerr|5*9 nawlej|60*9
12 Valerie|5*9 parkers|30*9 TomThumbKP|40*9 hermes|5*9 Rieekan|20*9 MikeLacey|10*9 pwils|5*9 TheGenius|5*9 dchoulette|70*9
13 pwils|5*7 MikeLacey|10*7 nixFourtyFive|5*7 dchoulette|70*7 ag5t|5*7 Rieekan|20*7 TomThumbKP|40*7
--- attempt 1 => completed --- [red]score 21185[/red] ---
00 pwils|5*7 TomThumbKP|40*7 peacecodotnet|5*7 rharsh|90*7 parkers|30*7 nixFourtyFive|5*7 timgerr|5*7
01 MikeLacey|10*7 dchoulette|70*7 nawlej|60*7 ag5t|5*7 hermes|5*7 timgerr|5*7 Valerie|5*7
02 TomThumbKP|40*7 duncdude|80*7 dchoulette|70*7 hermes|5*7 parkers|30*7 MikeLacey|10*7 nawlej|60*7
03 TheGenius|5*7 Valerie|5*7 MikeLacey|10*7 peacecodotnet|5*7 nawlej|60*7 hermes|5*7 rabFiftyFour|5*7
04 dchoulette|70*7 rharsh|90*7 TomThumbKP|40*7 Valerie|5*7 duncdude|80*7 nixFourtyFive|5*7 rabFiftyFour|5*7
05 rharsh|90*8 rabFiftyFour|5*8 MikeLacey|10*8 peacecodotnet|5*8 mikevh|50*8 nixFourtyFive|5*8 nawlej|60*8 Valerie|5*8
06 ag5t|5*8 hermes|5*8 TheGenius|5*8 parkers|30*8 timgerr|5*8 nawlej|60*8 pwils|5*8 TomThumbKP|40*8
07 parkers|30*8 timgerr|5*8 Valerie|5*8 ag5t|5*8 Ramnarayan|5*8 pwils|5*8 dchoulette|70*8 nawlej|60*8
08 duncdude|80*8 Valerie|5*8 parkers|30*8 hermes|5*8 nawlej|60*8 TheGenius|5*8 ag5t|5*8 Rieekan|20*8
09 peacecodotnet|5*9 Ramnarayan|5*9 parkers|30*9 nixFourtyFive|5*9 dchoulette|70*9 rabFiftyFour|5*9 nawlej|60*9 rharsh|90*9 TomThumbKP|40*9
10 nixFourtyFive|5*9 TheGenius|5*9 nawlej|60*9 duncdude|80*9 rharsh|90*9 Rieekan|20*9 TomThumbKP|40*9 rabFiftyFour|5*9 dchoulette|70*9
11 dchoulette|70*9 hermes|5*9 pwils|5*9 parkers|30*9 rabFiftyFour|5*9 Rieekan|20*9 TheGenius|5*9 mikevh|50*9 Ramnarayan|5*9
12 mikevh|50*9 peacecodotnet|5*9 TomThumbKP|40*9 ag5t|5*9 pwils|5*9 hermes|5*9 Ramnarayan|5*9 rabFiftyFour|5*9 parkers|30*9
13 rharsh|90*7 hermes|5*7 nawlej|60*7 parkers|30*7 timgerr|5*7 dchoulette|70*7 Valerie|5*7
--- attempt 2 => completed --- [red]score 24540[/red] ---
00 mikevh|50*7 nawlej|60*7 Ramnarayan|5*7 Rieekan|20*7 Valerie|5*7 ag5t|5*7 rabFiftyFour|5*7
01 TheGenius|5*7 duncdude|80*7 pwils|5*7 rabFiftyFour|5*7 Valerie|5*7 nawlej|60*7 rharsh|90*7
02 TomThumbKP|40*7 rabFiftyFour|5*7 mikevh|50*7 TheGenius|5*7 nawlej|60*7 pwils|5*7 parkers|30*7
03 mikevh|50*7 TomThumbKP|40*7 Ramnarayan|5*7 nawlej|60*7 nixFourtyFive|5*7 Valerie|5*7 TheGenius|5*7
04 peacecodotnet|5*7 rharsh|90*7 pwils|5*7 Valerie|5*7 TomThumbKP|40*7 timgerr|5*7 MikeLacey|10*7
05 TomThumbKP|40*8 Rieekan|20*8 MikeLacey|10*8 hermes|5*8 dchoulette|70*8 timgerr|5*8 TheGenius|5*8 mikevh|50*8
06 Rieekan|20*8 nawlej|60*8 peacecodotnet|5*8 rabFiftyFour|5*8 parkers|30*8 rharsh|90*8 nixFourtyFive|5*8 timgerr|5*8
07 ag5t|5*8 TomThumbKP|40*8 parkers|30*8 dchoulette|70*8 mikevh|50*8 Valerie|5*8 timgerr|5*8 peacecodotnet|5*8
08 parkers|30*8 dchoulette|70*8 Ramnarayan|5*8 peacecodotnet|5*8 pwils|5*8 nawlej|60*8 TomThumbKP|40*8 MikeLacey|10*8
09 peacecodotnet|5*9 nawlej|60*9 Rieekan|20*9 mikevh|50*9 MikeLacey|10*9 rharsh|90*9 TheGenius|5*9 duncdude|80*9 nixFourtyFive|5*9
10 peacecodotnet|5*9 TheGenius|5*9 timgerr|5*9 TomThumbKP|40*9 nixFourtyFive|5*9 hermes|5*9 nawlej|60*9 rharsh|90*9 dchoulette|70*9
11 duncdude|80*9 rabFiftyFour|5*9 mikevh|50*9 TheGenius|5*9 parkers|30*9 pwils|5*9 timgerr|5*9 ag5t|5*9 Rieekan|20*9
12 parkers|30*9 pwils|5*9 duncdude|80*9 rabFiftyFour|5*9 dchoulette|70*9 TheGenius|5*9 Ramnarayan|5*9 TomThumbKP|40*9 nawlej|60*9
13 MikeLacey|10*7 pwils|5*7 nawlej|60*7 nixFourtyFive|5*7 rabFiftyFour|5*7 mikevh|50*7 timgerr|5*7
--- attempt 3 => completed --- [red]score 24370[/red] ---[/tt]
As you can see the script loops through the shifts - from 0..13 in this case (14 shifts in total - Monday A.M. through to Sunday P.M.)
It then enters another loop - the number of staff required to cover the shift - and takes people from the staff list until the quota ... and then on to the next shift
This is all scored:-
staff member's competency x shift quota - and added up to give a total score for the rota
In theory, after hundreds of thousands of attempts, the highest score should be a very decent rota
But... My method is using random values. This essentially means that someone might never appear on the rota. Unlikely but possible.
Is there a way that each cell could be revolved like a car mileometer? This would mean that EVERY permutation would be covered.
Finally, bear in mind that someone cannot possibly work if they have a definite day off - but could (if necessary) if they have a requested day off
Other things to bear in mind are that it would be nice if no one was doing too many 'double' shifts - for example.
Really this is just common sense. At the end of the day the best rota is the one that evenly shares out the shifts among the members of staff,
puts the strongest members of staff on the more difficult shifts, and takes into account the rules
I know this is a fair bit of information but I can get quite close to a model within a few lines of code - and i'm a muppet!
I'd really appreciate some help on this - it is quite an interesting problem!
My brain is on fire now - if i've made an glaring errors in this post please let me know
Kind Regards
Duncan
I wonder if anyone can help me with this problem. I have been trying - with various levels of success - for a couple of weeks
Basically I would like to write a Perl script that would dynamically create a staff rota for a [red]restaurant[/red] each week
I have a friend - Sophia - who is a manager at a restaurant and she is responsible for this task. I went through the procedure with her and it is not easy by any means!
As an interim I have written an Excel spreadsheet to assist with the task - implementing conditional formatting, etc.
I hope to eventually create a dynamic script that will churn away and come up with the 'best' option - if this is possible... nothing is impossible, right?
The script - to be adaptable - will require the following:-
Variable number of shifts over the week - each shift having a required number of staff [tt]e.g. [blue]@quota = qw(7 7 7 7 7 8 8 8 8 9 9 9 9 7);[/blue][/tt]
This would set up a main loop with 14 shifts, each reflecting the number of staff required
Variable numbers of staff
Staff aptitude scores - once the script has come up with a potential rota these scores can be used to calculate the suitability of the rota
(i.e. if a poor member of staff is on the floor on a Saturday night it will score that far worse than if it was a more competent member of staff)
Definite & Requested days off - requested days off are not necessarily actioned
This is a tabulated example of Sophia's restaurant, with the staff quotas:-
[tt]shift 00 => 7 00 01 02 03 04 05 06 07
shift 01 => 7 00 01 02 03 04 05 06 07
shift 02 => 7 00 01 02 03 04 05 06 07
shift 03 => 7 00 01 02 03 04 05 06 07
shift 04 => 7 00 01 02 03 04 05 06 07
shift 05 => 8 00 01 02 03 04 05 06 07 08
shift 06 => 8 00 01 02 03 04 05 06 07 08
shift 07 => 8 00 01 02 03 04 05 06 07 08
shift 08 => 8 00 01 02 03 04 05 06 07 08
shift 09 => 9 00 01 02 03 04 05 06 07 08 09
shift 10 => 9 00 01 02 03 04 05 06 07 08 09
shift 11 => 9 00 01 02 03 04 05 06 07 08 09
shift 12 => 9 00 01 02 03 04 05 06 07 08 09
shift 13 => 7 00 01 02 03 04 05 06 07[/tt]
I have taken the current listing of MVP's (and others) from the Perl forum and given them all aptitude scores:-
Please don't be offended by the scores - they are not an actual indication of suitability to be a waiter!
PaulTEG[red],100[/red]
rharsh[red],90[/red]
duncdude[red],80[/red]
dchoulette[red],70[/red]
nawlej[red],60[/red]
mikevh[red],50[/red]
TomThumbKP[red],40[/red]
parkers[red],30[/red]
Rieekan[red],20[/red]
MikeLacey[red],10[/red]
ag5t[red],5[/red]
hermes1[red],5[/red]
pwils025[red],5[/red]
rab54[red],5[/red]
timgerr[red],5[/red]
peacecodotnet[red],5[/red]
nix45[red],5[/red]
Ramnarayan[red],5[/red]
Valerie[red],5[/red]
TheGenius22[red],5[/red]
Now i'll output some potential rotas and their scores (the number of people required on the shift is also used in governing the suitability of the member of staff in that slot
It makes more sense visually - here are 3 examples:-
[tt]
00 parkers|30*7 nixFourtyFive|5*7 dchoulette|70*7 rabFiftyFour|5*7 Ramnarayan|5*7 Valerie|5*7 mikevh|50*7
01 hermes|5*7 Rieekan|20*7 pwils|5*7 Valerie|5*7 nixFourtyFive|5*7 rharsh|90*7 dchoulette|70*7
02 ag5t|5*7 nixFourtyFive|5*7 mikevh|50*7 TheGenius|5*7 Rieekan|20*7 nawlej|60*7 Valerie|5*7
03 peacecodotnet|5*7 mikevh|50*7 nawlej|60*7 duncdude|80*7 TheGenius|5*7 pwils|5*7 dchoulette|70*7
04 dchoulette|70*7 Valerie|5*7 MikeLacey|10*7 TomThumbKP|40*7 pwils|5*7 Rieekan|20*7 Ramnarayan|5*7
05 hermes|5*8 MikeLacey|10*8 Valerie|5*8 ag5t|5*8 peacecodotnet|5*8 Rieekan|20*8 nixFourtyFive|5*8 Ramnarayan|5*8
06 ag5t|5*8 Ramnarayan|5*8 TomThumbKP|40*8 rabFiftyFour|5*8 MikeLacey|10*8 Valerie|5*8 rharsh|90*8 Rieekan|20*8
07 TheGenius|5*8 rharsh|90*8 nixFourtyFive|5*8 nawlej|60*8 parkers|30*8 hermes|5*8 mikevh|50*8 rabFiftyFour|5*8
08 dchoulette|70*8 nixFourtyFive|5*8 ag5t|5*8 Ramnarayan|5*8 TheGenius|5*8 nawlej|60*8 duncdude|80*8 pwils|5*8
09 duncdude|80*9 pwils|5*9 parkers|30*9 ag5t|5*9 Rieekan|20*9 Ramnarayan|5*9 nixFourtyFive|5*9 timgerr|5*9 dchoulette|70*9
10 Valerie|5*9 TomThumbKP|40*9 timgerr|5*9 parkers|30*9 Ramnarayan|5*9 nawlej|60*9 mikevh|50*9 MikeLacey|10*9 nixFourtyFive|5*9
11 rabFiftyFour|5*9 Ramnarayan|5*9 parkers|30*9 TheGenius|5*9 Rieekan|20*9 rharsh|90*9 hermes|5*9 timgerr|5*9 nawlej|60*9
12 Valerie|5*9 parkers|30*9 TomThumbKP|40*9 hermes|5*9 Rieekan|20*9 MikeLacey|10*9 pwils|5*9 TheGenius|5*9 dchoulette|70*9
13 pwils|5*7 MikeLacey|10*7 nixFourtyFive|5*7 dchoulette|70*7 ag5t|5*7 Rieekan|20*7 TomThumbKP|40*7
--- attempt 1 => completed --- [red]score 21185[/red] ---
00 pwils|5*7 TomThumbKP|40*7 peacecodotnet|5*7 rharsh|90*7 parkers|30*7 nixFourtyFive|5*7 timgerr|5*7
01 MikeLacey|10*7 dchoulette|70*7 nawlej|60*7 ag5t|5*7 hermes|5*7 timgerr|5*7 Valerie|5*7
02 TomThumbKP|40*7 duncdude|80*7 dchoulette|70*7 hermes|5*7 parkers|30*7 MikeLacey|10*7 nawlej|60*7
03 TheGenius|5*7 Valerie|5*7 MikeLacey|10*7 peacecodotnet|5*7 nawlej|60*7 hermes|5*7 rabFiftyFour|5*7
04 dchoulette|70*7 rharsh|90*7 TomThumbKP|40*7 Valerie|5*7 duncdude|80*7 nixFourtyFive|5*7 rabFiftyFour|5*7
05 rharsh|90*8 rabFiftyFour|5*8 MikeLacey|10*8 peacecodotnet|5*8 mikevh|50*8 nixFourtyFive|5*8 nawlej|60*8 Valerie|5*8
06 ag5t|5*8 hermes|5*8 TheGenius|5*8 parkers|30*8 timgerr|5*8 nawlej|60*8 pwils|5*8 TomThumbKP|40*8
07 parkers|30*8 timgerr|5*8 Valerie|5*8 ag5t|5*8 Ramnarayan|5*8 pwils|5*8 dchoulette|70*8 nawlej|60*8
08 duncdude|80*8 Valerie|5*8 parkers|30*8 hermes|5*8 nawlej|60*8 TheGenius|5*8 ag5t|5*8 Rieekan|20*8
09 peacecodotnet|5*9 Ramnarayan|5*9 parkers|30*9 nixFourtyFive|5*9 dchoulette|70*9 rabFiftyFour|5*9 nawlej|60*9 rharsh|90*9 TomThumbKP|40*9
10 nixFourtyFive|5*9 TheGenius|5*9 nawlej|60*9 duncdude|80*9 rharsh|90*9 Rieekan|20*9 TomThumbKP|40*9 rabFiftyFour|5*9 dchoulette|70*9
11 dchoulette|70*9 hermes|5*9 pwils|5*9 parkers|30*9 rabFiftyFour|5*9 Rieekan|20*9 TheGenius|5*9 mikevh|50*9 Ramnarayan|5*9
12 mikevh|50*9 peacecodotnet|5*9 TomThumbKP|40*9 ag5t|5*9 pwils|5*9 hermes|5*9 Ramnarayan|5*9 rabFiftyFour|5*9 parkers|30*9
13 rharsh|90*7 hermes|5*7 nawlej|60*7 parkers|30*7 timgerr|5*7 dchoulette|70*7 Valerie|5*7
--- attempt 2 => completed --- [red]score 24540[/red] ---
00 mikevh|50*7 nawlej|60*7 Ramnarayan|5*7 Rieekan|20*7 Valerie|5*7 ag5t|5*7 rabFiftyFour|5*7
01 TheGenius|5*7 duncdude|80*7 pwils|5*7 rabFiftyFour|5*7 Valerie|5*7 nawlej|60*7 rharsh|90*7
02 TomThumbKP|40*7 rabFiftyFour|5*7 mikevh|50*7 TheGenius|5*7 nawlej|60*7 pwils|5*7 parkers|30*7
03 mikevh|50*7 TomThumbKP|40*7 Ramnarayan|5*7 nawlej|60*7 nixFourtyFive|5*7 Valerie|5*7 TheGenius|5*7
04 peacecodotnet|5*7 rharsh|90*7 pwils|5*7 Valerie|5*7 TomThumbKP|40*7 timgerr|5*7 MikeLacey|10*7
05 TomThumbKP|40*8 Rieekan|20*8 MikeLacey|10*8 hermes|5*8 dchoulette|70*8 timgerr|5*8 TheGenius|5*8 mikevh|50*8
06 Rieekan|20*8 nawlej|60*8 peacecodotnet|5*8 rabFiftyFour|5*8 parkers|30*8 rharsh|90*8 nixFourtyFive|5*8 timgerr|5*8
07 ag5t|5*8 TomThumbKP|40*8 parkers|30*8 dchoulette|70*8 mikevh|50*8 Valerie|5*8 timgerr|5*8 peacecodotnet|5*8
08 parkers|30*8 dchoulette|70*8 Ramnarayan|5*8 peacecodotnet|5*8 pwils|5*8 nawlej|60*8 TomThumbKP|40*8 MikeLacey|10*8
09 peacecodotnet|5*9 nawlej|60*9 Rieekan|20*9 mikevh|50*9 MikeLacey|10*9 rharsh|90*9 TheGenius|5*9 duncdude|80*9 nixFourtyFive|5*9
10 peacecodotnet|5*9 TheGenius|5*9 timgerr|5*9 TomThumbKP|40*9 nixFourtyFive|5*9 hermes|5*9 nawlej|60*9 rharsh|90*9 dchoulette|70*9
11 duncdude|80*9 rabFiftyFour|5*9 mikevh|50*9 TheGenius|5*9 parkers|30*9 pwils|5*9 timgerr|5*9 ag5t|5*9 Rieekan|20*9
12 parkers|30*9 pwils|5*9 duncdude|80*9 rabFiftyFour|5*9 dchoulette|70*9 TheGenius|5*9 Ramnarayan|5*9 TomThumbKP|40*9 nawlej|60*9
13 MikeLacey|10*7 pwils|5*7 nawlej|60*7 nixFourtyFive|5*7 rabFiftyFour|5*7 mikevh|50*7 timgerr|5*7
--- attempt 3 => completed --- [red]score 24370[/red] ---[/tt]
As you can see the script loops through the shifts - from 0..13 in this case (14 shifts in total - Monday A.M. through to Sunday P.M.)
It then enters another loop - the number of staff required to cover the shift - and takes people from the staff list until the quota ... and then on to the next shift
This is all scored:-
staff member's competency x shift quota - and added up to give a total score for the rota
In theory, after hundreds of thousands of attempts, the highest score should be a very decent rota
But... My method is using random values. This essentially means that someone might never appear on the rota. Unlikely but possible.
Is there a way that each cell could be revolved like a car mileometer? This would mean that EVERY permutation would be covered.
Finally, bear in mind that someone cannot possibly work if they have a definite day off - but could (if necessary) if they have a requested day off
Other things to bear in mind are that it would be nice if no one was doing too many 'double' shifts - for example.
Really this is just common sense. At the end of the day the best rota is the one that evenly shares out the shifts among the members of staff,
puts the strongest members of staff on the more difficult shifts, and takes into account the rules
I know this is a fair bit of information but I can get quite close to a model within a few lines of code - and i'm a muppet!
I'd really appreciate some help on this - it is quite an interesting problem!
My brain is on fire now - if i've made an glaring errors in this post please let me know
Kind Regards
Duncan