diff --git a/OngekiScoreLog/app/AggregateOverdamage.php b/OngekiScoreLog/app/AggregateOverdamage.php new file mode 100644 index 00000000..b3a59910 --- /dev/null +++ b/OngekiScoreLog/app/AggregateOverdamage.php @@ -0,0 +1,61 @@ +basic_level !== null){ + foreach ($normalDifficulties as $difficulty) { + \App\AggregateOverdamage::record($music->id, $difficulty); + } + } + + if($music->lunatic_level !== null){ + \App\AggregateOverdamage::record($music->id, $lunaticDifficulty); + } + } + + \App\Facades\Slack::Debug("Max Over Damageの集計を行いました。"); + } + + public static function record($song_id, $difficulty){ + $max = AggregateOverdamage::calculation($song_id, $difficulty); + + $key = $song_id . "_" . $difficulty; + AggregateOverdamage::updateOrCreate( + ['id' => $key], + ['song_id' => $song_id, 'difficulty' => $difficulty, 'max' => $max] + ); + } + + private static function calculation($song_id, $difficulty){ + $sql = DB::table('score_datas') + ->select('song_id', 'difficulty', DB::raw('MAX(over_damage_high_score) as max_over_damage_high_score')) + ->where('song_id', $song_id) + ->where('difficulty', $difficulty) + ->groupBy('song_id', 'difficulty') + ; + try { + return $sql->get()[0]->max_over_damage_high_score; + } catch (\Throwable $th) { + return 0; + } + } +} diff --git a/OngekiScoreLog/app/Console/Kernel.php b/OngekiScoreLog/app/Console/Kernel.php index 1f18e1ad..48d3f587 100644 --- a/OngekiScoreLog/app/Console/Kernel.php +++ b/OngekiScoreLog/app/Console/Kernel.php @@ -30,7 +30,12 @@ protected function schedule(Schedule $schedule) $schedule->call(function () { \App\UserInformation::ResetAllUserPaymentState(); \App\Facades\Slack::Info(" すべてのユーザーの課金情報をリセットしました。"); - })->monthlyOn(1, '4:00'); + })->monthlyOn(1, '7:00'); + + // Max OverDamageの集計 + $schedule->call(function () { + \App\AggregateOverdamage::execute(); + })->dailyAt('4:30'); } /** diff --git a/OngekiScoreLog/app/Http/Controllers/AdminController.php b/OngekiScoreLog/app/Http/Controllers/AdminController.php index 5f718b7e..c9b095a5 100644 --- a/OngekiScoreLog/app/Http/Controllers/AdminController.php +++ b/OngekiScoreLog/app/Http/Controllers/AdminController.php @@ -69,6 +69,11 @@ public function GetConfig(){ return view('admin/config', compact(['result'])); } + public function GetAggregate(){ + $result = \App\AggregateOverdamage::all(); + return view('admin/aggregate', compact(['result'])); + } + /** * '/config'にgetリクエストがあったときに呼び出されます。 * パラメータに合致する処理を行い、'/'にリダイレクトします。 @@ -124,4 +129,10 @@ public function GetApply($type, $action = null){ return redirect('/admin?message=' . $message); } + + public function GetGenerateOverDamage(){ + ini_set("max_execution_time", 0); + \App\AggregateOverdamage::execute(); + return redirect('/admin?message=' . "Generate Over Damage: max. 実行しました!"); + } } diff --git a/OngekiScoreLog/app/Http/Controllers/ViewUserController.php b/OngekiScoreLog/app/Http/Controllers/ViewUserController.php index 0f8bf200..d9d2e68b 100644 --- a/OngekiScoreLog/app/Http/Controllers/ViewUserController.php +++ b/OngekiScoreLog/app/Http/Controllers/ViewUserController.php @@ -8,7 +8,10 @@ use App\User; use App\UserStatus; use App\ScoreData; +use App\AggregateOverdamage; use App\Facades\OngekiUtility; +use DateTime; + use function GuzzleHttp\json_encode; class ViewUserController extends Controller @@ -386,13 +389,17 @@ public function getOverDamegePage($id){ } // トップランカーのスコアを取得してkey: song_id, difficulty, value: over_damage_high_score の配列を作る + $lastUpdate = (new DateTime())->setTimestamp(0); $topRankerScore = []; { - $temp = (new ScoreData)->getTopRankerScore()->getValue(); + $temp = AggregateOverdamage::all(); foreach ($temp as $value) { $key = $value->song_id . "_" . $value->difficulty; - if(!isset($topRankerScore[$key])){ - $topRankerScore[$key] = $value->max_over_damage_high_score; + $topRankerScore[$key] = $value->max; + + // 最終更新日時を取得 + if($lastUpdate < $value->updated_at){ + $lastUpdate = $value->updated_at; } } } @@ -422,6 +429,6 @@ public function getOverDamegePage($id){ } } - return view('user_overdamage', compact('id', 'status', 'scoreDatas', 'topRankerScore')); + return view('user_overdamage', compact('id', 'status', 'lastUpdate', 'scoreDatas', 'topRankerScore')); } } diff --git a/OngekiScoreLog/app/ScoreData.php b/OngekiScoreLog/app/ScoreData.php index 8b239c4b..96779ab4 100644 --- a/OngekiScoreLog/app/ScoreData.php +++ b/OngekiScoreLog/app/ScoreData.php @@ -193,19 +193,6 @@ function getRecentUserScore($id){ return $this; } - function getTopRankerScore(){ - $sql = DB::table($this->table) - ->select('song_id', 'difficulty', - DB::raw('MAX(over_damage_high_score) as max_over_damage_high_score'), - DB::raw('MAX(battle_high_score) as max_battle_high_score'), - DB::raw('MAX(technical_high_score) as max_technical_high_score'),) - ->from($this->table) - ->groupBy('song_id', 'difficulty') - ; - $this->value = $sql->get(); - return $this; - } - /** * 指定した世代のスコアデータを取得します。 * diff --git a/OngekiScoreLog/database/migrations/2024_04_15_181601_create_aggregate_overdamage.php b/OngekiScoreLog/database/migrations/2024_04_15_181601_create_aggregate_overdamage.php new file mode 100644 index 00000000..b2cd730a --- /dev/null +++ b/OngekiScoreLog/database/migrations/2024_04_15_181601_create_aggregate_overdamage.php @@ -0,0 +1,34 @@ +string('id')->primary(); + $table->integer('song_id')->unsigned(); + $table->integer("difficulty")->unsigned(); + $table->decimal("max", 6, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('aggregate_overdamage'); + } +} diff --git a/OngekiScoreLog/resources/views/admin/_submenu.blade.php b/OngekiScoreLog/resources/views/admin/_submenu.blade.php index 8fd8bda1..54f48259 100644 --- a/OngekiScoreLog/resources/views/admin/_submenu.blade.php +++ b/OngekiScoreLog/resources/views/admin/_submenu.blade.php @@ -10,4 +10,11 @@ @else
  • @endif -config
  • \ No newline at end of file +config + +@if (isset($active) && $active === 'aggregate') +
  • +@else +
  • +@endif +aggregate
  • diff --git a/OngekiScoreLog/resources/views/admin/aggregate.blade.php b/OngekiScoreLog/resources/views/admin/aggregate.blade.php new file mode 100644 index 00000000..1de84e15 --- /dev/null +++ b/OngekiScoreLog/resources/views/admin/aggregate.blade.php @@ -0,0 +1,33 @@ +@extends('layouts.app') + +@section('title', '管理ページ') +@section('hero_title', "管理ページ") +@section('hero_subtitle', "config") + +@section('submenu') + @include('admin/_submenu', ['active' => 'aggregate']) +@endsection + +@section('content') +
    +

    集計一覧

    + + + + + + + + + + @foreach ($result as $key => $value) + + + + + + @endforeach + +
    idmaxupdated_at
    {{$value->id}}{{$value->max}}{{$value->updated_at}}
    +
    +@endsection diff --git a/OngekiScoreLog/resources/views/admin/index.blade.php b/OngekiScoreLog/resources/views/admin/index.blade.php index 7605eea5..b80b4ddf 100644 --- a/OngekiScoreLog/resources/views/admin/index.blade.php +++ b/OngekiScoreLog/resources/views/admin/index.blade.php @@ -40,5 +40,12 @@

    +
    +

    統計データ生成

    +

    超絶重いので実行する時間とタイミングに注意!

    +

    Over Damage

    +

    + +

    @endsection diff --git a/OngekiScoreLog/resources/views/layouts/components/user/song_status_overdamage.blade.php b/OngekiScoreLog/resources/views/layouts/components/user/song_status_overdamage.blade.php index 93694b5d..6149f714 100644 --- a/OngekiScoreLog/resources/views/layouts/components/user/song_status_overdamage.blade.php +++ b/OngekiScoreLog/resources/views/layouts/components/user/song_status_overdamage.blade.php @@ -2,6 +2,7 @@

    登録されている全ユーザーのオーバーダメージのうち、一番高いものと比較することが出来ます。
    OD埋めなどにご活用ください。

    プレイしている楽曲内で、一番ODが高い難易度のみ表示されます。全難易度のODが0の曲は表示されません。なお削除楽曲等も表示されます。ご了承下さい。

    + 最終更新: {{$lastUpdate->format('Y-m-d H:i:s')}} (?%表示は未集計です)
    @@ -42,9 +43,15 @@ {{$s->title}}song_id . "/" . strtolower($s->difficulty_str))}}">{{$s->title}} {{$s->difficulty}}{{substr($s->difficulty_str, 0, 3)}} {{$s->over_damage_high_score . "%"}} - {{$topRankerScore[$s->song_id . "_" . $s->difficulty] . "%"}} - {{$s->over_damage_high_score - $topRankerScore[$s->song_id . "_" . $s->difficulty]}}% - {{($topRankerScore[$s->song_id . "_" . $s->difficulty] != 0) ? ($s->over_damage_high_score / $topRankerScore[$s->song_id . "_" . $s->difficulty]) * 100 : 100}}% + @if (array_key_exists($s->song_id . "_" . $s->difficulty, $topRankerScore)) + {{$topRankerScore[$s->song_id . "_" . $s->difficulty] . "%"}} + {{$s->over_damage_high_score - $topRankerScore[$s->song_id . "_" . $s->difficulty]}}% + {{($topRankerScore[$s->song_id . "_" . $s->difficulty] != 0) ? ($s->over_damage_high_score / $topRankerScore[$s->song_id . "_" . $s->difficulty]) * 100 : 100}}% + @else + ?% + ?% + ?% + @endif {{date('Y-m-d', strtotime($s->updated_at))}} @endforeach diff --git a/OngekiScoreLog/resources/views/user_overdamage.blade.php b/OngekiScoreLog/resources/views/user_overdamage.blade.php index a96e01c0..dbe1f2dd 100644 --- a/OngekiScoreLog/resources/views/user_overdamage.blade.php +++ b/OngekiScoreLog/resources/views/user_overdamage.blade.php @@ -3,6 +3,9 @@ @section('title', $status[0]->name) @section('hero_subtitle', $status[0]->trophy) @section('hero_title', $status[0]->name) +@section('additional_head') + +@endsection @section('additional_footer') @@ -63,7 +66,7 @@ {{-- @component('layouts/components/user/song_filter') @endcomponent --}} - @component('layouts/components/user/song_status_overdamage', ['score' => $scoreDatas, 'topRankerScore' => $topRankerScore, 'id' => $id]) + @component('layouts/components/user/song_status_overdamage', ['score' => $scoreDatas, 'topRankerScore' => $topRankerScore, 'id' => $id, 'lastUpdate' => $lastUpdate]) @endcomponent @endsection diff --git a/OngekiScoreLog/routes/web.php b/OngekiScoreLog/routes/web.php index 71d08cc5..73bf518d 100644 --- a/OngekiScoreLog/routes/web.php +++ b/OngekiScoreLog/routes/web.php @@ -20,7 +20,9 @@ Route::get('/user/{id}/trophy', 'ViewUserTrophyController@getIndex')->where(['id' => '\d+']); Route::get('/user/{id}/music/{music}/{difficulty}', 'ViewUserMusicController@getIndex')->where(['id' => '\d+', 'music' => '\d+', 'difficulty' => '\w+']); Route::get('/user/{id}/music/{music}', 'ViewUserMusicController@getRedirect')->where(['id' => '\d+', 'music' => '\d+']); -Route::get('/user/{id}/overdamage', 'ViewUserController@getOverDamegePage')->where(['id' => '\d+']); +Route::middleware('throttle:5,1')->group(function () { + Route::get('/user/{id}/overdamage', 'ViewUserController@getOverDamegePage')->where(['id' => '\d+']); +}); Route::get('/user/{id}/{mode?}', 'ViewUserController@getUserPage')->where(['id' => '\d+']); Route::middleware('throttle:3,1')->group(function () { @@ -57,7 +59,9 @@ Route::group(['middleware' => ['auth', 'can:admin']], function () { Route::get('/admin', 'AdminController@GetIndex'); Route::get('/admin/config', 'AdminController@GetConfig'); + Route::get('/admin/aggregate', 'AdminController@GetAggregate'); Route::get('/admin/apply/{type}/{action?}', 'AdminController@GetApply'); + Route::get('/admin/generate/over-damage', 'AdminController@GetGenerateOverDamage'); Route::get('/admin/log/{path}/{fileName}', 'SimpleViewController@getLogFile'); });