Last active
November 26, 2017 11:52
-
-
Save sn0opy/b86f07b909e7bb424fb0bfa54beb35f1 to your computer and use it in GitHub Desktop.
Class to parse EFT fitting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Fittingcalc | |
{ | |
// don't touch this, or you will lose your hands | |
// see dgmAttributeTypes to know what they are | |
const REQ_SKILLS_ATTRIBUTES = [182, 183, 184, 1285, 1289, 1290]; | |
const REQ_SKILLS_LEVELS = [277, 278, 279, 1286, 1287, 1288]; | |
const REQ_SKILLS_ATTR_LEVLES = [ | |
182 => 277, | |
183 => 278, | |
184 => 279, | |
1285 => 1286, | |
1289 => 1287, | |
1290 => 1288, | |
]; | |
const DG_PGOUTPUT = 11; | |
const DG_PGLOAD = 15; | |
const DG_CPUOUTPUT = 48; | |
const DG_CPULOAD = 49; | |
const RAISE_ALREADY_FULLFILLED = 0; | |
const RAISE_SKILL_RAISED = 1; | |
const RAISE_CANNOT_RAISE = 2; | |
const CPU_SKILL_ORDER = [ | |
// CPU Management | |
// Weapon Upgrades | |
[3426 => 1], | |
[3318 => 1], | |
[3426 => 2], | |
[3318 => 2], | |
[3426 => 3], | |
[3318 => 3], | |
[3426 => 4], | |
[3426 => 5], | |
[3318 => 4], | |
[3318 => 5] | |
]; | |
const PG_SKILL_ORDER = [ | |
// Power Grid Management | |
// Shield Upgrades | |
// Advanced Weapon Upgrades | |
[3413 => 1], | |
[3413 => 2], | |
[3413 => 3], | |
[3413 => 4], | |
[3413 => 5], | |
[3425 => 1], | |
[11207 => 1], | |
[3425 => 2], | |
[11207 => 2], | |
[3425 => 3], | |
[11207 => 3], | |
[3425 => 4], | |
[11207 => 4], | |
[3425 => 5], | |
[11207 => 5] | |
]; | |
private static $ctx; | |
private static $cpu_raise_index = 0; | |
private static $pg_raise_index = 0; | |
private static $requiredSkills = []; | |
public static function calculate($fitting) | |
{ | |
$items = self::parseEftFitting($fitting); | |
$item_ids = self::getUniqueTypeIDs($items['all_item_types']); | |
self::getReqSkillsByTypeIDs($item_ids); | |
self::modifyRequiredSkills($items['fit_items']); | |
return json_encode(self::getSkillNames(self::$requiredSkills)); | |
} | |
private static function modifyRequiredSkills($fitting) | |
{ | |
dogma_init_context(self::$ctx); | |
dogma_set_default_skill_level(self::$ctx, 0); | |
$fitting = self::convertToTypeIDs($fitting); | |
// add ship | |
dogma_set_ship(self::$ctx, array_shift($fitting)); | |
// add skills | |
foreach (self::$requiredSkills as $skill => $level) { | |
dogma_set_skill_level(self::$ctx, $skill, $level); | |
} | |
// add modules | |
foreach($fitting as $item) { | |
dogma_add_module_s(self::$ctx, $item, $key, DOGMA_STATE_Active); | |
} | |
// raise CPU skills | |
$raise = null; | |
while (self::getAttribValue(self::DG_CPUOUTPUT) < self::getAttribValue(self::DG_CPULOAD) && $raise !== self::RAISE_CANNOT_RAISE) { | |
$raise = self::raiseSkill('cpu'); | |
} | |
// raise Powergrid skills | |
$raise = null; | |
while (self::getAttribValue(self::DG_PGOUTPUT) < self::getAttribValue(self::DG_PGLOAD) && $raise !== self::RAISE_CANNOT_RAISE) { | |
$raise = self::raiseSkill('powergrid'); | |
} | |
//\Log::warning("cpu: ".self::getAttribValue(self::DG_CPULOAD)."/".self::getAttribValue(self::DG_CPUOUTPUT)); | |
//\Log::warning("pg: ".self::getAttribValue(self::DG_PGLOAD)."/".self::getAttribValue(self::DG_PGOUTPUT)); | |
} | |
private static function getAttribValue($attrib) | |
{ | |
dogma_get_ship_attribute(self::$ctx, $attrib, $ret); | |
return $ret; | |
} | |
private static function raiseSkill($type) | |
{ | |
switch($type) { | |
case 'cpu': | |
$index =& self::$cpu_raise_index; | |
$skillsOrder = self::CPU_SKILL_ORDER; | |
break; | |
case 'powergrid': | |
$index =& self::$pg_raise_index; | |
$skillsOrder = self::PG_SKILL_ORDER; | |
break; | |
} | |
if (!isset($skillsOrder[$index])) { | |
return self::RAISE_CANNOT_RAISE; | |
} | |
$skill = $skillsOrder[$index]; | |
$skillId = key($skill); | |
$level = $skill[$skillId]; | |
$index++; | |
if (!isset(self::$requiredSkills[$skillId]) || self::$requiredSkills[$skillId] < $level) { | |
dogma_set_skill_level(self::$ctx, $skillId, $level); | |
self::$requiredSkills[$skillId] = $level; | |
return self::RAISE_SKILL_RAISED; | |
} | |
return self::RAISE_ALREADY_FULLFILLED; | |
} | |
private static function getReqSkillsByTypeIDs($typeIDs) | |
{ | |
$attributeids = array_merge(array_keys(self::REQ_SKILLS_ATTR_LEVLES), array_values(self::REQ_SKILLS_ATTR_LEVLES)); | |
foreach ($typeIDs as $type) { | |
$res = \DB::query( | |
"SELECT attributeID, valueInt, valueFloat | |
FROM dgmTypeAttributes | |
WHERE typeID = :typeid AND attributeID IN :attributeids | |
ORDER BY attributeID") | |
->parameters([ | |
':typeid' => $type['typeID'], | |
':attributeids' => $attributeids]) | |
->execute('sde') | |
->as_array(); | |
if (count($res)) { | |
$skillsToAdd = self::prepareRequiredSkills($res); | |
self::buildMinRequiredSkills($skillsToAdd); | |
self::findSubRequiredSkills($skillsToAdd); | |
} | |
} | |
} | |
private static function findSubRequiredSkills($skills) | |
{ | |
$toFind = []; | |
foreach ($skills as $skill => $level) { | |
$toFind[] = ['typeID' => $skill]; | |
} | |
self::getReqSkillsByTypeIDs($toFind); | |
} | |
private static function buildMinRequiredSkills($toAdd) | |
{ | |
foreach($toAdd as $skill => $level) { | |
if (isset(self::$requiredSkills[$skill])) { | |
if (self::$requiredSkills[$skill] < $level) { | |
self::$requiredSkills[$skill] = $level; | |
} | |
} else { | |
self::$requiredSkills[$skill] = $level; | |
} | |
} | |
} | |
private static function prepareRequiredSkills($attributes) | |
{ | |
$skills = []; | |
$keys = []; | |
// build an array of attributes | |
foreach ($attributes as $attribute) { | |
$attribValue = $attribute['valueInt'] !== null ? $attribute['valueInt'] : $attribute['valueFloat']; | |
$keys[$attribute['attributeID']] = $attribValue; | |
} | |
// iterate over all attributes and build the skill array | |
foreach(self::REQ_SKILLS_ATTR_LEVLES as $k => $v) { | |
if (isset($keys[$k])) { | |
$skills[$keys[$k]] = $keys[$v]; | |
} | |
} | |
return $skills; | |
} | |
private static function parseEftFitting($fitting) | |
{ | |
$fitting = self::sanatizeFittingBlock($fitting); | |
$fitsplit = explode("\n", $fitting); | |
// get shipname of first line by removing brackets | |
list($shipname, $fitname) = explode(", ", substr(array_shift($fitsplit), 1, -1)); | |
$fit_all_items = []; | |
$fit_calc_items = []; | |
// first element is always the ship type | |
$fit_all_items[] = $fit_calc_items[] = $shipname; | |
foreach ($fitsplit as $key => $line) { | |
// split line to get charge | |
$linesplit = explode(", ", $line); | |
if (isset($linesplit[1])) { | |
$fit_all_items[] = $linesplit[1]; | |
} | |
// don't add drones to fitting | |
if (preg_match("/ x\d+/", $linesplit[0])) { | |
$fit_all_items[] = self::sanatizeTypeName($linesplit[0]); | |
} else { | |
$fit_all_items[] = $fit_calc_items[] = self::sanatizeTypeName($linesplit[0]); | |
} | |
} | |
return ['all_item_types' => array_unique($fit_all_items), 'fit_items' => $fit_calc_items]; | |
} | |
private static function getUniqueTypeIDs($items) | |
{ | |
$res = \DB::query("SELECT typeID, typeName FROM invTypes WHERE typeName IN :typenames") | |
->parameters([':typenames' => $items]) | |
->execute('sde') | |
->as_array(); | |
return $res; | |
} | |
private static function convertToTypeIDs($items) { | |
foreach ($items as $key => $item) { | |
$items[$key] = \DB::query("SELECT typeID FROM invTypes WHERE typeName = :typename") | |
->parameters([':typename' => $item]) | |
->execute('sde') | |
->current()['typeID']; | |
} | |
return $items; | |
} | |
private static function sanatizeFittingBlock($fitting) | |
{ | |
// remove useless empty lines and whatnot | |
return ltrim(rtrim(preg_replace("/^[ \t]*[\r\n]+/m", "", $fitting))); | |
} | |
private static function sanatizeTypeName($item) | |
{ | |
// remove amount for charges | |
// sample: Scourge Rage Heavy Assault Missile x66 | |
return ltrim(rtrim(preg_replace("/ x\d+/", "", $item))); | |
} | |
private static function getSkillNames($types) | |
{ | |
$skills = []; | |
foreach($types as $skill => $level) { | |
$res = \DB::query('SELECT typeName FROM invTypes WHERE typeID = :typeid') | |
->parameters([':typeid' => $skill]) | |
->execute('sde') | |
->current(); | |
$skills[] = [ | |
'typeId' => $skill, | |
'typeName' => $res['typeName'], | |
'level' => $level | |
]; | |
} | |
ksort($skills); | |
return $skills; | |
} | |
private static function getItemNames($items) | |
{ | |
$itemNames = []; | |
foreach($items as $typeid) { | |
$res = \DB::query('SELECT typeName FROM invTypes WHERE typeID = :typeid') | |
->parameters([':typeid' => $typeid]) | |
->execute('sde') | |
->current(); | |
$itemNames[] = $res['typeName']; | |
} | |
ksort($itemNames); | |
return $itemNames; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment