diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 02f32142..57f36e07 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -601,61 +601,41 @@ class AjaxProfile extends AjaxHandler */ - $completion = DB::Aowow()->select('SELECT type AS ARRAY_KEY, typeId AS ARRAY_KEY2, cur, max FROM ?_profiler_completion WHERE id = ?d', $pBase['id']); - foreach ($completion as $type => $data) + // questId => [cat1, cat2] + $profile['quests'] = []; + if ($quests = DB::Aowow()->selectCol('SELECT `questId` FROM ?_profiler_completion_quests WHERE `id` = ?d', $pBase['id'])) { - switch ($type) - { - case Type::FACTION: // factionId => amount - $profile['reputation'] = array_combine(array_keys($data), array_column($data, 'cur')); - break; - case Type::TITLE: - foreach ($data as &$d) - $d = 1; - - $profile['titles'] = $data; - break; - case Type::QUEST: - $qList = new QuestList(array(['id', array_keys($data)], Cfg::get('SQL_LIMIT_NONE'))); - $qResult = []; - foreach ($qList->iterate() as $id => $__) - $qResult[$id] = [$qList->getField('cat1'), $qList->getField('cat2')]; - - $profile['quests'] = $qResult; - break; - case Type::SPELL: - foreach ($data as &$d) - $d = 1; - - $profile['spells'] = $data; - break; - case Type::ACHIEVEMENT: - $achievements = array_filter($data, function ($x) { return $x['max'] === null; }); - $statistics = array_filter($data, function ($x) { return $x['max'] !== null; }); - - // achievements - $profile['achievements'] = array_combine(array_keys($achievements), array_column($achievements, 'cur')); - $profile['achievementpoints'] = DB::Aowow()->selectCell('SELECT SUM(points) FROM ?_achievement WHERE id IN (?a)', array_keys($achievements)); - - // raid progression - $activity = array_filter($statistics, function ($x) { return $x['cur'] > (time() - MONTH); }); - foreach ($activity as &$r) - $r = 1; - - // ony .. subtract 10-man from 25-man - - $profile['statistics'] = array_combine(array_keys($statistics), array_column($statistics, 'max')); - $profile['activity'] = $activity; - break; - case Type::SKILL: - foreach ($data as &$d) - $d = [$d['cur'], $d['max']]; - - $profile['skills'] = $data; - break; - } + $qList = new QuestList(array(['id', $quests], Cfg::get('SQL_LIMIT_NONE'))); + if (!$qList->error) + foreach ($qList->iterate() as $id => $__) + $profile['quests'][$id] = [$qList->getField('cat1'), $qList->getField('cat2')]; } + // skillId => [value, max] + $profile['skills'] = DB::Aowow()->select('SELECT `skillId` AS ARRAY_KEY, `value` AS "0", `max` AS "1" FROM ?_profiler_completion_skills WHERE `id` = ?d', $pBase['id']); + + // factionId => amount + $profile['reputation'] = DB::Aowow()->selectCol('SELECT `factionId` AS ARRAY_KEY, `standing` FROM ?_profiler_completion_reputation WHERE `id` = ?d', $pBase['id']); + + // titleId => 1 + $profile['titles'] = DB::Aowow()->selectCol('SELECT `titleId` AS ARRAY_KEY, 1 FROM ?_profiler_completion_titles WHERE `id` = ?d', $pBase['id']); + + // achievementId => date + $profile['achievements'] = DB::Aowow()->selectCol('SELECT `achievementId` AS ARRAY_KEY, `date` FROM ?_profiler_completion_achievements WHERE `id` = ?d', $pBase['id']); + + // just points + $profile['achievementpoints'] = $profile['achievements'] ? DB::Aowow()->selectCell('SELECT SUM(`points`) FROM ?_achievement WHERE `id` IN (?a)', array_keys($profile['achievements'])) : 0; + + // achievementId => counter + $profile['statistics'] = DB::Aowow()->selectCol('SELECT `achievementId` AS ARRAY_KEY, `counter` FROM ?_profiler_completion_statistics WHERE `id` = ?d', $pBase['id']); + + // achievementId => 1 + $profile['activity'] = DB::Aowow()->selectCol('SELECT `achievementId` AS ARRAY_KEY, 1 FROM ?_profiler_completion_statistics WHERE `id` = ?d AND `date` > ?d', $pBase['id'], time() - MONTH); + + // spellId => 1 + $profile['spells'] = DB::Aowow()->selectCol('SELECT `spellId` AS ARRAY_KEY, 1 FROM ?_profiler_completion_spells WHERE `id` = ?d', $pBase['id']); + + $gItems = []; $usedSlots = []; diff --git a/includes/profiler.class.php b/includes/profiler.class.php index 86554b07..deb44bc4 100644 --- a/includes/profiler.class.php +++ b/includes/profiler.class.php @@ -597,103 +597,95 @@ class Profiler /* completion data */ /*******************/ - DB::Aowow()->query('DELETE FROM ?_profiler_completion WHERE id = ?d', $profileId); + // done quests // - // done quests - if ($quests = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, quest AS typeId FROM character_queststatus_rewarded WHERE guid = ?d', $profileId, Type::QUEST, $char['guid'])) + DB::Aowow()->query('DELETE FROM ?_profiler_completion_quests WHERE `id` = ?d', $profileId); + + if ($quests = DB::Characters($realmId)->select('SELECT ?d AS `id`, `quest` AS `questId` FROM character_queststatus_rewarded WHERE `guid` = ?d', $profileId, $char['guid'])) foreach (Util::createSqlBatchInsert($quests) as $q) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$q, array_keys($quests[0])); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_quests (?#) VALUES '.$q, array_keys($quests[0])); CLI::write(' ..quests'); - // known skills (professions only) + // known skills (professions only) // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_skills WHERE `id` = ?d', $profileId); + $skAllowed = DB::Aowow()->selectCol('SELECT `id` FROM ?_skillline WHERE `typeCat` IN (9, 11) AND (`cuFlags` & ?d) = 0', CUSTOM_EXCLUDE_FOR_LISTVIEW); - $skills = DB::Characters($realmId)->select('SELECT ?d AS `id`, ?d AS `type`, `skill` AS typeId, `value` AS cur, `max` FROM character_skills WHERE guid = ?d AND `skill` IN (?a)', $profileId, Type::SKILL, $char['guid'], $skAllowed); + $skills = DB::Characters($realmId)->select('SELECT ?d AS `id`, `skill` AS `skillId`, `value`, `max` FROM character_skills WHERE `guid` = ?d AND `skill` IN (?a)', $profileId, $char['guid'], $skAllowed); $racials = DB::Aowow()->select('SELECT `effect1MiscValue` AS ARRAY_KEY, `effect1DieSides` + `effect1BasePoints` AS qty, `reqRaceMask`, `reqClassMask` FROM ?_spell WHERE `typeCat` = -4 AND `effect1Id` = 6 AND `effect1AuraId` = 98'); - // apply racial profession bonuses - foreach ($skills as &$sk) + + foreach ($skills as &$sk) // apply racial profession bonuses { - if (!isset($racials[$sk['typeId']])) + if (!isset($racials[$sk['skillId']])) continue; - $r = $racials[$sk['typeId']]; + $r = $racials[$sk['skillId']]; if ((!$r['reqRaceMask'] || $r['reqRaceMask'] & (1 << ($char['race'] - 1))) && (!$r['reqClassMask'] || $r['reqClassMask'] & (1 << ($char['class'] - 1)))) { - $sk['cur'] += $r['qty']; - $sk['max'] += $r['qty']; + $sk['value'] += $r['qty']; + $sk['max'] += $r['qty']; } } unset($sk); if ($skills) - { - // apply auto-learned trade skills - DB::Aowow()->query(' - INSERT INTO ?_profiler_completion - SELECT ?d, ?d, spellId, NULL, NULL - FROM ?_skilllineability - WHERE skillLineId IN (?a) AND - acquireMethod = 1 AND - (reqRaceMask = 0 OR reqRaceMask & ?d) AND - (reqClassMask = 0 OR reqClassMask & ?d)', - $profileId, Type::SPELL, - array_column($skills, 'typeId'), - 1 << ($char['race'] - 1), - 1 << ($char['class'] - 1) - ); - foreach (Util::createSqlBatchInsert($skills) as $sk) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$sk, array_keys($skills[0])); - } + DB::Aowow()->query('INSERT INTO ?_profiler_completion_skills (?#) VALUES '.$sk, array_keys($skills[0])); CLI::write(' ..professions'); - // reputation + // reputation // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_reputation WHERE `id` = ?d', $profileId); // get base values for this race/class $reputation = []; - $baseRep = DB::Aowow()->selectCol(' - SELECT id AS ARRAY_KEY, baseRepValue1 FROM aowow_factions WHERE baseRepValue1 && (baseRepRaceMask1 & ?d || (!baseRepRaceMask1 AND baseRepClassMask1)) && - ((baseRepClassMask1 & ?d) || !baseRepClassMask1) UNION - SELECT id AS ARRAY_KEY, baseRepValue2 FROM aowow_factions WHERE baseRepValue2 && (baseRepRaceMask2 & ?d || (!baseRepRaceMask2 AND baseRepClassMask2)) && - ((baseRepClassMask2 & ?d) || !baseRepClassMask2) UNION - SELECT id AS ARRAY_KEY, baseRepValue3 FROM aowow_factions WHERE baseRepValue3 && (baseRepRaceMask3 & ?d || (!baseRepRaceMask3 AND baseRepClassMask3)) && - ((baseRepClassMask3 & ?d) || !baseRepClassMask3) UNION - SELECT id AS ARRAY_KEY, baseRepValue4 FROM aowow_factions WHERE baseRepValue4 && (baseRepRaceMask4 & ?d || (!baseRepRaceMask4 AND baseRepClassMask4)) && - ((baseRepClassMask4 & ?d) || !baseRepClassMask4) - ', $ra, $cl, $ra, $cl, $ra, $cl, $ra, $cl); + $baseRep = DB::Aowow()->selectCol( + 'SELECT `id` AS ARRAY_KEY, `baseRepValue1` FROM aowow_factions WHERE `baseRepValue1` && (`baseRepRaceMask1` & ?d || (!`baseRepRaceMask1` AND `baseRepClassMask1`)) && + ((`baseRepClassMask1` & ?d) || !`baseRepClassMask1`) UNION + SELECT `id` AS ARRAY_KEY, `baseRepValue2` FROM aowow_factions WHERE `baseRepValue2` && (`baseRepRaceMask2` & ?d || (!`baseRepRaceMask2` AND `baseRepClassMask2`)) && + ((`baseRepClassMask2` & ?d) || !`baseRepClassMask2`) UNION + SELECT `id` AS ARRAY_KEY, `baseRepValue3` FROM aowow_factions WHERE `baseRepValue3` && (`baseRepRaceMask3` & ?d || (!`baseRepRaceMask3` AND `baseRepClassMask3`)) && + ((`baseRepClassMask3` & ?d) || !`baseRepClassMask3`) UNION + SELECT `id` AS ARRAY_KEY, `baseRepValue4` FROM aowow_factions WHERE `baseRepValue4` && (`baseRepRaceMask4` & ?d || (!`baseRepRaceMask4` AND `baseRepClassMask4`)) && + ((`baseRepClassMask4` & ?d) || !`baseRepClassMask4`)', + $ra, $cl, $ra, $cl, $ra, $cl, $ra, $cl + ); - if ($reputation = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, faction AS typeId, standing AS cur FROM character_reputation WHERE guid = ?d AND (flags & 0x4) = 0', $profileId, Type::FACTION, $char['guid'])) + if ($reputation = DB::Characters($realmId)->select('SELECT ?d AS `id`, `faction` AS `factionId`, `standing` FROM character_reputation WHERE `guid` = ?d AND (`flags` & 0x4) = 0', $profileId, $char['guid'])) { // merge back base values for encountered factions foreach ($reputation as &$set) { - if (empty($baseRep[$set['typeId']])) + if (empty($baseRep[$set['factionId']])) continue; - $set['cur'] += $baseRep[$set['typeId']]; - unset($baseRep[$set['typeId']]); + $set['standing'] += $baseRep[$set['factionId']]; + unset($baseRep[$set['factionId']]); } } // insert base values for not yet encountered factions foreach ($baseRep as $id => $val) $reputation[] = array( - 'id' => $profileId, - 'type' => Type::FACTION, - 'typeId' => $id, - 'cur' => $val + 'id' => $profileId, + 'factionId' => $id, + 'standing' => $val ); foreach (Util::createSqlBatchInsert($reputation) as $rep) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$rep, array_keys($reputation[0])); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_reputation (?#) VALUES '.$rep, array_keys($reputation[0])); CLI::write(' ..reputation'); - // known titles + // known titles // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_titles WHERE `id` = ?d', $profileId); + $tBlocks = explode(' ', $char['knownTitles']); $indizes = []; for ($i = 0; $i < 6; $i++) @@ -702,38 +694,63 @@ class Profiler $indizes[] = $j + ($i * 32); if ($indizes) - DB::Aowow()->query('INSERT INTO ?_profiler_completion SELECT ?d, ?d, id, NULL, NULL FROM ?_titles WHERE bitIdx IN (?a)', $profileId, Type::TITLE, $indizes); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_titles SELECT ?d, `id` FROM ?_titles WHERE `bitIdx` IN (?a)', $profileId, $indizes); CLI::write(' ..titles'); - // achievements - if ($achievements = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, achievement AS typeId, date AS cur FROM character_achievement WHERE guid = ?d', $profileId, Type::ACHIEVEMENT, $char['guid'])) + // achievements // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_achievements WHERE `id` = ?d', $profileId); + + if ($achievements = DB::Characters($realmId)->select('SELECT ?d AS id, `achievement` AS `achievementId`, `date` FROM character_achievement WHERE `guid` = ?d', $profileId, $char['guid'])) { foreach (Util::createSqlBatchInsert($achievements) as $a) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$a, array_keys($achievements[0])); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_achievements (?#) VALUES '.$a, array_keys($achievements[0])); - $data['achievementpoints'] = DB::Aowow()->selectCell('SELECT SUM(points) FROM ?_achievement WHERE id IN (?a) AND (flags & ?d) = 0', array_column($achievements, 'typeId'), ACHIEVEMENT_FLAG_COUNTER); + $data['achievementpoints'] = DB::Aowow()->selectCell('SELECT SUM(`points`) FROM ?_achievement WHERE `id` IN (?a) AND (`flags` & ?d) = 0', array_column($achievements, 'achievementId'), ACHIEVEMENT_FLAG_COUNTER); } CLI::write(' ..achievements'); - // raid progression - if ($progress = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, criteria AS typeId, date AS cur, counter AS `max` FROM character_achievement_progress WHERE guid = ?d AND criteria IN (?a)', $profileId, Type::ACHIEVEMENT, $char['guid'], self::$raidProgression)) + // raid progression // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_statistics WHERE `id` = ?d', $profileId); + + if ($progress = DB::Characters($realmId)->select('SELECT ?d AS `id`, `criteria` AS `achievementId`, `date`, `counter` FROM character_achievement_progress WHERE `guid` = ?d AND `criteria` IN (?a)', $profileId, $char['guid'], self::$raidProgression)) { - array_walk($progress, function (&$val) { $val['typeId'] = array_search($val['typeId'], self::$raidProgression); }); + array_walk($progress, function (&$val) { $val['achievementId'] = array_search($val['achievementId'], self::$raidProgression); }); foreach (Util::createSqlBatchInsert($progress) as $p) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$p, array_keys($progress[0])); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_statistics (?#) VALUES '.$p, array_keys($progress[0])); } CLI::write(' ..raid progression'); - // known spells - if ($spells = DB::Characters($realmId)->select('SELECT ?d AS id, ?d AS `type`, spell AS typeId FROM character_spell WHERE guid = ?d AND disabled = 0', $profileId, Type::SPELL, $char['guid'])) + // known spells // + + DB::Aowow()->query('DELETE FROM ?_profiler_completion_spells WHERE `id` = ?d', $profileId); + + if ($spells = DB::Characters($realmId)->select('SELECT ?d AS `id`, `spell` AS `spellId` FROM character_spell WHERE `guid` = ?d AND `disabled` = 0', $profileId, $char['guid'])) foreach (Util::createSqlBatchInsert($spells) as $s) - DB::Aowow()->query('INSERT INTO ?_profiler_completion (?#) VALUES '.$s, array_keys($spells[0])); + DB::Aowow()->query('INSERT INTO ?_profiler_completion_spells (?#) VALUES '.$s, array_keys($spells[0])); + + // apply auto-learned spells from trade skills + if ($skills) + DB::Aowow()->query( + 'INSERT INTO ?_profiler_completion_spells + SELECT ?d, `spellId` + FROM ?_skilllineability + WHERE `skillLineId` IN (?a) AND + `acquireMethod` = 1 AND + (`reqRaceMask` = 0 OR `reqRaceMask` & ?d) AND + (`reqClassMask` = 0 OR `reqClassMask` & ?d)', + $profileId, + array_column($skills, 'skillId'), + 1 << ($char['race'] - 1), + 1 << ($char['class'] - 1) + ); CLI::write(' ..known spells (vanity pets & mounts)'); diff --git a/includes/types/profile.class.php b/includes/types/profile.class.php index f1771bd5..a11a6a13 100644 --- a/includes/types/profile.class.php +++ b/includes/types/profile.class.php @@ -397,16 +397,16 @@ class ProfileListFilter extends Filter if ($this->useLocalList) { $this->extraOpts[$k] = array( - 'j' => ['?_profiler_completion '.$k.' ON '.$k.'.id = p.id AND '.$k.'.`type` = '.Type::SKILL.' AND '.$k.'.typeId = '.$skillId.' AND '.$k.'.cur '.$cr[1].' '.$cr[2], true], - 's' => [', '.$k.'.cur AS '.$col] + 'j' => [sprintf('?_profiler_completion_skills %1$s ON `%1$s`.`id` = p.`id` AND `%1$s`.`skillId` = %2$d AND `%1$s`.`value` %3$s %4$d', $k, $skillId, $cr[1], $cr[2]), true], + 's' => [', '.$k.'.`value` AS '.$col] ); - return [$k.'.typeId', null, '!']; + return [$k.'.skillId', null, '!']; } else { $this->extraOpts[$k] = array( - 'j' => ['character_skills '.$k.' ON '.$k.'.guid = c.guid AND '.$k.'.skill = '.$skillId.' AND '.$k.'.value '.$cr[1].' '.$cr[2], true], - 's' => [', '.$k.'.value AS '.$col] + 'j' => [sprintf('character_skills %1$s ON `%1$s`.`guid` = c.`guid` AND `%1$s`.`skill` = %2$d AND `%1$s`.`value` %3$s %4$d', $k, $skillId, $cr[1], $cr[2]), true], + 's' => [', '.$k.'.`value` AS '.$col] ); return [$k.'.skill', null, '!']; } @@ -424,12 +424,12 @@ class ProfileListFilter extends Filter if ($this->useLocalList) { - $this->extraOpts[$k] = ['j' => ['?_profiler_completion '.$k.' ON '.$k.'.id = p.id AND '.$k.'.`type` = '.Type::ACHIEVEMENT.' AND '.$k.'.typeId = '.$cr[2], true]]; - return [$k.'.typeId', null, '!']; + $this->extraOpts[$k] = ['j' => [sprintf('?_profiler_completion_achievements %1$s ON `%1$s`.`id` = p.`id` AND `%1$s`.`achievementId` = %2$d', $k, $cr[2]), true]]; + return [$k.'.achievementId', null, '!']; } else { - $this->extraOpts[$k] = ['j' => ['character_achievement '.$k.' ON '.$k.'.guid = c.guid AND '.$k.'.achievement = '.$cr[2], true]]; + $this->extraOpts[$k] = ['j' => [sprintf('character_achievement %1$s ON `%1$s`.`guid` = c.`guid` AND `%1$s`.`achievement` = %2$d', $k, $cr[2]), true]]; return [$k.'.achievement', null, '!']; } } @@ -439,12 +439,12 @@ class ProfileListFilter extends Filter if (!Util::checkNumeric($cr[2], NUM_CAST_INT)) return false; - if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_items WHERE id = ?d', $cr[2])) + if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_items WHERE `id` = ?d', $cr[2])) return false; $k = 'i_'.Util::createHash(12); - $this->extraOpts[$k] = ['j' => ['?_profiler_items '.$k.' ON '.$k.'.id = p.id AND '.$k.'.item = '.$cr[2], true]]; + $this->extraOpts[$k] = ['j' => [sprintf('?_profiler_items %1$s ON `%1$s`.`id` = p.`id` AND `%1$s`.`item` = %2$d', $k, $cr[2]), true]]; return [$k.'.item', null, '!']; } diff --git a/includes/utilities.php b/includes/utilities.php index 3a96e592..67beccfa 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -1281,12 +1281,7 @@ abstract class Util if (count($d) != $nItems) return []; - $d = array_map(function ($x) { - if ($x === null) - return 'NULL'; - - return DB::Aowow()->escape($x); - }, $d); + $d = array_map(function ($x) { return $x === null ? 'NULL' : DB::Aowow()->escape($x); }, $d); $buff[] = implode(',', $d); diff --git a/setup/db_structure.sql b/setup/db_structure.sql index 1707cc02..a05d85d8 100644 --- a/setup/db_structure.sql +++ b/setup/db_structure.sql @@ -1820,24 +1820,118 @@ CREATE TABLE `aowow_profiler_arena_team_member` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `aowow_profiler_completion_achievements` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_achievements`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_achievements` ( + `id` int(10) unsigned NOT NULL, + `achievementId` smallint(5) unsigned NOT NULL, + `date` int(10) unsigned DEFAULT NULL, + KEY `id` (`id`), + KEY `typeId` (`achievementId`), + CONSTRAINT `FK_pr_completion_achievements` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `aowow_profiler_completion_quests` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_quests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_quests` ( + `id` int(10) unsigned NOT NULL, + `questId` mediumint(8) unsigned NOT NULL, + KEY `id` (`id`), + CONSTRAINT `FK_pr_completion_quests` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `aowow_profiler_completion_reputation` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_reputation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_reputation` ( + `id` int(10) unsigned NOT NULL, + `factionId` smallint(5) unsigned NOT NULL, + `standing` mediumint(9) DEFAULT NULL, + KEY `id` (`id`), + CONSTRAINT `FK_pr_completion_reputation` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `aowow_profiler_completion_skills` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_skills`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_skills` ( + `id` int(10) unsigned NOT NULL, + `skillId` smallint(5) unsigned NOT NULL, + `value` smallint(5) unsigned DEFAULT NULL, + `max` smallint(5) unsigned DEFAULT NULL, + KEY `id` (`id`), + KEY `typeId` (`skillId`), + CONSTRAINT `FK_pr_completion_skills` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `aowow_profiler_completion_spells` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_spells`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_spells` ( + `id` int(10) unsigned NOT NULL, + `spellId` mediumint(8) unsigned NOT NULL, + KEY `id` (`id`), + CONSTRAINT `FK_pr_completion_spells` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `aowow_profiler_completion_statistics` +-- + +DROP TABLE IF EXISTS `aowow_profiler_completion_statistics`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `aowow_profiler_completion_statistics` ( + `id` int(10) unsigned NOT NULL, + `achievementId` smallint(6) NOT NULL, + `date` int(10) unsigned DEFAULT NULL, + `counter` smallint(5) unsigned DEFAULT NULL, + KEY `id` (`id`), + KEY `typeId` (`achievementId`), + CONSTRAINT `FK_pr_completion_statistics` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `aowow_profiler_completion` -- -DROP TABLE IF EXISTS `aowow_profiler_completion`; +DROP TABLE IF EXISTS `aowow_profiler_completion_titles`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8mb4 */; -CREATE TABLE `aowow_profiler_completion` ( - `id` int unsigned NOT NULL, - `type` smallint unsigned NOT NULL, - `typeId` mediumint NOT NULL, - `cur` int DEFAULT NULL, - `max` int DEFAULT NULL, +CREATE TABLE `aowow_profiler_completion_titles` ( + `id` int(10) unsigned NOT NULL, + `titleId` tinyint(3) unsigned NOT NULL, KEY `id` (`id`), - KEY `type` (`type`), - KEY `typeId` (`typeId`), - CONSTRAINT `FK_pr_completion` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + CONSTRAINT `FK_pr_completion_titles` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -3226,7 +3320,7 @@ UNLOCK TABLES; LOCK TABLES `aowow_dbversion` WRITE; /*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */; -INSERT INTO `aowow_dbversion` VALUES (1720451579,0,NULL,NULL); +INSERT INTO `aowow_dbversion` VALUES (1720455279,0,NULL,NULL); /*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */; UNLOCK TABLES; diff --git a/setup/updates/1720455278_01.sql b/setup/updates/1720455278_01.sql new file mode 100644 index 00000000..88b450bb --- /dev/null +++ b/setup/updates/1720455278_01.sql @@ -0,0 +1,73 @@ +SET FOREIGN_KEY_CHECKS=0; + +DROP TABLE IF EXISTS `aowow_profiler_completion_quests`; +CREATE TABLE `aowow_profiler_completion_quests` ( +`id` int unsigned NOT NULL, +`questId` mediumint unsigned NOT NULL, +KEY `id` (`id`), +CONSTRAINT `FK_pr_completion_quests` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_skills`; +CREATE TABLE `aowow_profiler_completion_skills` ( +`id` int unsigned NOT NULL, +`skillId` smallint unsigned NOT NULL, +`value` smallint unsigned DEFAULT NULL, +`max` smallint unsigned DEFAULT NULL, +KEY `id` (`id`), +KEY `typeId` (`skillId`), +CONSTRAINT `FK_pr_completion_skills` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_reputation`; +CREATE TABLE `aowow_profiler_completion_reputation` ( +`id` int unsigned NOT NULL, +`factionId` smallint unsigned NOT NULL, +`standing` mediumint DEFAULT NULL, +KEY `id` (`id`), +CONSTRAINT `FK_pr_completion_reputation` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_titles`; +CREATE TABLE `aowow_profiler_completion_titles` ( +`id` int unsigned NOT NULL, +`titleId` tinyint unsigned NOT NULL, +KEY `id` (`id`), +CONSTRAINT `FK_pr_completion_titles` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_achievements`; +CREATE TABLE `aowow_profiler_completion_achievements` ( +`id` int unsigned NOT NULL, +`achievementId` smallint unsigned NOT NULL, +`date` int unsigned DEFAULT NULL, +KEY `id` (`id`), +KEY `typeId` (`achievementId`), +CONSTRAINT `FK_pr_completion_achievements` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_statistics`; +CREATE TABLE `aowow_profiler_completion_statistics` ( +`id` int unsigned NOT NULL, +`achievementId` smallint NOT NULL, +`date` int unsigned DEFAULT NULL, +`counter` smallint unsigned DEFAULT NULL, -- could be values of INT size, but surely not for bosskill counters, right? ... RIGHT!? +KEY `id` (`id`), +KEY `typeId` (`achievementId`), +CONSTRAINT `FK_pr_completion_statistics` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +DROP TABLE IF EXISTS `aowow_profiler_completion_spells`; +CREATE TABLE `aowow_profiler_completion_spells` ( +`id` int unsigned NOT NULL, +`spellId` mediumint unsigned NOT NULL, +KEY `id` (`id`), +CONSTRAINT `FK_pr_completion_spells` FOREIGN KEY (`id`) REFERENCES `aowow_profiler_profiles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- force profiles to be updated +UPDATE `aowow_profiler_profiles` SET `lastUpdated` = 0; + +DROP TABLE IF EXISTS `aowow_profiler_completion`; + +SET FOREIGN_KEY_CHECKS=1; diff --git a/static/js/Profiler.js b/static/js/Profiler.js index ade3a3e9..8ae3f8e9 100644 --- a/static/js/Profiler.js +++ b/static/js/Profiler.js @@ -95,14 +95,14 @@ function Profiler() { _progress = [ // aowow: don't forget to enable tracking in includes/profiler.class.php { level: 284, instance: 5, heroic: 1, name: g_zones[4987] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'spell_shadow_twilight', achievs: [4816], kills: [[4823, 39863]] }, // Ruby Sanctum 25 hc - { level: 277, instance: 5, heroic: 1, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4637], kills: [[4673, 37970], [4682, 37955], [4664, 37813], [4667, 36626], [4661, 847], [4656, 36855], [4642, 36612], [4679, 36678], [4670, 36627], [4685, 36853], [4676, 36789], [4688, 36597]] }, // Icecrown Citadel 25 hc + { level: 277, instance: 5, heroic: 1, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4637], kills: [[4642, 36612], [4656, 36855], [4661, 847], [4664, 37813], [4667, 36626], [4670, 36627], [4679, 36678], [4673, 37970], [4682, 37955], [4676, 36789], [4685, 36853], [4688, 36597]] }, // Icecrown Citadel 25 hc { level: 271, instance: 5, name: g_zones[4987] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'spell_shadow_twilight', achievs: [4815], kills: [[4820, 39863]] }, // Ruby Sanctum 25 nh { level: 271, instance: 3, heroic: 1, name: g_zones[4987] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'spell_shadow_twilight', achievs: [4818], kills: [[4822, 39863]] }, // Ruby Sanctum 10 hc - { level: 264, instance: 5, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4608], kills: [[4672, 37970], [4681, 37955], [4663, 37813], [4666, 36626], [4660, 847], [4655, 36855], [4641, 36612], [4678, 36678], [4669, 36627], [4683, 36853], [4675, 36789], [4687, 36597]] }, // Icecrown Citadel 25 nh - { level: 264, instance: 3, heroic: 1, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4636], kills: [[4671, 37970], [4680, 37955], [4662, 37813], [4665, 36626], [4659, 847], [4654, 36855], [4640, 36612], [4677, 36678], [4668, 36627], [4684, 36853], [4674, 36789], [4686, 36597]] }, // Icecrown Citadel 10 hc + { level: 264, instance: 5, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4608], kills: [[4641, 36612], [4655, 36855], [4660, 847], [4663, 37813], [4666, 36626], [4669, 36627], [4678, 36678], [4672, 37970], [4681, 37955], [4675, 36789], [4683, 36853], [4687, 36597]] }, // Icecrown Citadel 25 nh + { level: 264, instance: 3, heroic: 1, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4636], kills: [[4640, 36612], [4654, 36855], [4659, 847], [4662, 37813], [4665, 36626], [4668, 36627], [4677, 36678], [4671, 37970], [4680, 37955], [4674, 36789], [4684, 36853], [4686, 36597]] }, // Icecrown Citadel 10 hc { level: 258, instance: 3, name: g_zones[4987] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'spell_shadow_twilight', achievs: [4817], kills: [[4821, 39863]] }, // Ruby Sanctum 10 nh { level: 258, instance: 5, heroic: 1, name: g_zones[4722] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_reputation_argentchampion', achievs: [3812], kills: [[4031, 629], [4034, 34780], [4038, 637], [4042, 641], [4046, 34564]] }, // Trial of the Crusader 25 hc - { level: 251, instance: 3, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4532], kills: [[4648, 37970], [4651, 37955], [4645, 37813], [4646, 36626], [4644, 847], [4643, 36855], [4639, 36612], [4650, 36678], [4647, 36627], [4652, 36853], [4649, 36789], [4653, 36597]] }, // Icecrown Citadel 10 nh + { level: 251, instance: 3, name: g_zones[4812] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'achievement_dungeon_icecrown_frostmourne', achievs: [4532], kills: [[4639, 36612], [4643, 36855], [4644, 847], [4645, 37813], [4646, 36626], [4647, 36627], [4650, 36678], [4648, 37970], [4651, 37955], [4649, 36789], [4652, 36853], [4653, 36597]] }, // Icecrown Citadel 10 nh { level: 245, instance: 5, name: g_zones[4722] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_reputation_argentchampion', achievs: [3916], kills: [[4029, 629], [4035, 34780], [4039, 637], [4043, 641], [4047, 34564]] }, // Trial of the Crusader 25 nh { level: 245, instance: 3, heroic: 1, name: g_zones[4722] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid10, ''), icon: 'achievement_reputation_argentchampion', achievs: [3918], kills: [[4030, 629], [4033, 34780], [4037, 637], [4041, 641], [4045, 34564]] }, // Trial of the Crusader 10 hc { level: 245, instance: 5, name: g_zones[2159] + $WH.sprintf(LANG.lvitem_dd, LANG.lvitem_raid25, ''), icon: 'achievement_boss_onyxia', achievs: [4397], kills: [[1756, 10184]] }, // Onyxia's Lair 25 @@ -792,6 +792,7 @@ function Profiler() { source: 'g_quests', order: 'g_quest_catorder', catgs: 'g_quest_categories', + cattotal: 'g_quest_catorder_total', catgid: 'category2', subcat: 'category', typeid: 5,