Strimoid/Strimoid

View on GitHub
app/Console/Commands/UpdateStats.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

namespace Strimoid\Console\Commands;

use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Strimoid\Models\Comment;
use Strimoid\Models\CommentReply;
use Strimoid\Models\Content;
use Strimoid\Models\Entry;
use Strimoid\Models\EntryReply;
use Strimoid\Models\UserAction;

class UpdateStats extends Command
{
    protected $name = 'lara:updatestats';
    protected $description = 'Updates stats.';

    public function handle(): void
    {
        DB::connection()->disableQueryLog();

        $conn = DB::connection();
        $conn->disableQueryLog();

        $firstDay = Carbon::create(2013, 1, 1);

        $x = 1;

        $weekAgo = Carbon::today()->subWeek();
        $actions = UserAction::where('created_at', '>', $weekAgo)->get();

        // Delete old data first
        $fromDay = $weekAgo->diffInDays($firstDay);
        $conn->table('daily_actions')->where('day', '>=', $fromDay)->delete();

        foreach ($actions as $action) {
            $object = $action->element;

            if (!$object) {
                continue;
            }

            $day = $object->created_at->diffInDays($firstDay);
            $points = $this->calculatePoints($action, $object);

            $fieldName = $this->getFieldName($action);

            $query = $conn->table('daily_actions')
                ->where('day', $day)
                ->where('user_id', $action->user_id)
                ->where('group_id', $object->group_id);

            // First try to increase existing record
            $result = $query->increment($fieldName);

            if ($result) {
                $query->increment('uv', $object->uv);
                $query->increment('uv', $object->dv);

                if ($points > 0) {
                    $query->increment('points', $points);
                }
                if ($points < 0) {
                    $query->decrement('points', $points);
                }
            } else {
                $data = [
                    'day' => $day,
                    'user_id' => $action->user_id,
                    'group_id' => $object->group_id,
                    'uv' => $object->uv,
                    'dv' => $object->dv,
                    'contents' => 0,
                    'comments' => 0,
                    'entries' => 0,
                    'points' => $points,
                ];

                $data[$fieldName] = 1;

                $conn->table('daily_actions')->insert($data);
            }

            // Show progress
            if (!$x++ % 100) {
                $this->info($x . ' actions processed');
            }
        }

        $this->info('All actions processed');
    }

    protected function getFieldName($action): ?string
    {
        $className = $action->element::class;

        switch ($className) {
            case Content::class:
                return 'contents';

            case Comment::class:
            case CommentReply::class:
                return 'comments';

            case Entry::class:
            case EntryReply::class:
                return 'entries';
        }

        return null;
    }

    protected function calculatePoints($action, $object)
    {
        $actionPointsBase = 1;
        $actionPointsModifier = 1;
        $actionPoints = $actionPointsBase * $actionPointsModifier;

        $actionScoreBase = $object->uv - $object->dv;
        $actionScoreModifier = 0.5;
        $actionScore = round($actionScoreBase * $actionScoreModifier);

        return $actionPoints + $actionScore;
    }
}