<commit_before><?php namespace App\Console\Commands;

use App\Console\Command;
use App\Models\Item;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class UpdateWardrobe extends Command
{

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'gw2:update-wardrobe';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = "Update the official skins with item ids";

    public static $key = 'resolved-skins';

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {

        $this->infoStart('Getting official skin list...');
        $skins = $this->getOfficialSkinList();
        $this->infoFinish('Getting official skin done');

        $this->infoStart('Resolving skin ids to items...');
        $skins = $this->resolveSkinsToItems($skins);
        $this->infoFinish('Resolving skin ids to items done');

        Redis::set(self::$key, serialize($skins));

    }

    private function getOfficialSkinList()
    {

        $count = count(json_decode(file_get_contents('https://api.guildwars2.com/v2/skins'), true));
        $pages = ceil(($count / 50) - 1);

        $skins = [];

        for ($i = 0; $i <= $pages; $i++) {
            $content = json_decode(@file_get_contents('https://api.guildwars2.com/v2/skins?page=' . $i), true);
            $skins = array_merge($skins, $content);
        }

        return $skins;

    }

    private function resolveSkinsToItems($skins)
    {

        // Cleanup the names
        foreach ($skins as &$skin) {
            $skin['name'] = trim($skin['name']);
        }

        // Try and grab the items for the skins
        $skins = $this->resolveItemsBySkinId($skins);
        $skins = $this->resolveItemsByName($skins);
        $skins = $this->resolveItemsBySkinName($skins);
        $skins = $this->resolveItemsBySloppyName($skins);
        $skins = $this->resolveItemsByWiki($skins);

        // Show which skins we are not resolving :(
        $this->info('Not being able to resolve ' . count($this->missingItems($skins)) . ' skins:');
        foreach ($skins as &$skin) {

            if (isset($skin['items'])) {
                continue;
            }

            $this->info('   > ' . $skin['name'] . '(' . $skin['id'] . ')');
            $skin['items'] = [];

        }

        // Build a return array!
        $return = [];
        foreach ($skins as $skin) {
            $return[(int) $skin['id']] = array_values(array_map('intval', array_unique($skin['items'])));
        }

        return $return;

    }

    /**
     * @param $skins
     * @return array
     */
    private function resolveItemsBySkinId($skins)
    {

        $skin_items = Item::select('skin', DB::raw("GROUP_CONCAT(DISTINCT id SEPARATOR ',') AS items"))
            ->whereIn('skin', array_pluck($skins, 'id'))
            ->groupBy('skin')
            ->lists('items', 'skin');

        foreach ($skins as &$skin) {

            if (!isset($skin_items[$skin['id']])) {
                continue;
            }

            $skin['items'] = explode(',', $skin_items[$skin['id']]);

        }

        $this->info('Resolved ' . count($skin_items) . ' skins by skin id...');

        return $skins;

    }

    private function resolveItemsByName($skins)
    {

        // Grab the names of the remaining skins
        $names = array_pluck($skins, 'name');

        // Try to find them
        $name_items = Item::select('name_en', DB::raw("GROUP_CONCAT(DISTINCT id SEPARATOR ',') AS items"))
            ->whereIn('name_en', $names)
            ->groupBy('name_en')
            ->lists('items', 'name_en');

        foreach ($skins as &$skin) {

            $name = $skin['name'];

            if (!isset($name_items[$name])) {
                continue;
            }

            $skin_items = explode(',', $name_items[$name]);

            if (isset($skin['items'])) {
                $skin['items'] = array_merge($skin['items'], $skin_items);
            } else {
                $skin['items'] = $skin_items;
            }

        }

        $this->info('Resolved ' . count($name_items) . ' skins by name lookup...');

        return $skins;

    }

    private function resolveItemsBySkinName($skins)
    {

        $skinName = function ($skin) {
            return $skin . ' Skin';
        };

        // Grab the names of the remaining skins
        $names = array_map($skinName, array_pluck($skins, 'name'));

        // Try to find them<commit_msg>Fix some guesswork mistakes<commit_after><?php namespace App\Console\Commands;

use App\Console\Command;
use App\Models\Item;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;

class UpdateWardrobe extends Command
{

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'gw2:update-wardrobe';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = "Update the official skins with item ids";

    public static $key = 'resolved-skins';

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {

        $this->infoStart('Getting official skin list...');
        $skins = $this->getOfficialSkinList();
        $this->infoFinish('Getting official skin done');

        $this->infoStart('Resolving skin ids to items...');
        $skins = $this->resolveSkinsToItems($skins);
        $this->infoFinish('Resolving skin ids to items done');

        Redis::set(self::$key, serialize($skins));

    }

    private function getOfficialSkinList()
    {

        $count = count(json_decode(file_get_contents('https://api.guildwars2.com/v2/skins'), true));
        $pages = ceil(($count / 50) - 1);

        $skins = [];

        for ($i = 0; $i <= $pages; $i++) {
            $content = json_decode(@file_get_contents('https://api.guildwars2.com/v2/skins?page=' . $i), true);
            $skins = array_merge($skins, $content);
        }

        return $skins;

    }

    private function resolveSkinsToItems($skins)
    {

        // Cleanup the names
        foreach ($skins as &$skin) {
            $skin['name'] = trim($skin['name']);
        }

        // Try and grab the items for the skins
        $skins = $this->resolveItemsBySkinId($skins);
        $skins = $this->resolveItemsByName($skins);
        $skins = $this->resolveItemsBySkinName($skins);
        $skins = $this->resolveItemsBySloppyName($skins);
        $skins = $this->resolveItemsByWiki($skins);

        // Show which skins we are not resolving :(
        $this->info('Not being able to resolve ' . count($this->missingItems($skins)) . ' skins:');
        foreach ($skins as &$skin) {

            if (isset($skin['items'])) {
                continue;
            }

            $this->info('   > ' . $skin['name'] . '(' . $skin['id'] . ')');
            $skin['items'] = [];

        }

        // Build a return array!
        $return = [];
        foreach ($skins as $skin) {
            $return[(int) $skin['id']] = array_values(array_map('intval', array_unique($skin['items'])));
        }

        return $return;

    }

    /**
     * @param $skins
     * @return array
     */
    private function resolveItemsBySkinId($skins)
    {

        $skin_items = Item::select('skin', DB::raw("GROUP_CONCAT(DISTINCT id SEPARATOR ',') AS items"))
            ->whereIn('skin', array_pluck($skins, 'id'))
            ->groupBy('skin')
            ->lists('items', 'skin');

        foreach ($skins as &$skin) {

            if (!isset($skin_items[$skin['id']])) {
                continue;
            }

            $skin['items'] = explode(',', $skin_items[$skin['id']]);

        }

        $this->info('Resolved ' . count($skin_items) . ' skins by skin id...');

        return $skins;

    }

    private function resolveItemsByName($skins)
    {

        // Grab the names of the remaining skins
        $names = array_pluck($this->missingItems($skins), 'name');

        // Try to find them
        $name_items = Item::select('name_en', DB::raw("GROUP_CONCAT(DISTINCT id SEPARATOR ',') AS items"))
            ->whereIn('name_en', $names)
            ->groupBy('name_en')
            ->lists('items', 'name_en');

        foreach ($skins as &$skin) {

            $name = $skin['name'];

            if (!isset($name_items[$name])) {
                continue;
            }

            $skin['items'] = explode(',', $name_items[$name]);

        }

        $this->info('Resolved ' . count($name_items) . ' skins by name lookup...');

        return $skins;

    }

    private function resolveItemsBySkinName($skins)
    {

        $skinName = function ($skin) {
            return $skin . ' Skin';
        };

        // Grab the names of the remaining skins
        $names = array_map($skinName, array_pluck($skins, 'name'));

        // Try to find them
{'fraction_non_alphanumeric': 0.16296625222024866, 'fraction_numerical': 0.0019982238010657193, 'mean_word_length': 2.051829268292683, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 50, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4027402', 'n_tokens_mistral': 2823, 'n_tokens_neox': 2601, 'n_words': 582}