Skip to content

Commit 1c292ca

Browse files
committed
Split jobs into separate table, achievement points
1 parent 6c66ddd commit 1c292ca

File tree

15 files changed

+69
-154
lines changed

15 files changed

+69
-154
lines changed

composer.lock

+12-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/fftracker/Cron.php

-44
Original file line numberDiff line numberDiff line change
@@ -105,50 +105,6 @@ public function UpdateOld(int $limit = 1, int $instance = 1): bool|string
105105
}
106106
}
107107

108-
/**
109-
* Function to add missing jobs to tracker
110-
* @return bool|string
111-
*/
112-
public function UpdateJobs(): bool|string
113-
{
114-
try {
115-
#Cache controller
116-
$dbController = HomePage::$dbController;
117-
#Get the freshest character ID
118-
$characterId = $dbController->selectValue('SELECT `characterid` FROM `ffxiv__character` WHERE `deleted` IS NULL ORDER BY `updated` DESC LIMIT 1;');
119-
#Grab its data from Lodestone
120-
$character = (new Character((string)$characterId))->getFromLodestone();
121-
if (empty($character['jobs'])) {
122-
return 'No jobs retrieved for character '.$characterId;
123-
}
124-
#Sort alphabetically by keys
125-
ksort($character['jobs'], SORT_NATURAL);
126-
#Prepare string for ALTER
127-
$alter = [];
128-
#Previous job in the list (for AFTER clause)
129-
$previous = '';
130-
foreach ($character['jobs'] as $job => $details) {
131-
#Remove spaces from the job name
132-
$jobNoSpace = preg_replace('/\s*/', '', $job);
133-
#Check if job is present as respective column
134-
if (!$dbController->checkColumn('ffxiv__character', $jobNoSpace)) {
135-
#Add respective column definition
136-
$alter[] = 'ADD COLUMN `'.$jobNoSpace.'` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT \'Level of '.$job.' job\' AFTER `'.(empty($previous) ? 'pvp_matches' : $previous).'`';
137-
}
138-
#Update previous column name
139-
$previous = $jobNoSpace;
140-
}
141-
if (empty($alter)) {
142-
#Nothing to add
143-
return true;
144-
}
145-
#Generate and run the query
146-
return $dbController->query('ALTER TABLE `ffxiv__character` '.implode(', ', $alter).';');
147-
} catch (\Throwable $e) {
148-
return $e->getMessage()."\r\n".$e->getTraceAsString();
149-
}
150-
}
151-
152108
/**
153109
* Update list of servers
154110
* @return bool|string

lib/fftracker/Entities/Character.php

+28-30
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Character extends Entity
2525
public array $groups = [];
2626
public array $jobs = [];
2727
public array $achievements = [];
28+
public int $achievementPoints = 0;
2829
public array $owned = [];
2930

3031
#Function to get initial data from DB
@@ -45,6 +46,8 @@ protected function getFromDB(): array
4546
} else {
4647
$data['username'] = null;
4748
}
49+
#Get jobs
50+
$data['jobs'] = HomePage::$dbController->selectAll('SELECT `name`, `level`, `last_change` FROM `ffxiv__character_jobs` LEFT JOIN `ffxiv__jobs` ON `ffxiv__character_jobs`.`jobid`=`ffxiv__jobs`.`jobid` WHERE `ffxiv__character_jobs`.`characterid`=:id ORDER BY `name`;', [':id'=>$this->id]);
4851
#Get old names. For now returning only the count due to cases of bullying, when the old names are learnt. They are still being collected, though for statistical purposes.
4952
$data['oldNames'] = HomePage::$dbController->Count('SELECT COUNT(*) FROM `ffxiv__character_names` WHERE `characterid`=:id AND `name`!=:name', [':id'=>$this->id, ':name'=>$data['name']]);
5053
#Get previous known incarnations (combination of gender and race/clan)
@@ -145,19 +148,8 @@ protected function process(array $fromDB): void
145148
foreach ($this->achievements as $key=>$achievement) {
146149
$this->achievements[$key]['time'] = (empty($achievement['time']) ? null : strtotime($achievement['time']));
147150
}
148-
#Remove all already processed elements to converts the rest to jobs array
149-
unset(
150-
$fromDB['characterid'], $fromDB['userid'], $fromDB['username'], $fromDB['name'], $fromDB['avatar'], $fromDB['biography'], $fromDB['genderid'], $fromDB['datacenter'],
151-
$fromDB['registered'], $fromDB['updated'],$fromDB['deleted'], $fromDB['clan'], $fromDB['race'], $fromDB['server'], $fromDB['titleIcon'],
152-
$fromDB['region'], $fromDB['city'], $fromDB['cityid'], $fromDB['nameday'], $fromDB['guardian'], $fromDB['guardianid'],
153-
$fromDB['servers'], $fromDB['incarnations'], $fromDB['title'], $fromDB['titleid'], $fromDB['dbid'], $fromDB['gcId'],
154-
$fromDB['gcrankid'], $fromDB['gc_rank'], $fromDB['gcName'], $fromDB['oldNames'], $fromDB['killedby'],
155-
$fromDB['groups'], $fromDB['achievements'], $fromDB['pvp_matches'], $fromDB['enemyid'], $fromDB['raceid'],
156-
);
157-
$this->jobs = $fromDB;
158-
foreach ($this->jobs as $key=>$job) {
159-
$this->jobs[$key] = (int)$job;
160-
}
151+
$this->achievementPoints = $fromDB['achievement_points'];
152+
$this->jobs = $fromDB['jobs'];
161153
}
162154

163155
#Function to update the entity
@@ -203,16 +195,23 @@ protected function updateDB(bool $manual = false): string|bool
203195
if (($this->lodestone['bio'] === '-')) {
204196
$this->lodestone['bio'] = null;
205197
}
198+
#Get total achievements points. Using foreach for speed
199+
$achievementPoints = 0;
200+
if (!empty($this->lodestone['achievements']) && is_array($this->lodestone['achievements'])) {
201+
foreach ($this->lodestone['achievements'] as $item) {
202+
$achievementPoints += (int)$item['points'];
203+
}
204+
}
206205
#Main query to insert or update a character
207206
$queries[] = [
208207
'INSERT INTO `ffxiv__character`(
209-
`characterid`, `serverid`, `name`, `manual`, `registered`, `updated`, `deleted`, `enemyid`, `biography`, `titleid`, `avatar`, `clanid`, `genderid`, `namedayid`, `guardianid`, `cityid`, `gcrankid`, `pvp_matches`
208+
`characterid`, `serverid`, `name`, `manual`, `registered`, `updated`, `deleted`, `enemyid`, `biography`, `titleid`, `avatar`, `clanid`, `genderid`, `namedayid`, `guardianid`, `cityid`, `gcrankid`, `pvp_matches`, `achievement_points`
210209
)
211210
VALUES (
212-
:characterid, (SELECT `serverid` FROM `ffxiv__server` WHERE `server`=:server), :name, :manual, UTC_DATE(), CURRENT_TIMESTAMP(), NULL, NULL, :biography, (SELECT `achievementid` as `titleid` FROM `ffxiv__achievement` WHERE `title` IS NOT NULL AND `title`=:title LIMIT 1), :avatar, (SELECT `clanid` FROM `ffxiv__clan` WHERE `clan`=:clan), :genderid, (SELECT `namedayid` FROM `ffxiv__nameday` WHERE `nameday`=:nameday), (SELECT `guardianid` FROM `ffxiv__guardian` WHERE `guardian`=:guardian), (SELECT `cityid` FROM `ffxiv__city` WHERE `city`=:city), `gcrankid` = (SELECT `gcrankid` FROM `ffxiv__grandcompany_rank` WHERE `gc_rank`=:gcRank ORDER BY `gcrankid` LIMIT 1), 0
211+
:characterid, (SELECT `serverid` FROM `ffxiv__server` WHERE `server`=:server), :name, :manual, UTC_DATE(), CURRENT_TIMESTAMP(), NULL, NULL, :biography, (SELECT `achievementid` as `titleid` FROM `ffxiv__achievement` WHERE `title` IS NOT NULL AND `title`=:title LIMIT 1), :avatar, (SELECT `clanid` FROM `ffxiv__clan` WHERE `clan`=:clan), :genderid, (SELECT `namedayid` FROM `ffxiv__nameday` WHERE `nameday`=:nameday), (SELECT `guardianid` FROM `ffxiv__guardian` WHERE `guardian`=:guardian), (SELECT `cityid` FROM `ffxiv__city` WHERE `city`=:city), `gcrankid` = (SELECT `gcrankid` FROM `ffxiv__grandcompany_rank` WHERE `gc_rank`=:gcRank ORDER BY `gcrankid` LIMIT 1), 0, :achievementPoints
213212
)
214213
ON DUPLICATE KEY UPDATE
215-
`serverid`=(SELECT `serverid` FROM `ffxiv__server` WHERE `server`=:server), `name`=:name, `updated`=CURRENT_TIMESTAMP(), `deleted`=NULL, `enemyid`=NULL, `biography`=:biography, `titleid`=(SELECT `achievementid` as `titleid` FROM `ffxiv__achievement` WHERE `title` IS NOT NULL AND `title`=:title LIMIT 1), `avatar`=:avatar, `clanid`=(SELECT `clanid` FROM `ffxiv__clan` WHERE `clan`=:clan), `genderid`=:genderid, `namedayid`=(SELECT `namedayid` FROM `ffxiv__nameday` WHERE `nameday`=:nameday), `guardianid`=(SELECT `guardianid` FROM `ffxiv__guardian` WHERE `guardian`=:guardian), `cityid`=(SELECT `cityid` FROM `ffxiv__city` WHERE `city`=:city), `gcrankid`=(SELECT `gcrankid` FROM `ffxiv__grandcompany_rank` WHERE `gc_rank` IS NOT NULL AND `gc_rank`=:gcRank ORDER BY `gcrankid` LIMIT 1);',
214+
`serverid`=(SELECT `serverid` FROM `ffxiv__server` WHERE `server`=:server), `name`=:name, `updated`=CURRENT_TIMESTAMP(), `deleted`=NULL, `enemyid`=NULL, `biography`=:biography, `titleid`=(SELECT `achievementid` as `titleid` FROM `ffxiv__achievement` WHERE `title` IS NOT NULL AND `title`=:title LIMIT 1), `avatar`=:avatar, `clanid`=(SELECT `clanid` FROM `ffxiv__clan` WHERE `clan`=:clan), `genderid`=:genderid, `namedayid`=(SELECT `namedayid` FROM `ffxiv__nameday` WHERE `nameday`=:nameday), `guardianid`=(SELECT `guardianid` FROM `ffxiv__guardian` WHERE `guardian`=:guardian), `cityid`=(SELECT `cityid` FROM `ffxiv__city` WHERE `city`=:city), `gcrankid`=(SELECT `gcrankid` FROM `ffxiv__grandcompany_rank` WHERE `gc_rank` IS NOT NULL AND `gc_rank`=:gcRank ORDER BY `gcrankid` LIMIT 1), `achievement_points`=:achievementPoints;',
216215
[
217216
':characterid'=>$this->id,
218217
':server'=>$this->lodestone['server'],
@@ -230,24 +229,23 @@ protected function updateDB(bool $manual = false): string|bool
230229
':guardian'=>$this->lodestone['guardian']['name'],
231230
':city'=>$this->lodestone['city']['name'],
232231
':gcRank'=>(empty($this->lodestone['grandCompany']['rank']) ? '' : $this->lodestone['grandCompany']['rank']),
232+
':achievementPoints' => [$achievementPoints, 'int']
233233
],
234234
];
235235
#Update levels. Doing this in cycle since columns can vary. This can reduce performance, but so far this is the best idea I have to make it as automated as possible
236236
if (!empty($this->lodestone['jobs'])) {
237237
foreach ($this->lodestone['jobs'] as $job=>$level) {
238-
#Remove spaces from the job name
239-
$jobNoSpace = preg_replace('/\s*/', '', $job);
240-
#Check if column exists in order to avoid errors. Checking that level is not empty to not waste time on updating zeros
241-
if (!empty($level['level']) && HomePage::$dbController->checkColumn('ffxiv__character', $jobNoSpace)) {
242-
#Update level
243-
$queries[] = [
244-
'UPDATE `ffxiv__character` SET `'.$jobNoSpace.'`=:level WHERE `characterid`=:characterid;',
245-
[
246-
':characterid' => $this->id,
247-
':level' => [(int)$level['level'], 'int'],
248-
],
249-
];
250-
}
238+
#Insert job, in case it's missing
239+
$queries[] = ['INSERT IGNORE INTO `ffxiv__jobs` (`name`) VALUES (:job);', [':job' => $job]];
240+
#Update level
241+
$queries[] = [
242+
'INSERT INTO `ffxiv__character_jobs` (`characterid`, `jobid`, `level`, `last_change`) VALUES (:characterid, (SELECT `jobid` FROM `ffxiv__jobs` WHERE `name`=:jobname), :level, CURRENT_TIMESTAMP()) ON DUPLICATE KEY UPDATE `level`=:level, `last_change`=IF(`level`=:level, `last_change`, CURRENT_TIMESTAMP());',
243+
[
244+
':characterid' => $this->id,
245+
':jobname' => $job,
246+
':level' => [(int)$level['level'], 'int'],
247+
],
248+
];
251249
}
252250
}
253251
#Insert server, if it has not been inserted yet. If server is registered at all.
@@ -309,7 +307,7 @@ protected function updateDB(bool $manual = false): string|bool
309307
[
310308
':achievementid'=>$achievementid,
311309
':name'=> $item['name'],
312-
':icon'=> self::removeLodestoneDomain($item['icon']),
310+
':icon'=> str_replace('.png', '.webp', self::removeLodestoneDomain($item['icon'])),
313311
':points'=> $item['points'],
314312
],
315313
];

lib/fftracker/Pages/Character.php

-4
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ protected function generate(array $path): array
3434
if (empty($outputArray['character']['id'])) {
3535
return ['http_error' => 404, 'suggested_link' => $this->getLastCrumb()];
3636
}
37-
#Adjust jobs
38-
foreach ($outputArray['character']['jobs'] as $job=>$level) {
39-
$outputArray['character']['jobs'][$job] = ['name'=>preg_replace('/((?!^)[A-Z])/m', ' $1', $job), 'level'=>$level];
40-
}
4137
#Try to exit early based on modification date
4238
$this->lastModified($outputArray['character']['dates']['updated']);
4339
#Continue breadcrumbs

lib/fftracker/Statistics.php

+2-38
Original file line numberDiff line numberDiff line change
@@ -110,45 +110,9 @@ private function getRaw(array &$data, Controller $dbCon): void
110110
private function getCharacters(array &$data, Controller $dbCon): void
111111
{
112112
#Jobs popularity
113-
$data['characters']['jobs'] = $dbCon->selectRow(
114-
'SELECT
115-
SUM(`Alchemist`) AS `Alchemist`,
116-
SUM(`Armorer`) AS `Armorer`,
117-
SUM(`Astrologian`) AS `Astrologian`,
118-
SUM(`Bard`) AS `Bard`,
119-
SUM(`BlackMage`) AS `Black Mage`,
120-
SUM(`Blacksmith`) AS `Blacksmith`,
121-
SUM(`BlueMage`) AS `Blue Mage`,
122-
SUM(`Botanist`) AS `Botanist`,
123-
SUM(`Carpenter`) AS `Carpenter`,
124-
SUM(`Culinarian`) AS `Culinarian`,
125-
SUM(`Dancer`) AS `Dancer`,
126-
SUM(`DarkKnight`) AS `Dark Knight`,
127-
SUM(`Dragoon`) AS `Dragoon`,
128-
SUM(`Fisher`) AS `Fisher`,
129-
SUM(`Goldsmith`) AS `Goldsmith`,
130-
SUM(`Gunbreaker`) AS `Gunbreaker`,
131-
SUM(`Leatherworker`) AS `Leatherworker`,
132-
SUM(`Machinist`) AS `Machinist`,
133-
SUM(`Miner`) AS `Miner`,
134-
SUM(`Monk`) AS `Monk`,
135-
SUM(`Ninja`) AS `Ninja`,
136-
SUM(`Paladin`) AS `Paladin`,
137-
SUM(`Pictomancer`) AS `Pictomancer`,
138-
SUM(`Reaper`) AS `Reaper`,
139-
SUM(`RedMage`) AS `Red Mage`,
140-
SUM(`Sage`) AS `Sage`,
141-
SUM(`Samurai`) AS `Samurai`,
142-
SUM(`Scholar`) AS `Scholar`,
143-
SUM(`Summoner`) AS `Summoner`,
144-
SUM(`Viper`) AS `Viper`,
145-
SUM(`Warrior`) AS `Warrior`,
146-
SUM(`Weaver`) AS `Weaver`,
147-
SUM(`WhiteMage`) AS `White Mage`
148-
FROM `ffxiv__character`;'
113+
$data['characters']['jobs'] = $dbCon->selectPair(
114+
'SELECT `name`, SUM(`level`) as `sum` FROM `ffxiv__character_jobs` LEFT JOIN `ffxiv__jobs` ON `ffxiv__jobs`.`jobid`=`ffxiv__character_jobs`.`jobid` GROUP BY `ffxiv__character_jobs`.`jobid` ORDER BY `sum` DESC;'
149115
);
150-
#Sort array
151-
arsort($data['characters']['jobs']);
152116
#Most name changes
153117
$data['characters']['changes']['name'] = $dbCon->countUnique('ffxiv__character_names', 'characterid', '', 'ffxiv__character', 'INNER', 'characterid', '`tempresult`.`characterid` AS `id`, `ffxiv__character`.`avatar` AS `icon`, \'character\' AS `type`, `ffxiv__character`.`name`', 'DESC', 20, [], true);
154118
ArrayHelpers::renameColumn($data['characters']['changes']['name'], 'value', 'name');

0 commit comments

Comments
 (0)