基于多个规则对对象进行排序

My school's choir performs singing Valentines every year on Valentine's Day. The choir goes around from class to class throughout the day singing to people who received Valentines from their friend or significant other.

We sell approximately 1000 singing Valentines each year. These need to be sorted based on a plethora of rules - for example:

  • No one class period can have a total of more that 150 Valentines. (There are five groups of singers, and we have found that it is logistically impossible for each group to deliver more than 30 Valentines per class period.)
  • Any Valentine recipient who has a class in their schedule during zero or seventh period must receive their Valentine during zero or seventh period.
  • The load of singing Valentines should preferably be spread evenly throughout the day where possible so that there aren't 150 valentines during third period and 20 during fourth period, for instance.
  • Each of the five groups of singers should have their deliveries located in the same relative area to minimize time wasted in transit.

The list goes on. Currently, all 1000 Valentines are being sorted by hand, which is ridiculously inefficient. I was thinking of making a PHP or JS script to automate the process. Here is how I envision it:

  1. When purchasing Valentines, students will fill out a Google Form with their name, the recipient's name, and the class period during which they prefer that the recipient receive his or her Valentine.

  2. The script will fetch data from the resulting spreadsheet row by row and create a Valentine object for each row.

  3. For each Valentine object, the script will look up the recipient's schedule and add his or her schedule as room numbers to the Valentine object in the form of object variables/attributes (i.e. $period1 = 312 means that the recipient's first period class is in room 312.)

    • This part may have to be done by hand in the Google spreadsheet before the script fetches its data, as I'm not sure that I will have access to the school database.
  4. Here's the part where I'm stuck. Once the script has a list of 1000 or so Valentine objects, each with their own $sender, $recp, $period0 through $period7, and $prefPeriod values, somehow the script will sort each object into the appropriate class period based on the rules above and the data in each object.

If PHP isn't the best language for the job, I'm open to suggestions. I initially chose PHP because it is the language I know best.

Any help on this would be much appreciated.

TL;DR: I need to sort objects into categories based on several rules that use data from those objects' properties.

Have a look at usort(). It allows you to sort using any user function. Inside that function, you can compare the objects however you want. In below example, I compare their properties: property1 and property2.

<?php
$obj1 = new \StdClass;
$obj2 = new \StdClass;
$obj3 = new \StdClass;
$obj1->property1 = '1';
$obj2->property1 = '2';
$obj3->property1 = '2';
$obj1->property2 = '1';
$obj2->property2 = '1';
$obj3->property2 = '2';
$objs = [$obj2, $obj1, $obj3]; //after sorting, it should be obj1, obj2, obj3

//first we sort by property1, then by property2
usort($objs, function($a, $b)
{
    $result = strcmp($a->property1, $b->property1);
    if ($result === 0)
        $result = strcmp($a->property2, $b->property2);
    return $result;
});

print_r($objs);

Result:

Array
(
    [0] => stdClass Object
        (
            [property1] => 1
            [property2] => 1
        )
    [1] => stdClass Object
        (
            [property1] => 2
            [property2] => 1
        )
    [2] => stdClass Object
        (
            [property1] => 2
            [property2] => 2
        )
)

Perfectly sorted!

Basically, your custom function should return 1, -1 or 0 if the objects are equal. strcmp is perfect for this, since it returns compatible values. To sort by multiple properties, we check if two objects have the same property1 by comparing the first result to 0. If they are the same, we compare property2. As you see, this can be extended further, to other properties, with ease.