Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Test 1 - orig: 7.4 new: 8.5 (116.1%) samu: 10.8 (146.5%) - 0 stations
- Test 2 - orig: 21.1 new: 20.2 (95.9%) samu: 22.3 (105.7%) - 1 station 0 rating
- Test 3 - orig: 19.9 new: 24.7 (123.7%) samu: 30.5 (152.8%) - 1 station
- Test 4 - orig: 32.4 new: 77.7 (239.5%) samu: 180.3 (555.9%) - 2 stations one company
- Test 5 - orig: 33.2 new: 74.0 (222.8%) samu: 178.5 (537.6%) - 2 stations 2 companies
- Test 6 - orig: 48.6 new: 130.0 (267.8%) samu: 317.3 (653.5%) - 3 stations 2 companies
- Test 7 - orig: 47.8 new: 136.1 (285.0%) samu: 304.9 (638.5%) - 3 stations 1 company
- Test 8 - orig: 153.3 new: 458.8 (299.3%) samu: 831.3 (542.3%) - 10 stations 10 companies
- Test 9 - orig: 144.0 new: 478.2 (332.2%) samu: 842.0 (584.8%) - 10 stations 1 company
- Test 10 - orig: 145.8 new: 293.0 (201.0%) samu: 351.8 (241.2%) - 10 stations but only 3 valid
- uint MoveGoodsToStationSamu(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
- {
- /* Return if nothing to do. Also the rounding below fails for 0. */
- if (all_stations->size() == 0) return 0;
- if (amount == 0) return 0;
- Station *first_station = nullptr;
- typedef std::pair<Station *, uint> StationInfo;
- std::vector<StationInfo> used_stations;
- for (Station *st : *all_stations) {
- if (!CanMoveGoodsToStation(st, type)) continue;
- /* Avoid allocating a vector if there is only one station to significantly
- * improve performance in this common case. */
- if (first_station == nullptr) {
- first_station = st;
- continue;
- }
- if (used_stations.size() == 0) {
- used_stations.reserve(2);
- used_stations.emplace_back(std::make_pair(first_station, 0));
- }
- used_stations.emplace_back(std::make_pair(st, 0));
- }
- /* no stations around at all? */
- if (first_station == nullptr) return 0;
- if (used_stations.size() == 0) {
- /* only one station around */
- amount *= (first_station->goods[type].rating + 1);
- return UpdateStationWaiting(first_station, type, amount, source_type, source_id);
- }
- uint company_best[OWNER_NONE + 1] = {}; // best rating for each company, including OWNER_NONE
- uint company_sum[OWNER_NONE + 1] = {}; // sum of ratings for each company
- uint best_rating = 0;
- uint best_sum = 0; // sum of best ratings for each company
- for (auto &p : used_stations) {
- auto owner = p.first->owner;
- auto rating = p.first->goods[type].rating;
- if (rating > company_best[owner]) {
- best_sum += rating - company_best[owner]; // it's usually faster than iterating companies later
- company_best[owner] = rating;
- if (rating > best_rating) best_rating = rating;
- }
- company_sum[owner] += rating;
- }
- /* From now we'll calculate with fractional cargo amounts.
- * First determine how much cargo we really have. */
- amount *= best_rating + 1;
- uint moving = 0;
- for (auto &p : used_stations) {
- uint st_owner = p.first->owner;
- /* Multiply the amount by (company best / sum of best for each company) to get cargo allocated to a company
- * and by (station rating / sum of ratings in a company) to get the result for a single station. */
- p.second = amount * company_best[st_owner] * p.first->goods[type].rating / best_sum / company_sum[st_owner];
- moving += p.second;
- }
- /* If there is some cargo left due to rounding issues distribute it among the best rated stations. */
- if (amount > moving) {
- std::sort(used_stations.begin(), used_stations.end(), [type] (const StationInfo &a, const StationInfo &b) {
- return b.first->goods[type].rating < a.first->goods[type].rating;
- });
- assert(amount - moving <= used_stations.size());
- for (uint i = 0; i < amount - moving; i++) {
- used_stations[i].second++;
- }
- }
- uint moved = 0;
- for (auto &p : used_stations) {
- moved += UpdateStationWaiting(p.first, type, p.second, source_type, source_id);
- }
- return moved;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement