Merge pull request #358 from shikorism/feature/remake-user-page

グラフページの再編
This commit is contained in:
shibafu
2020-05-24 21:23:23 +09:00
committed by GitHub
13 changed files with 375 additions and 143 deletions

View File

@@ -5,9 +5,11 @@ namespace App\Http\Controllers;
use App\Ejaculation;
use App\User;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Validator;
class UserController extends Controller
{
@@ -60,7 +62,18 @@ SQL
->limit(10)
->get();
return view('user.profile')->with(compact('user', 'ejaculations', 'tags'));
// シコ草
$countByDayQuery = $this->countEjaculationByDay($user)
->where('ejaculated_date', '>=', now()->startOfMonth()->subMonths(9))
->where('ejaculated_date', '<', now()->addMonth()->startOfMonth())
->get();
$countByDay = [];
foreach ($countByDayQuery as $data) {
$date = Carbon::createFromFormat('Y/m/d', $data->date);
$countByDay[$date->timestamp] = $data->count;
}
return view('user.profile')->with(compact('user', 'ejaculations', 'tags', 'countByDay'));
}
public function stats($name)
@@ -70,73 +83,72 @@ SQL
abort(404);
}
$dateUntil = now()->addMonth()->startOfMonth();
$availableMonths = $this->makeStatsAvailableMonths($user);
$graphData = $this->makeGraphData($user);
$groupByDay = Ejaculation::select(DB::raw(
<<<'SQL'
to_char(ejaculated_date, 'YYYY/MM/DD') AS "date",
count(*) AS "count"
SQL
))
->where('user_id', $user->id)
->where('ejaculated_date', '<', $dateUntil)
->groupBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
->orderBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
->get();
return view('user.stats.index')->with(compact('user', 'graphData', 'availableMonths'));
}
$groupByHour = Ejaculation::select(DB::raw(
<<<'SQL'
to_char(ejaculated_date, 'HH24') AS "hour",
count(*) AS "count"
SQL
))
->where('user_id', $user->id)
->where('ejaculated_date', '<', $dateUntil)
->groupBy(DB::raw("to_char(ejaculated_date, 'HH24')"))
->orderBy(DB::raw('1'))
->get();
$dailySum = [];
$monthlySum = [];
$yearlySum = [];
$dowSum = array_fill(0, 7, 0);
$hourlySum = array_fill(0, 24, 0);
// 年間グラフ用の配列初期化
if ($groupByDay->first() !== null) {
$year = Carbon::createFromFormat('Y/m/d', $groupByDay->first()->date)->year;
$currentYear = date('Y');
for (; $year <= $currentYear; $year++) {
$yearlySum[$year] = 0;
}
public function statsYearly($name, $year)
{
$user = User::where('name', $name)->first();
if (empty($user)) {
abort(404);
}
foreach ($groupByDay as $data) {
$date = Carbon::createFromFormat('Y/m/d', $data->date);
$yearAndMonth = $date->format('Y/m');
$dailySum[$date->timestamp] = $data->count;
$yearlySum[$date->year] += $data->count;
$dowSum[$date->dayOfWeek] += $data->count;
$monthlySum[$yearAndMonth] = ($monthlySum[$yearAndMonth] ?? 0) + $data->count;
$validator = Validator::make(compact('year'), [
'year' => 'required|date_format:Y'
]);
if ($validator->fails()) {
return redirect()->route('user.stats', compact('name'));
}
foreach ($groupByHour as $data) {
$hour = (int)$data->hour;
$hourlySum[$hour] += $data->count;
$availableMonths = $this->makeStatsAvailableMonths($user);
if (!isset($availableMonths[$year])) {
return redirect()->route('user.stats', compact('name'));
}
$graphData = [
'dailySum' => $dailySum,
'dowSum' => $dowSum,
'monthlySum' => $monthlySum,
'yearlyKey' => array_keys($yearlySum),
'yearlySum' => array_values($yearlySum),
'hourlyKey' => array_keys($hourlySum),
'hourlySum' => array_values($hourlySum),
];
$graphData = $this->makeGraphData(
$user,
Carbon::createFromDate($year, 1, 1, config('app.timezone'))->startOfDay(),
Carbon::createFromDate($year, 1, 1, config('app.timezone'))->addYear()->startOfDay()
);
return view('user.stats')->with(compact('user', 'graphData'));
return view('user.stats.yearly')
->with(compact('user', 'graphData', 'availableMonths'))
->with('currentYear', (int) $year);
}
public function statsMonthly($name, $year, $month)
{
$user = User::where('name', $name)->first();
if (empty($user)) {
abort(404);
}
$validator = Validator::make(compact('year', 'month'), [
'year' => 'required|date_format:Y',
'month' => 'required|date_format:m'
]);
if ($validator->fails()) {
return redirect()->route('user.stats.yearly', compact('name', 'year'));
}
$availableMonths = $this->makeStatsAvailableMonths($user);
if (!isset($availableMonths[$year]) || !in_array($month, $availableMonths[$year], false)) {
return redirect()->route('user.stats.yearly', compact('name', 'year'));
}
$graphData = $this->makeGraphData(
$user,
Carbon::createFromDate($year, $month, 1, config('app.timezone'))->startOfDay(),
Carbon::createFromDate($year, $month, 1, config('app.timezone'))->addMonth()->startOfDay()
);
return view('user.stats.monthly')
->with(compact('user', 'graphData', 'availableMonths'))
->with('currentYear', (int) $year)
->with('currentMonth', (int) $month);
}
public function okazu($name)
@@ -191,4 +203,104 @@ SQL
return view('user.likes')->with(compact('user', 'likes'));
}
private function makeStatsAvailableMonths(User $user): array
{
$availableMonths = [];
$oldest = $user->ejaculations()->orderBy('ejaculated_date')->first();
if (isset($oldest)) {
$oldestMonth = $oldest->ejaculated_date->startOfMonth();
$currentMonth = now()->startOfMonth();
for ($month = $currentMonth; $oldestMonth <= $currentMonth; $month = $month->subMonth()) {
if (!isset($availableMonths[$month->year])) {
$availableMonths[$month->year] = [];
}
$availableMonths[$month->year][] = $month->month;
}
}
return $availableMonths;
}
private function makeGraphData(User $user, CarbonInterface $dateSince = null, CarbonInterface $dateUntil = null): array
{
if ($dateUntil === null) {
$dateUntil = now()->addMonth()->startOfMonth();
}
$dateCondition = [
['ejaculated_date', '<', $dateUntil],
];
if ($dateSince !== null) {
$dateCondition[] = ['ejaculated_date', '>=', $dateSince];
}
$groupByDay = $this->countEjaculationByDay($user)
->where($dateCondition)
->get();
$groupByHour = Ejaculation::select(DB::raw(
<<<'SQL'
to_char(ejaculated_date, 'HH24') AS "hour",
count(*) AS "count"
SQL
))
->where('user_id', $user->id)
->where($dateCondition)
->groupBy(DB::raw("to_char(ejaculated_date, 'HH24')"))
->orderBy(DB::raw('1'))
->get();
$dailySum = [];
$monthlySum = [];
$yearlySum = [];
$dowSum = array_fill(0, 7, 0);
$hourlySum = array_fill(0, 24, 0);
// 年間グラフ用の配列初期化
if ($groupByDay->first() !== null) {
$year = Carbon::createFromFormat('Y/m/d', $groupByDay->first()->date)->year;
$currentYear = date('Y');
for (; $year <= $currentYear; $year++) {
$yearlySum[$year] = 0;
}
}
foreach ($groupByDay as $data) {
$date = Carbon::createFromFormat('Y/m/d', $data->date);
$yearAndMonth = $date->format('Y/m');
$dailySum[$date->timestamp] = $data->count;
$yearlySum[$date->year] += $data->count;
$dowSum[$date->dayOfWeek] += $data->count;
$monthlySum[$yearAndMonth] = ($monthlySum[$yearAndMonth] ?? 0) + $data->count;
}
foreach ($groupByHour as $data) {
$hour = (int)$data->hour;
$hourlySum[$hour] += $data->count;
}
return [
'dailySum' => $dailySum,
'dowSum' => $dowSum,
'monthlySum' => $monthlySum,
'yearlyKey' => array_keys($yearlySum),
'yearlySum' => array_values($yearlySum),
'hourlyKey' => array_keys($hourlySum),
'hourlySum' => array_values($hourlySum),
];
}
private function countEjaculationByDay(User $user)
{
return Ejaculation::select(DB::raw(
<<<'SQL'
to_char(ejaculated_date, 'YYYY/MM/DD') AS "date",
count(*) AS "count"
SQL
))
->where('user_id', $user->id)
->groupBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"))
->orderBy(DB::raw("to_char(ejaculated_date, 'YYYY/MM/DD')"));
}
}