Skip to content

Instantly share code, notes, and snippets.

@sn0opy
Last active November 26, 2017 11:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sn0opy/b86f07b909e7bb424fb0bfa54beb35f1 to your computer and use it in GitHub Desktop.
Save sn0opy/b86f07b909e7bb424fb0bfa54beb35f1 to your computer and use it in GitHub Desktop.
Class to parse EFT fitting
<?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