Loading

Revision differences

Old revision #pfsmdufv4New revision #pnufelyg1
  1static int CDECL StationRatingSorter(const Station * const *a, const Station * const *b)  
  2{  
  3//    GSortT(used_stations->Begin(), used_stations.Lenght(), );  
  4    const Station *sta = *a;  
  5    const Station *stb = *b;  
  6    return stb->goods[0].rating - sta->goods[0].rating;  
  7}  
  8  
1uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)  9uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)  
2{  10{  
3    /* Return if nothing to do. Also the rounding below fails for 0. */  11    /* Return if nothing to do. Also the rounding below fails for 0. */  
  
6    Station *st1 = NULL;   // Station with best rating  14    Station *st1 = NULL;   // Station with best rating  
7    Station *st2 = NULL;   // Second best station  15    Station *st2 = NULL;   // Second best station  
8    Station *st3 = NULL;   // Third best station  16    Station *st3 = NULL;   // Third best station  
  17    Station *st4 = NULL;   // Fourth best station  
  18    Station *st5 = NULL;   // Fifth best station  
  19    Station *st6 = NULL;   // Sixth best station  
9    uint best_rating1 = 0; // rating of st1  20    uint best_rating1 = 0; // rating of st1  
10    uint best_rating2 = 0; // rating of st2  21    uint best_rating2 = 0; // rating of st2  
11    uint best_rating3 = 0; // rating of st3  22    uint best_rating3 = 0; // rating of st3  
  23    uint best_rating4 = 0; // rating of st4  
  24    uint best_rating5 = 0; // rating of st5  
  25    uint best_rating6 = 0; // rating of st6  
  26  
  27    StationList used_stations;  
12  28  
13    for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {  29    for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) {  
14        Station *st = *st_iter;  30        Station *st = *st_iter;  
  
26            if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop  42            if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop  
27        }  43        }  
28  44  
29        /* This station can be used, add it to st1/st2/st3 */  45        /* This station can be used, add it to st1/st2/st3/st4/st5/st6 */
   46        used_stations.Include(st);
   47
30        if (st1 == NULL || st->goods[type].rating >= best_rating1) {  48        if (st1 == NULL || st->goods[type].rating >= best_rating1) {  
31            st3 = st2;  31            st6 = st5; best_rating6 = best_rating5;
32            best_rating3 = best_rating2;  32            st5 = st4; best_rating5 = best_rating4;
33            st2 = st1;  33            st4 = st3; best_rating4 = best_rating3;
34            best_rating2 = best_rating1;  34            st3 = st2; best_rating3 = best_rating2;
35            st1 = st;  35            st2 = st1; best_rating2 = best_rating1;
36            best_rating1 = st->goods[type].rating;  36            st1 = st; best_rating1 = st->goods[type].rating;
37        } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {  55        } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {  
38            st3 = st2;  56            st6 = st5; best_rating6 = best_rating5;
39            best_rating3 = best_rating2;  57            st5 = st4; best_rating5 = best_rating4;
40            st2 = st;  58            st4 = st3; best_rating4 = best_rating3;
41            best_rating2 = st->goods[type].rating;  59            st3 = st2; best_rating3 = best_rating2;
   60            st2 = st; best_rating2 = st->goods[type].rating;
42        } else if (st3 == NULL || st->goods[type].rating >= best_rating3) {  61        } else if (st3 == NULL || st->goods[type].rating >= best_rating3) {  
43            st3 = st;  62            st6 = st5; best_rating6 = best_rating5;
44            best_rating3 = st->goods[type].rating;  63            st5 = st4; best_rating5 = best_rating4;
   64            st4 = st3; best_rating4 = best_rating3;
   65            st3 = st; best_rating3 = st->goods[type].rating;
   66        } else if (st4 == NULL || st->goods[type].rating >= best_rating4) {
   67            st6 = st5; best_rating6 = best_rating5;
   68            st5 = st4; best_rating5 = best_rating4;
   69            st4 = st; best_rating4 = st->goods[type].rating;
   70        } else if (st5 == NULL || st->goods[type].rating >= best_rating5) {
   71            st6 = st5; best_rating6 = best_rating5;
   72            st5 = st; best_rating5 = st->goods[type].rating;
   73        } else if (st6 == NULL || st->goods[type].rating >= best_rating6) {
   74            st6 = st; best_rating6 = st->goods[type].rating;
45        }  75        }  
46    }  76    }  
47  77  
  78    uint no_stations = used_stations.Length();  
  79  
  80    GSortT(used_stations.Begin(), used_stations.Length(), &StationRatingSorter);  
  81     
  82    if (no_stations > 1) {  
  83        Station *st1 = &used_stations.Begin();  
  84        Station *st2 = &st1++;  
  85        uint offset = 0;  
  86  
  87        while (no_stations > 1) {  
  88            const int diff = st1->goods[type].rating - st2->goods[type].rating;  
  89            if (diff <= 0) {  
  90                if (offset != 0) {  
  91                    st1 += offset;  
  92                    st2 += offset;  
  93                    offset = 0;  
  94                    continue;  
  95                }  
  96  
  97                st1++;  
  98                st2++;  
  99                no_stations--;  
  100            } else {  
  101                Swap(*st1, *st2);  
  102  
  103                if (st1 == *used_stations.Begin()) continue;  
  104  
  105                st1--;  
  106                st2--;  
  107                offset++;  
  108                }  
  109        }  
  110//        for (Station **st_iter = used_stations.Begin(); st_iter != used_stations.End(); ++st_iter) {  
  111//            Station *st1 = *st_iter;  
  112//            Station *st2 = *st_iter + 1;  
  113//  
  114//            if (st1->goods[type].rating >= st2->goods[type].rating) {  
  115//                st2 = st1;  
  116//            }  
  117//  
  118//        }  
  119    }  
  120     
48    /* no stations around at all? */  121    /* no stations around at all? */  
49    if (st1 == NULL) return 0;  122    if (st1 == NULL) return 0;  
50  123  
  
78        return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);  151        return moved + UpdateStationWaiting(st2, type, worst_cargo, source_type, source_id);  
79    }  152    }  
80  153  
81    /* three stations around, the best three (highest rating) are in st1, st2 and st3 */  154    if (st4 == NULL) {
   155        /* three stations around, the best three (highest rating) are in st1, st2 and st3 */
   156        assert(st1 != NULL);
   157        assert(st2 != NULL);
   158        assert(st3 != NULL);
   159        assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0);
   160
   161        /* Then determine the amount the worst stations get. We do it this way as the
   162         * best should get a bonus, which in this case is the rounding difference from
   163         * this calculation. In reality that will mean the bonus will be pretty low.
   164         * Nevertheless, the best station should always get the most cargo regardless
   165         * of rounding issues. */
   166        uint cargo_st3 = amount * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
   167        assert(cargo_st3 <= (amount - cargo_st3));
   168
   169        uint remaining = amount - cargo_st3;
   170        uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
   171        assert(cargo_st2 <= (remaining - cargo_st2));
   172
   173        uint cargo_st1 = remaining - cargo_st2;
   174        assert(amount == cargo_st1 + cargo_st2 + cargo_st3);
   175
   176        /* And then send the cargo to the stations! */
   177        uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
   178        moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
   179        return moved + UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
   180    }
   181
   182    if (st5 == NULL) {
   183        /* Four stations around, the best four (highest rating) are in st1, st2, st3 and st4 */
   184        assert(st1 != NULL);
   185        assert(st2 != NULL);
   186        assert(st3 != NULL);
   187        assert(st4 != NULL);
   188        assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0);
   189
   190        /* Then determine the amount the worst stations get. We do it this way as the
   191         * best should get a bonus, which in this case is the rounding difference from
   192         * this calculation. In reality that will mean the bonus will be pretty low.
   193         * Nevertheless, the best station should always get the most cargo regardless
   194         * of rounding issues. */
   195        uint cargo_st4 = amount * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
   196        assert(cargo_st4 <= (amount - cargo_st4));
   197
   198        uint remaining = amount - cargo_st4;
   199        uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
   200        assert(cargo_st3 <= (remaining - cargo_st3));
   201
   202        remaining -= cargo_st3;
   203        uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
   204        assert(cargo_st2 <= (remaining - cargo_st2));
   205
   206        uint cargo_st1 = remaining - cargo_st2;
   207        assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4);
   208
   209        /* And then send the cargo to the stations! */
   210        uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
   211        moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
   212        moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
   213        return moved + UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
   214    }
   215
   216    if (st6 == NULL) {
   217        /* Five stations around, the best five (highest rating) are in st1, st2, st3, st4 and st5 */
   218        assert(st1 != NULL);
   219        assert(st2 != NULL);
   220        assert(st3 != NULL);
   221        assert(st4 != NULL);
   222        assert(st5 != NULL);
   223        assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0 || best_rating5 != 0);
   224
   225        /* Then determine the amount the worst stations get. We do it this way as the
   226         * best should get a bonus, which in this case is the rounding difference from
   227         * this calculation. In reality that will mean the bonus will be pretty low.
   228         * Nevertheless, the best station should always get the most cargo regardless
   229         * of rounding issues. */
   230        uint cargo_st5 = amount * best_rating5 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5);
   231        assert(cargo_st5 <= (amount - cargo_st5));
   232
   233        uint remaining = amount - cargo_st5;
   234        uint cargo_st4 = remaining * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
   235        assert(cargo_st4 <= (remaining - cargo_st4));
   236
   237        remaining -= cargo_st4;
   238        uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
   239        assert(cargo_st3 <= (remaining - cargo_st3));
   240
   241        remaining -= cargo_st3;
   242        uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
   243        assert(cargo_st2 <= (remaining - cargo_st2));
   244
   245        uint cargo_st1 = remaining - cargo_st2;
   246        assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4 + cargo_st5);
   247
   248        /* And then send the cargo to the stations! */
   249        uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
   250        moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
   251        moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
   252        moved += UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
   253        return moved + UpdateStationWaiting(st5, type, cargo_st5, source_type, source_id);
   254    }
   255
   256    /* Six stations around, the best six (highest rating) are in st1, st2, st3, st4, st5 and st6 */
82    assert(st1 != NULL);  257    assert(st1 != NULL);  
83    assert(st2 != NULL);  258    assert(st2 != NULL);  
84    assert(st3 != NULL);  259    assert(st3 != NULL);  
85    assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 !=0);  260    assert(st4 != NULL);
86  261    assert(st5 != NULL);
87    /* Then determine the amount the worst station gets. We do it this way as the  262    assert(st6 != NULL);
   263    assert(best_rating1 != 0 || best_rating2 != 0 || best_rating3 != 0 || best_rating4 != 0 || best_rating5 != 0 || best_rating6 != 0);
   264
   265    /* Then determine the amount the worst stations get. We do it this way as the
88     * best should get a bonus, which in this case is the rounding difference from  266     * best should get a bonus, which in this case is the rounding difference from  
89     * this calculation. In reality that will mean the bonus will be pretty low.  267     * this calculation. In reality that will mean the bonus will be pretty low.  
90     * Nevertheless, the best station should always get the most cargo regardless  268     * Nevertheless, the best station should always get the most cargo regardless  
91     * of rounding issues. */  269     * of rounding issues. */  
92    uint worst_cargo_st3 = amount * best_rating3 / (best_rating1 + best_rating2 + best_rating3);  270    uint cargo_st6 = amount * best_rating6 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5 + best_rating6);
93    assert(worst_cargo_st3 <= (amount - worst_cargo_st3));  271    assert(cargo_st6 <= (amount - cargo_st6));
94  272
95    uint remaining_amount = amount - worst_cargo_st3;  273    uint remaining = amount - cargo_st6;
96    uint worst_cargo_st2 = remaining_amount * best_rating2 / (best_rating1 + best_rating2);  274    uint cargo_st5 = remaining * best_rating5 / (best_rating1 + best_rating2 + best_rating3 + best_rating4 + best_rating5);
97    assert(worst_cargo_st2 <= (remaining_amount - worst_cargo_st2));  275    assert(cargo_st5 <= (remaining - cargo_st5));
   276
   277    remaining -= cargo_st5;
   278    uint cargo_st4 = remaining * best_rating4 / (best_rating1 + best_rating2 + best_rating3 + best_rating4);
   279    assert(cargo_st4 <= (remaining - cargo_st4));
   280
   281    remaining -= cargo_st4;
   282    uint cargo_st3 = remaining * best_rating3 / (best_rating1 + best_rating2 + best_rating3);
   283    assert(cargo_st3 <= (remaining - cargo_st3));
   284
   285    remaining -= cargo_st3;
   286    uint cargo_st2 = remaining * best_rating2 / (best_rating1 + best_rating2);
   287    assert(cargo_st2 <= (remaining - cargo_st2));
   288
   289    uint cargo_st1 = remaining - cargo_st2;
   290    assert(amount == cargo_st1 + cargo_st2 + cargo_st3 + cargo_st4 + cargo_st5 + cargo_st6);
98  291  
99    /* And then send the cargo to the stations! */  292    /* And then send the cargo to the stations! */  
100    uint moved = UpdateStationWaiting(st1, type, remaining_amount - worst_cargo_st2, source_type, source_id);  293    uint moved = UpdateStationWaiting(st1, type, cargo_st1, source_type, source_id);
101    /* HALP - I GOT 3 UpdateStationWaitings now! */  294    moved += UpdateStationWaiting(st2, type, cargo_st2, source_type, source_id);
102    moved += UpdateStationWaiting(st2, type, worst_cargo_st2, source_type, source_id);  295    moved += UpdateStationWaiting(st3, type, cargo_st3, source_type, source_id);
103    return moved + UpdateStationWaiting(st3, type, worst_cargo_st3, source_type, source_id);  296    moved += UpdateStationWaiting(st4, type, cargo_st4, source_type, source_id);
   297    moved += UpdateStationWaiting(st5, type, cargo_st5, source_type, source_id);
   298    return moved + UpdateStationWaiting(st6, type, cargo_st6, source_type, source_id);
104} 299}