I need to sort a collection first by the field points
and then by company_fantasy
I tried some forms according to this post link that would be the same problem but did not succeed. I'm using Laravel 5.3
In this way I am sorting by points, but if two companies have the same score, I need them to sort by company_fantasy
:
if ($order === self::ORDER_POINTS) {
$collection = $collection->sortByDesc('points');
}
namespace App\Libella\Library;
use Cache;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Rentalhost\Libella\Company;
use Rentalhost\Libella\Score;
use Rentalhost\Libella\ScoreAssignment;
use Rentalhost\Libella\ScoreMedal;
class CompanyRanking
{
const ORDER_MEDALS = 'medals';
const ORDER_POINTS = 'points';
/**
* Relação de atribuições à empresa.
* @var ScoreAssignment[]|Collection
*/
public $assignments;
/**
* Número de medalhas de bronze.
* @var int
*/
public $bronzes = 0;
/**
* Empresa.
* @var Company
*/
public $company;
/**
* Número de medalhas de ouro.
* @var int
*/
public $golds = 0;
/**
* Relação de medalhas da empresa.
* @var ScoreMedal[]|Collection
*/
public $medals;
/**
* Pontuação.
* @var int
*/
public $points = 0;
/**
* Número de medalhas de prata.
* @var int
*/
public $silvers = 0;
/**
* CompanyRanking constructor.
* @param Company $company Empresa de referência.
*/
public function __construct(Company $company)
{
$this->company = $company;
$this->medals = collect();
$this->assignments = collect();
}
/**
* Retorna um rankeamento até uma data determinada (ou todas).
* @param Carbon|null $until Data limite para obter as informações (inclusiva).
* @param string|null $order Modo de organização.
* @return CompanyRanking[]|Collection
*/
static public function get($until = null, $order = null)
{
$order = $order ?? self::ORDER_POINTS;
$prefix = static::class;
if ($until instanceof Carbon) {
$prefix .= $until->toAtomString() . '.';
}
$scores = Score::pluck('id');
/** @var ScoreMedal[]|Collection $scoreMedals */
$scoreMedals = Cache::store('array')->rememberForever($prefix . '.scoreMedals', function () use ($scores, $until) {
/** @var ScoreMedal|Builder $scoresMedalsQuery */
$scoresMedalsQuery = ScoreMedal::query();
$scoresMedalsQuery->with('team.company');
$scoresMedalsQuery->whereIn('score_id', $scores);
// Aplica a data limite.
if ($until !== null) {
$scoresMedalsQuery->whereDate('created_at', '<=', $until);
}
return $scoresMedalsQuery->get();
});
/** @var ScoreAssignment[]|Collection $assignments */
$assignments = Cache::store('array')->rememberForever($prefix . '.assignments', function () use ($until) {
/** @var ScoreAssignment|Builder $assignmentsQuery */
$assignmentsQuery = ScoreAssignment::query();
$assignmentsQuery->with('company');
// Aplica a data limite.
if ($until !== null) {
$assignmentsQuery->whereDate('created_at', '<=', $until);
}
return $assignmentsQuery->get();
});
// Empresas.
/** @var Company[]|Collection $companies */
$companiesQuery = Company::query();
$companiesQuery->orderBy('company_fantasy');
$companies = $companiesQuery->get();
$collection = collect();
foreach ($companies as $company) {
$companyRanking = new static($company);
$companyRanking->medals = $scoreMedals->where('team.company_id', $company->id);
$companyRanking->assignments = $assignments->where('company_id', $company->id);
// Calcula as medalhas.
$companyRanking->golds += $companyRanking->medals->where('medal_ranking', '1')->count();
$companyRanking->silvers += $companyRanking->medals->where('medal_ranking', '2')->count();
$companyRanking->bronzes += $companyRanking->medals->where('medal_ranking', '3')->count();
// Calcula a pontuação.
$companyRanking->points +=
$companyRanking->medals->reduce(function ($carry, ScoreMedal $scoreMedal) {
return $carry + $scoreMedal->getPoints();
}, 0) +
$companyRanking->assignments->reduce(function ($carry, ScoreAssignment $scoreAssignment) {
return $carry + $scoreAssignment->assignment_points;
}, 0);
$scoreMedals = $scoreMedals->reject($companyRanking->medals);
$assignments = $assignments->reject($companyRanking->assignments);
$collection->put($company->id, $companyRanking);
}
if ($order === self::ORDER_POINTS) {
$collection = $collection->sortByDesc('points');
}
else if ($order === self::ORDER_MEDALS) {
$collection = $collection->sortByDesc(function (CompanyRanking $companyRanking) {
return $companyRanking->golds * 1e6 +
$companyRanking->silvers * 1e3 +
$companyRanking->bronzes;
})->sortBy('company.company_fantasy');
}
return $collection;
}
/**
* Retorna um número de referência para a quantidade de medalhas virtuais.
* @param int $number Número de medalhas reais.
* @return int
*/
static public function medalsVirtuals($number)
{
return min(floor(ceil(sqrt(8 * max(0, $number) + 1)) / 1.8), 7);
}
/**
* Soma o número de medalhas.
* @return int
*/
public function sumMedals()
{
return $this->golds +
$this->silvers +
$this->bronzes;
}
}