TCVis/app/MatsuriHime/Election.php

226 lines
8.7 KiB
PHP

<?php
namespace App\MatsuriHime;
use Guzzle;
use Carbon\Carbon;
use DB;
use Cache;
use App\Rank;
class Election
{
public const nuke_threshold = 2500;
public static function getDramaNames() {
if(!Cache::has('drama_names')) {
$response = Guzzle::get("https://api.matsurihi.me/mltd/v1/election")->getBody()->getContents();
$dramas = json_decode($response);
$dramas = $dramas->dramas;
$drama_list = [];
foreach($dramas as $drama) {
$drama_roles = [];
foreach($drama->roles as $role) {
$drama_list[$role->name] = $drama->name;
}
}
Cache::forever('drama_names',$drama_list);
}
return Cache::get('drama_names');
}
public static function getRanking() {
$response = Guzzle::get("https://api.matsurihi.me/mltd/v1/election/current");
return json_decode($response->getBody()->getContents());
}
public static function createSnapshot() {
$rankings = Election::getRanking();
$hasSnapshot = true;
DB::beginTransaction();
foreach($rankings as $ladder) {
$existingSnapshot = Cache::get('snap_time_'.$ladder->name);
if(!isset($existingSnapshot) || $existingSnapshot->lt(Carbon::parse($ladder->summaryTime)) ) {
$hasSnapshot = false;
$idols = [];
foreach($ladder->data[0] as $data) {
$rank = new Rank();
$rank->role = $ladder->name;
$rank->character = $data->idol_name;
$idols[] = $data->idol_name;
$rank->score = $data->score;
$rank->summary_time = Carbon::parse($ladder->summaryTime);
$rank->save();
}
$remnant_idols = Rank::where('role',$ladder->name)->whereNotIn('character',$idols)->orderBy('summary_time','desc')->get()->groupBy('character');
foreach($remnant_idols as $remnant_char => $remnant) {
$rank = new Rank();
$rank->role = $ladder->name;
$rank->character = $remnant_char;
$rank->score = $remnant->first()->score;
$rank->summary_time = Carbon::parse($ladder->summaryTime);
$rank->save();
}
Cache::forever('snap_time_'.$ladder->name,Carbon::parse($ladder->summaryTime));
Cache::forever('snap_time',Carbon::parse($ladder->summaryTime));
} else {
}
}
DB::commit();
if(!$hasSnapshot) {
$snap_time = Cache::get('snap_time');
$end_date = $snap_time->toDateTimeString();
$start_date = $snap_time->subMinutes(24*60)->toDateTimeString();
Election::generateChartPointsDate($start_date,$end_date);
Election::incrementNukeData();
}
}
public static function generateChartPointsDate($start_date,$end_date) {
if(Cache::has('timepoints_'.$start_date.'-'.$end_date)) return $start_date.'-'.$end_date;
$ranks = Rank::where('summary_time','>=',$start_date)->where('summary_time','<=',$end_date)->orderBy('summary_time')->get();
$timepoints = $ranks->pluck('summary_time')->unique();
$ranks = $ranks->groupBy('role');
Cache::forever('timepoints_'.$start_date.'-'.$end_date,$timepoints);
$timelabels = [];
foreach($timepoints as $timepoint) {
$timelabels[] = $timepoint->toDateTimeString();
}
$timelabels = collect($timelabels);
Cache::forever('timelabels_'.$start_date.'-'.$end_date,$timelabels);
$timepoints_count = $timepoints->count();
$globalDataPoints = [];
foreach($ranks as $roleName => $roleRank) {
$dataPoints = [];
$ladder = $roleRank->groupBy('character')->sortByDesc(function($rank,$key) {
return $rank->last()->score;
});
foreach($ladder as $character => $rank) {
$standing = $rank->pluck('score')->take($timepoints_count)->values();
$standing = $standing->pad(-$timepoints_count,(int)0)->values();
$dataPoints[$character] = $standing;
if(!array_key_exists($character,$globalDataPoints)) $globalDataPoints[$character] = $standing->values();
else {
$scores = $standing->values();
\Log::error($globalDataPoints[$character]->count().' vs '.$standing->count().' the jury is '.$timepoints_count);
$globalDataPoints[$character]->transform(function($item,$index) use ($scores) {
return $item+$scores[$index];
});
}
}
$dataPoints = collect($dataPoints)->take(10);
Cache::forever('data_'.$roleName.'_'.$start_date.'-'.$end_date,$dataPoints);
}
$globalDataPoints = collect($globalDataPoints);
$globalDataPoints = $globalDataPoints->sortByDesc(function($item, $key) {
return $item->last();
});
$globalDataPoints = $globalDataPoints->take(10);
Cache::forever('data_global_'.$start_date.'-'.$end_date,$globalDataPoints);
return $start_date.'-'.$end_date;
}
public static function generateChartPointsNew() {
$ranks = Rank::orderBy('summary_time')->get();
$timepoints = $ranks->pluck('summary_time')->unique();
$ranks = $ranks->groupBy('role');
Cache::forever('timepoints',$timepoints);
$timelabels = [];
foreach($timepoints as $timepoint) {
$timelabels[] = $timepoint->toDateTimeString();
}
$timelabels = collect($timelabels);
Cache::forever('timelabels',$timelabels);
$timepoints_count = $timepoints->count();
$globalDataPoints = [];
foreach($ranks as $roleName => $roleRank) {
$dataPoints = [];
$ladder = $roleRank->groupBy('character')->sortByDesc(function($rank,$key) {
return $rank->last()->score;
});
foreach($ladder as $character => $rank) {
$standing = $rank->pluck('score');
$standing = $standing->pad(-$timepoints_count,(int)0);
$dataPoints[$character] = $standing;
if(!array_key_exists($character,$globalDataPoints)) $globalDataPoints[$character] = $standing->pluck('score');
else {
$scores = $standing->pluck('score');
$globalDataPoints[$character]->transform(function($item,$index) use ($scores) {
return $item+$scores[$index];
});
}
}
$dataPoints = collect($dataPoints)->take(10);
Cache::forever('data_'.$roleName,$dataPoints);
}
$globalDataPoints = collect($globalDataPoints);
$globalDataPoints = $globalDataPoints->sortByDesc(function($item, $key) {
return $item->last();
});
$globalDataPoints = $globalDataPoints->take(10);
Cache::forever('data_global',$globalDataPoints);
}
public static function incrementNukeData() {
$nukes = Cache::get('nukes');
$dramaNames = Election::getDramaNames();
$ranks = collect(Cache::get('drama_names'))->keys();
$firstPoint = Cache::get('snap_time');
foreach($ranks as $role) {
$ladder = Rank::where('role',$role)->orderBy('summary_time','desc')->get()->groupBy('character')->take(2);
foreach($ladder as $character => $points) {
$future_point = $points[0];
$point = $points[1] ?? null;
$future_point_score = $future_point->score;
$point_score = 0;
if($point) {
$point_score = $point->score;
if($future_point_score - $point_score >= Election::nuke_threshold) {
\Log::error($role.$character.$point->summary_time);
$nuke = [
'code' => $role.$character.$point->summary_time,
'drama' => $dramaNames[$role],
'role' => $role,
'character' => $character,
'nuke_time_start' => $point->summary_time,
'nuke_time_end' => $future_point->summary_time,
'nuke_pts' => $future_point_score - $point_score,
];
$nukes[] = $nuke;
}
}
}
}
$collect = collect($nukes)->sortBy('nuke_time_start')->reverse();
Cache::forever('nukes',$collect);
}
public static function generateNukeData() {
$dramaNames = Election::getDramaNames();
$nukes = [];
$ranks = Rank::orderBy('summary_time')->get()->groupBy('role');
$firstPoint = $ranks->first()->first()->summary_time;
foreach($ranks as $role => $ladder) {
$ladder = $ladder->groupBy('character');
foreach($ladder as $character => $points) {
$count = $points->count();
foreach($points as $index => $future_point) {
$point = null;
if(($index-1) >= 0) $point = $points[$index-1];
if(isset($future_point)) {
$future_point_score = $future_point->score;
$point_score = $point->score ?? 0;
if($future_point_score - $point_score >= Election::nuke_threshold && !$future_point->summary_time->eq($firstPoint)) {
\Log::error($role.$character.($point ? $point->summary_time : $future_point->summary_time->subMinutes(5)));
$nuke = [
'code' => $role.$character.$future_point->summary_time,
'role' => $role,
'drama' => $dramaNames[$role],
'character' => $character,
'nuke_time_start' => ($point ? $point->summary_time : $future_point->summary_time->subMinutes(5)),
'nuke_time_end' => $future_point->summary_time,
'nuke_pts' => $future_point_score - $point_score,
];
$nukes[] = $nuke;
}
}
}
}
}
Cache::forever('nukes',collect($nukes)->sortBy('nuke_time_start')->reverse());
}
}