Major update

This commit is contained in:
Damillora 2019-01-02 19:18:53 +00:00
parent 794b91088a
commit b4b06eacf8
10 changed files with 378 additions and 191 deletions

View File

@ -0,0 +1,44 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\MatsuriHime\Election;
class GenerateNuke extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tcvis:generatenuke';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create Nuke Data';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
Election::generateNukeData();
//
}
}

View File

@ -29,7 +29,6 @@ class Kernel extends ConsoleKernel
$schedule->call(function() {
\App\MatsuriHime\Election::createSnapshot();
})->everyMinute();
}
/**

View File

@ -16,23 +16,57 @@ class HomeController extends Controller
public function getIdolDB() {
return json_decode(Storage::get('idols.json'));
}
public function getIdolColor($idol) {
$idolColors = $this->getIdolColors();
return $idolColors[explode("\n",$idol)[0]];
}
public function getIdolColors(){
if(!Cache::get('idol_colors')) {
$colors = [];
$idolDB = collect($this->getIdolDB()->idols);
foreach($idolDB as $idol) {
$colors[$idol->name->kanji->value] = $idol->color;
}
// dd($colors);
return $colors;
Cache::forever('idol_colors',$colors);
}
// return $colors;
return Cache::get('idol_colors');
}
public function statistics(Request $request) {
$dataPoints = Rank::count();
return view('statistics',['data_points' => $dataPoints]);
}
public function nukes(Request $request) {
$nukes = Cache::get('nukes');
return view('nukes',["nukes" => $nukes]);
}
public function newChart($timelabels,$roleName,$request,$amount,$dramaNames,$colors,$enlarge = false) {
$chart = new RankChart;
$height = 400;
if($enlarge) $height = 1000;
$options = [
'axisOptions' => [
'xIsSeries' => true,
'xAxisMode' => 'tick'
],
'lineOptions' => [
'regionFill' => true,
],
'title' => $roleName.' ('.($roleName == 'global' ? 'Global' : $dramaNames[$roleName]).')',
'colors' => $colors,
'height' => $height,
];
$chart->options($options);
$chart->isNavigable(true);
$chart->labels($timelabels->toArray());
$chart->hideDots(true);
$api = url('/api/chart/'.$roleName."?date_since=".$request->date_since.'&since='.$request->since.'&take='.$request->take);
$chart->load($api);
return $chart;
}
public function home(Request $request) {
$minutes = $request->since ?? 60*24*90;
$idolColors = $this->getIdolColors();
$minutes = $request->since ?? 60*24;
$timepoints = Cache::get('timepoints');
$requested_date = $request->date_since;
if($requested_date) {
@ -45,51 +79,100 @@ class HomeController extends Controller
return $item->gte(Carbon::now()->addHours(9)->subMinutes($minutes+5));
});
$take = $timepoints->count();
$idolColors = $this->getIdolColors();
$dramaNames = Election::getDramaNames();
$ranks = Rank::all()->groupBy('role');
$ranks = collect($dramaNames)->keys();
$charts = [];
$timelabels = [];
foreach($timepoints as $timepoint) {
$timelabels[] = $timepoint->toDateTimeString();
}
$timelabels = collect($timelabels);
$timelabels = $timelabels->splice(count($timelabels) - $take);
$timelabels = Cache::get('timelabels');
$timelabels = $timelabels->take(-$take)->values();
if($request->take) $timelabels = $timelabels->take($request->take);
foreach($ranks as $roleName => $roleRank) {
$chartPoint = Cache::get('data_'.$roleName);
// dd($chartPoint);
if(!isset($chartPoint)) {
\App\MatsuriHime\Election::createSnapshot();
$chartPoint = Cache::get('data_'.$roleName);
}
$chart = new RankChart;
$chart->options([
'axisOptions' => [
'xIsSeries' => true,
'xAxisMode' => 'tick'
],
'lineOptions' => [
'regionFill' => true
],
'title' => $roleName.' ('.$dramaNames[$roleName].')'
]);
$chart->isNavigable(true);
$chart->labels($timelabels->toArray());
$chart->hideDots(true);
foreach($chartPoint as $idol => $dataPoints) {
$values = collect($dataPoints);
$values = $values->splice(count($values) - $take);
if($request->take) $values = $values->take($request->take);
$idol_color = $idolColors[$idol];
$chart->dataSet($idol,'line',$values->toArray())->color($idol_color);
foreach($ranks as $roleName) {
$chartPoint = null;
$chartPoint = collect(Cache::get('data_'.$roleName))->keys();
$colors = [];
foreach($chartPoint as $point) {
$colors[] = $this->getIdolColor($point);
}
$chart =$this->newChart($timelabels,$roleName,$request,$request->take,$dramaNames,$colors,$request->enlarge);
$chartData["drama"] = $dramaNames[$roleName];
$chartData["name"] = $roleName;
$chartData["chart"] = $chart;
$charts[] = $chartData;
}
return view('home', [ 'chart_groups' => collect($charts)->groupBy("drama"), 'since' => $request->since ]);
return view('home', [ 'chart_groups' => collect($charts)->groupBy("drama"), 'since' => $request->since, 'enlarge' => $request->enlarge , 'date_since' => $request->date_since, 'take' => $request->take]);
}
public function homeNew(Request $request) {
$idolColors = $this->getIdolColors();
$minutes = $request->since ?? 60*24;
$snap_time = Cache::get('snap_time');
$end_date = $snap_time->toDateTimeString();
$start_date = ( $request->date_since != "" ? $request->date_since : $snap_time->subMinutes($request->since ?? 24*60)->toDateTimeString());
$timerange = \App\MatsuriHime\Election::generateChartPointsDate($start_date,$end_date);
$timepoints = Cache::get('timepoints_'.$timerange);
$take = $timepoints->count();
$dramaNames = Election::getDramaNames();
$ranks = collect($dramaNames)->keys();
$charts = [];
$timelabels = Cache::get('timelabels_'.$timerange);
$timelabels = $timelabels->take(-$take)->values();
if($request->take) $timelabels = $timelabels->take($request->take);
foreach($ranks as $roleName) {
$chartPoint = null;
$chartPoint = collect(Cache::get('data_'.$roleName.'_'.$timerange))->keys();
$colors = [];
foreach($chartPoint as $point) {
$colors[] = $this->getIdolColor($point);
}
$chart =$this->newChart($timelabels,$roleName,$request,$request->take,$dramaNames,$colors,$request->enlarge);
$chartData["drama"] = $dramaNames[$roleName];
$chartData["name"] = $roleName;
$chartData["chart"] = $chart;
$charts[] = $chartData;
}
return view('home', [ 'chart_groups' => collect($charts)->groupBy("drama"), 'since' => $request->since, 'enlarge' => $request->enlarge , 'date_since' => $request->date_since, 'take' => $request->take]);
}
public function viewChart($chart_name, Request $request) {
$minutes = $request->since ?? 60*24;
$minutes = $request->since ?? 60*24;
$snap_time = Cache::get('snap_time');
$end_date = $snap_time->toDateTimeString(); $start_date = ( $request->date_since != "" ? $request->date_since : $snap_time->subMinutes($request->since ?? 24*60)->toDateTimeString());
$timerange = \App\MatsuriHime\Election::generateChartPointsDate($start_date,$end_date);
$timepoints = Cache::get('timepoints_'.$timerange);
$take = $timepoints->count();
$idolColors = $this->getIdolColors();
$dramaNames = Election::getDramaNames();
$charts = [];
$timelabels = Cache::get('timelabels_'.$timerange);
$timelabels = $timelabels->take(-$take)->values();
if($request->take) $timelabels = $timelabels->take($request->take);
$roleName = $chart_name;
$roleRank = "Global";
$chartPoint = collect(Cache::get('data_'.$roleName.'_'.$timerange))->keys();
$colors = [];
foreach($chartPoint as $point) {
$colors[] = $this->getIdolColor($point);
}
$chart =$this->newChart($timelabels,$roleName,$request,$request->take,$dramaNames,$colors,$request->enlarge);
$chartData["drama"] = ($roleName == 'global' ? 'Global' : $dramaNames[$roleName]);
$chartData["name"] = $roleName;
$chartData["chart"] = $chart;
$charts[] = $chartData;
return view('home', [ 'chart_groups' => collect($charts)->groupBy("drama"), 'since' => $request->since, 'enlarge' => $request->enlarge , 'date_since' => $request->date_since, 'take' => $request->take, 'chart_name' => $chart_name]);
}
public function viewChartApi($chart_name, Request $request) {
$snap_time = Cache::get('snap_time');
$end_date = $snap_time->toDateTimeString();
$start_date = ( $request->date_since != "" ? $request->date_since : $snap_time->subMinutes($request->since ?? 24*60)->toDateTimeString());
$timerange = \App\MatsuriHime\Election::generateChartPointsDate($start_date,$end_date);
$take = $request->since;
$roleName = $chart_name;
$chartPoint = Cache::get('data_'.$roleName.'_'.$timerange);
$chart = new RankChart;
foreach($chartPoint as $idol => $dataPoints) {
$values = $dataPoints;
if($request->take) $values = $dataPoints->take($request->take)->values();
$chart->dataSet($idol,'line',$values->toArray());
}
return $chart->api();
}
//
}

View File

@ -10,6 +10,7 @@ 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();
@ -35,8 +36,9 @@ class Election
$hasSnapshot = true;
DB::beginTransaction();
foreach($rankings as $ladder) {
$existingSnapshot = Rank::where('role',$ladder->name)->where('summary_time',Carbon::parse($ladder->summaryTime))->count();
if($existingSnapshot == 0) {
$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();
@ -55,49 +57,169 @@ class Election
$rank->score = $remnant->first()->score;
$rank->summary_time = Carbon::parse($ladder->summaryTime);
$rank->save();
\Log::error($remnant_char.' '.$remnant->first()->score);
}
Cache::forever('snap_time_'.$ladder->name,Carbon::parse($ladder->summaryTime));
Cache::forever('snap_time',Carbon::parse($ladder->summaryTime));
} else {
\Log::info("snapshot has been taken for " . (string)$ladder->summaryTime);
}
}
DB::commit();
Election::generateChartPointsNew();
}
public static function generateChartPointsNew() {
$ranks = Rank::orderBy('summary_time')->get()->groupBy('role');
$timepoints = Rank::distinct('summary_time')->orderBy('summary_time')->pluck('summary_time');
Cache::forever('timepoints',$timepoints);
foreach($ranks as $roleName => $roleRank) {
$dataPoints = [];
$ladder = $roleRank->sortBy('summary_time')->groupBy('character')->sortByDesc(function($rank,$key) {
return $rank->last()->score;
});
foreach($ladder as $character => $rank) {
$standing = $rank;
$standing = $standing->pad(-$timepoints->count(),(int)0);
$dataPoints[$character] = $standing->pluck('score');
}
Cache::forever('data_'.$roleName,$dataPoints);
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 generateChartPoints() {
$ranks = Rank::all()->groupBy('role');
foreach($ranks as $roleName => $roleRank) {
$chartPoint = [];
$idols = $roleRank->unique('character')->pluck('character');
$timepoints = $roleRank->sortBy('summary_time')->unique('summary_time')->pluck('summary_time');
foreach($idols as $idol) {
foreach($timepoints as $timepoint) {
$chartPoint[$idol][$timepoint->toDateTimeString()] = 0;
}
foreach($roleRank->where('character',$idol) as $point) {
$chartPoint[$idol][$point->summary_time->toDateTimeString()] = $point->score;
}
}
Cache::forever('chart_point_'.$roleName,$chartPoint);
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());
}
}

View File

@ -19,14 +19,20 @@
</script>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="col-md-12" >
<div class="card">
<div class="card-header">Settings</div>
<div class="card-body">
<form action="{{ url()->current() }}" method="GET">
<form action="{{ url()->current() }}" method="GET" id="settings-form">
@if(isset($since) || isset($date_since))
<div class="form-group">
<a href="{{ url()->current() }}">Reset</a>
</div>
@endif
@if(!isset($date_since))
<div class="form-group">
<label for="show-last">Show last:</label>
<select name="since" id="show-last" onchange="this.form.submit()">
<select name="since" id="show-last" onchange="this.form.submit()" class="form-control">
<option value="">Show last..</option>
<option value="30" {{ $since == 30 ? "selected" : "" }} >30 minutes</option>
<option value="60" {{ $since == 60 ? "selected" : "" }} >1 hour</option>
@ -35,27 +41,20 @@
<option value="1440" {{ $since == 1440 ? "selected" : "" }} >24 hours</option>
<option value="4320" {{ $since == 4320 ? "selected" : "" }} >3 days</option>
<option value="10080" {{ $since == 10080 ? "selected" : "" }} >1 week</option>
<option value="full" {{ $since == "full" ? "selected" : "" }} >Entire history</option>
<option value="86400" {{ $since == 86400 ? "selected" : "" }} >Entire history</option>
</select>
</div>
</form>
<form action="{{ url()->current() }}" method="GET">
@endif
@if(!isset($since))
<div class="form-group">
<label for="datetimepicker1">Date since:</label>
<div class="input-group date" id="datetimepicker1" data-target-input="nearest">
<input name="date_since" type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1" />
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
</div>
</div>
<script type="text/javascript">
$(function () {
$('#datetimepicker1').datetimepicker();
$('#datetimepicker1').on('change.datetimepicker', function() {
this.form.submit();
});
});
</script>
<label for="datetimepicker1">Date since:</label>
<input name="date_since" type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1" value="{{ $date_since }}" onchange="this.form.submit()" />
</div>
@endif
<input type="hidden" name="take" value="{{ $take }}" />
<div class='form-group'>
<input id="enlarge-1" type=checkbox name='enlarge' {{ $enlarge == 'on' ? 'checked' : '' }} onchange="this.form.submit()"/>
<label for="enlarge-1">Enlarge chart</label>
</div>
</form>
</div>
@ -67,7 +66,7 @@
<div>
@foreach($charts as $chart)
<div class="card">
<div class="card-header">{{ $chart["name"] }}</div>
<div class="card-header"><a href="{{ url('chart/'.$chart['name']) }}">{{ $chart["name"] }}</a></div>
<div class="card-body text-center">
{!! $chart["chart"]->container() !!}
<button class="btn btn-primary" onclick="exportPNG('{{ $chart["name"] }} ({{ $drama_name }})',window.{{ $chart["chart"]->id }})">Export as PNG</button>

View File

@ -53,6 +53,8 @@
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<li><a class="nav-link" href="{{ url('/') }}">{{ __('Home') }}</a></li>
<li><a class="nav-link" href="{{ url('/chart/global') }}">{{ __('Global Chart') }}</a></li>
<li><a class="nav-link" href="{{ url('/nukes') }}">{{ __('Nukes') }}</a></li>
<li><a class="nav-link" href="{{ url('/statistics') }}">{{ __('Statistics') }}</a></li>
</ul>
</div>

View File

@ -1,88 +0,0 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="{{ url('jquery.fancybox.min.css') }}" />
<script src="{{ url('jquery.fancybox.js') }}"></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<link rel="stylesheet" href="{{ url('magnific-popup.css') }}" type="text/css" media="screen" />
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light navbar-laravel">
<div class="container">
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Laravel') }}
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
@guest
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
@if (Route::has('register'))
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
@endif
@else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->name }} <span class="caret"></span>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
@if(Auth::user()->is_admin)
@endif
<a class="dropdown-item" href="{{ route('submit') }}">Submit Score</a>
<a class="dropdown-item" href="{{ route('approval') }}">Approve Submission</a>
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
@csrf
</form>
</div>
</li>
@endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
@yield('content')
</main>
</div>
</body>
</html>

View File

@ -0,0 +1,21 @@
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12">
<div class="card">
<div class="card">
<div class="card-header">Nukes</div>
<div class="card-body text-left">
<ul>
@foreach($nukes as $nuke)
<li><strong>{{ $nuke["nuke_time_start"] }}</strong>: ~{{ round($nuke["nuke_pts"],-3) }} nuke by <a href="{{ url('/chart/'.$nuke['role'].'?date_since='.$nuke['nuke_time_start']->subMinutes(30).'&take=13')}}">{{ $nuke["character"] }} as {{ $nuke["role"] }}</a></li>
@endforeach
</ul>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -16,3 +16,6 @@ use Illuminate\Http\Request;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('/chart/{chart}', 'HomeController@viewChartApi');

View File

@ -11,5 +11,7 @@
|
*/
Route::get('/', 'HomeController@home');
Route::get('/', 'HomeController@homeNew');
Route::get('/chart/{chart}', 'HomeController@viewChart');
Route::get('/statistics', 'HomeController@statistics');
Route::get('/nukes','HomeController@nukes');