#!/usr/bin/perl -w use warnings; use strict; $|=1; use EVE::Db; my $dbh = EVE::Db::dbh(); die "cant connect to db: ".DBI->errstr unless $dbh; use EVE::Cache; my $CC = EVE::Cache::get(); use CGI::Fast qw/ :standard /; while (my $q = new CGI::Fast) { &do_bpo($q); } exit 0; die "never here"; sub do_bpo ($) { use CGI qw/:standard *ul *table *Tr/; my ($q,) = @_; use Time::HiRes qw ( time ); my $begin = time; use EVEcommon; my $trust = $ENV{'HTTP_EVE.TRUSTED'} || 'undef'; print header,"\n", start_html("BPO Calc"),"\n"; my $url = $q->url({absolute=>1,}); $url =~ s,:8\d/,/,; print h1(a({href=>$url,},"BPO Calc")),"\n"; my @sp = (); my $debug = $q->param("debug") || $q->url_param("debug") || 0; if ($debug) { push @sp, "debug=1"; } ## TODO: config my $vtag = $EVE::Db::vtag; my @vers = grep { $_->[3] =~ /:(itm|ta[rmt]):/ } @EVE::Db::versions; my %vers; my @cvers; my $versname = {}; my $vers; for (@vers) { $vers = $_->[0]; die "dupe vers $vers" if exists $vers{$vers}; $vers{$vers} = $_; push @cvers, $vers; $versname->{$vers} = $_->[2]." -- ".$vers; } my $opt_d = $vers{$vers}->[1]; my $dbe = $q->param("db") || $q->url_param("db") || ""; my $db = ($dbe =~ /^(\w+)$/i) ? lc $1 : ""; if ($db) { if ($db eq 'sisi') { $opt_d = "dbz_$db"; } elsif ($db =~ /^(tq|ccp|dbo)$/) { $db = $vers; } if ($vers{$db}) { $opt_d = $vers{$db}->[1]; } if ($db && $q->url_param("db")) { push @sp, "db=$db"; } } else { $db = $vers; } die "no db" unless $opt_d; die "bad db" unless $opt_d =~ /^\w+$/; die "invalid db $db" unless exists $vers{$db}; my $submit = $url; if (@sp) { $submit .= "?".join("&",@sp); } my @parm = (); my $patt = $q->param("patt") || ""; if ($patt) { # Delete("patt"); my $lpatt = $patt; $lpatt =~ s/\s+/%/g; $lpatt =~ s/(^|$)/%/g; $lpatt =~ s/%+/%/g; push @parm, $lpatt; } else { goto BEGINHTML; } my $pub = $q->param("pub"); my $publ = (defined $pub) ? (1 && $pub) : undef; my $sth_bpolist = $dbh->prepare_cached(qq{ select distinct i.typeID, i.typeName from $opt_d.invTypes i, $opt_d.invBlueprintTypes t where t.bluePrintTypeID = i.typeID ${\(defined $publ ? "and i.published = $publ" : "")} ${\($patt ? "and i.typeName like ?" : "")} }) or die $dbh->errstr; $sth_bpolist->execute(@parm) or die $sth_bpolist->errstr; my $rows = $sth_bpolist->fetchall_arrayref(); $sth_bpolist->finish(); my %id_to_bpo = (); for (@$rows) { my ($id, $name,) = @$_; $id_to_bpo{$id} = $name; } my $type = $q->param("type"); $type = undef unless $type && $id_to_bpo{$type}; if (!defined $type) { # try to auto-select type if (scalar(@$rows) == 1) { # just one match? $type = $rows->[0][0]; } else { my $rpatt = quotemeta $patt; my $n; for (@$rows) { my $N = $_->[1]; if (!defined $n || length $n > length $N) { $n = $N; $type = $_->[0]; } } } } if ($type) { my $v; my $key = "typeversions:$vtag:$type"; $v = $CC->get($key) if defined $CC; unless (defined $v && keys %$v) { $v = {}; my ($from, $to, $on, $od, $gen,); for (@vers) { my ($n, $d, $D, $f,) = @$_; my $sth = $dbh->prepare_cached(qq{ select typeID from $d.invTypes where typeID = ? }) or die $dbh->errstr; $sth->execute($type) or die $sth->errstr; my $ar = $sth->fetchall_arrayref(); if (defined $ar && @$ar) { die "morph" unless $ar->[0]->[0] == $type; use Data::Dumper; $Data::Dumper::Sortkeys = 1; my $vd = &load_data($vers{$n}, $type); my $vds = Dumper($vd); my $me = $D." ".$n; if (!defined $od || $od ne $vds) { if (defined $od) { die "no on" unless $on; $v->{$on} = "v".++$gen.": ".$from." - ".($to||$me); } $od = $vds; $from = $me; } $to = $me; $on = $n; } } $v->{$on} = "v".++$gen.": ".$from." - ".$to; $CC->set($key, $v) if defined $CC && defined $v && keys %$v; } if (defined $v && keys %$v) { $versname = $v; @cvers = grep { exists $v->{$_} } @cvers; } } my $me = $q->param("me"); $me = undef unless defined $me && $me =~ /^\s*(-?\d+([\s,]+-?\d+)*)\s*$/; my %me = (0 => "__base",); if ($me) { $me =~ s/[\s,]+/,/g; $me =~ s/(^,|,$)//g; my @mes = split /,/, $me; for (@mes) { $me{int($_)} = '__requested'; } } my $pe = $q->param("pe"); $pe = undef unless defined $pe && $pe =~ /^[\d,]+$/; my %pe = (0 => "__base",); if ($pe) { my @pes = split /,/, $pe; for (@pes) { $pe{int($_)} = '__requested'; } } my $skme = $q->param("skme"); $skme = 0 unless defined $skme && $skme =~ /^[012345]$/; my $skpe = $q->param("skpe"); $skpe = 0 unless defined $skpe && $skpe =~ /^[012345]$/; my $batch = $q->param("batch"); $batch = 1 unless defined $batch && $batch =~ /^\d+$/; my $wastebatch = 1; # EA change: back to per-run rounding my @ids_by_name = sort { lc($id_to_bpo{$a}) cmp lc($id_to_bpo{$b}) } keys %id_to_bpo; #print hr, br, start_form(-method=>'get'); BEGINHTML: print hr, br, $q->start_form({action => $submit,},); print start_table; print Tr(td("Version: "), td({colspan=>2}, $q->popup_menu(-name => 'db', -values => \@cvers, -default => $opt_d, -labels => $versname, ),,),), "\n"; print Tr(td(["Search: ", $q->textfield(-name => 'patt', -default => '', -size => 20,),],),), "\n"; goto ENDHTML unless $patt; print Tr(td("Select: "), td({colspan=>2}, $q->popup_menu(-name => 'type', -values => \@ids_by_name, -default => $type, -labels => \%id_to_bpo, ),,),), "\n"; print Tr(td(["ME: ", $q->textfield( -name => 'me', -default => '', -size => 20,), "f.ex. 20 or 20,50,100",]), td({width=>50,},""), td([ "Metallurgy Level:", $q->radio_group( -name => 'skme', -values => [0,1,2,3,4,5,], -default => 3,), ])), "\n"; print Tr(td(["PE: ", $q->textfield(-name => 'pe', -default => '', -size => 20,),"", "", "Research Level:", $q->radio_group( -name => 'skpe', -values => [0,1,2,3,4,5,], -default => 3,), ])), "\n"; print Tr(td(["Batch: ", $q->textfield(-name => 'batch', -default => '', -size => 20,), # "for waste calculation", ])), "\n"; ENDHTML: print end_table,"\n"; print $q->submit, $q->end_form, "\n"; goto EXITHTML unless $type; # data my $data = &load_data($vers{$db}, $type); die "no data" unless defined $data && keys %$data; my $params = $data->{params}; die "no params" unless defined $params && keys %$params; my $product = $data->{product}; die "no product" unless defined $product && keys %$product; my $sellers = $data->{sellers}; die "no sellers" unless defined $sellers; my $gl = ""; $gl = sprintf '/mybpo?group=%i', $params->{groupID}; if ($ENV{REMOTE_ADDR} =~ /^(10|192)\./) { $gl .= "&show=all"; } my $surl = $q->self_url; $surl =~ s,:8[12345]/,/,; print hr,h2( span({title=>"typeID:".$params->{typeID},}, a({href=>"showinfo:$type"}, $params->{typeName})). " - ".span({style=>'color: green',title=>"groupID:".$params->{groupID},}, ($gl ? a({href=>$gl,},$params->{groupName}) : $params->{groupName}), ). " - ".span({style=>'color: green',title=>"categoryID:".$params->{categoryID},},$params->{categoryName}), " - ".a({href=>"/hist?type=".$params->{typeID},},"hist"), " - ".a({href=>$surl},"link")), "\n"; my @sellers = (); for (@$sellers) { my ($corp, $cid, $min, $max,) = @$_; my $sel = a({href=>"showinfo:2//$cid",},$corp); my $k = "bposellerregions:$opt_d:$vtag:$cid"; my $ar; $ar = $CC->get($k) if defined $CC; unless ($ar) { my $sth = $dbh->prepare_cached(qq{ select distinct r.regionName from $opt_d.mapRegions r, $opt_d.mapSolarSystems s, eve.apiStations sta where sta.corporationID = ? and sta.solarSystemID = s.solarSystemID and s.regionID = r.regionID }) or dir $dbh->errstr; $sth->execute($cid) or die $sth->errstr; $ar = $sth->fetchall_arrayref(); $sth->finish; $CC->set($k, $ar) if defined $CC && defined $ar; } my $sec = sprintf("%.2f-%.2f", $min, $max); if ($ar && @$ar) { my $regs = join ", ", sort map({$_->[0]} @$ar); $sec = span({ style=>'color: green', title=>$regs,}, $sec,); } $sel .= " sec ".$sec; push @sellers, $sel; } my $mwaste = $params->{wasteFactor}; my $metime = $params->{researchMaterialTime}; my $pwaste = $params->{productivityModifier}; my $petime = $params->{researchProductivityTime}; my $ptime = $params->{productionTime}-$params->{productivityModifier}; my $reqs = $data->{reqs}; die "no reqs" unless defined $reqs; my %reqs_wst=(); for my $r (@$reqs) { if ($debug) { print hr,"\n"; print h3("req: ".$_), br, "\n"; for (sort keys %$r) { printf "%s: %s
\n", $_, defined($r->{$_}) ? $r->{$_} : "[NULL]"; } print hr, "\n"; } my $name = $r->{typeName}; $reqs_wst{$name} = { name => $name, quant => $r->{quantity}, id => $r->{materialTypeID}, }; } my $materials = $data->{materials}; die "no materials" unless $materials; my %reqs_add=(); my (@skills_build, @skills_me, @skills_pe, @skills_copy,); for my $r (@$materials) { if ($debug) { print hr,"\n"; print h3("req: ".$_), br, "\n"; for (sort keys %$r) { printf "%s: %s
\n", $_, defined($r->{$_}) ? $r->{$_} : "[NULL]"; } print hr, "\n"; } if ($r->{categoryName} eq 'Skill') { if ($r->{activityName} eq 'Manufacturing') { push @skills_build, $r; } elsif ($r->{activityName} eq 'Research Time Productivity') { push @skills_pe, $r; } elsif ($r->{activityName} eq 'Research Material Productivity') { push @skills_me, $r; } elsif ($r->{activityName} eq 'Copying') { push @skills_copy, $r; } } elsif ($r->{activityName} eq 'Manufacturing') { my $name = $r->{typeName}; my $quant = $r->{quantity}; $reqs_add{$name} = { name => $name, quant => $r->{quantity}, cat => $r->{categoryName}, dmg => $r->{damagePerJob}, id => $r->{requiredTypeID}, rec => $r->{recycle}, }; if ($r->{_recycle}) { for my $R (@{$r->{_recycle}}) { my $name = $R->{typeName}; next unless $reqs_wst{$name}; $reqs_wst{$name}->{quant} -= $R->{quantity}; if ($reqs_wst{$name}->{quant} <= 0) { delete $reqs_wst{$name}; }; } } } } my $maxme = 0; for my $n (keys %reqs_wst) { my $quant = $reqs_wst{$n}->{quant}; # my $tme = $mwaste ? int($quant/$mwaste*0.5) : 0; #14:59 hrm actually (0.02 * BaseWasteFactor * Maxruns * amountOf Mineral) - 1 #15:00 if you stick that in and compare answers, you should see that its right my $tme = $mwaste ? int($quant*$mwaste*$wastebatch*0.02) : 0; if ($quant > 0) { if ($tme*$metime < 365*24*60*60) { $me{$tme} = $n; } else { $maxme = $tme if $tme > $maxme; } } else { warn "negative quantities ('$n' for '$type')in new bpotool?"; next; # wtf. example_ minerals on Hulk } } my $tl = $params->{techLevel}; if (scalar keys %me < 3) { if ($tl == 2 && !@sellers) { $me{"-6"} ||= "t2"; $me{"-4"} ||= "t2"; $me{"-2"} ||= "t2"; $me{"-1"} ||= "t2"; } else { for (10,50,100,300) { if ($maxme > $_) { $me{$_} ||= "random"; } } } } if ($tl == 2 && !@sellers) { $me{"-4"} ||= "t2"; } print start_table; print Tr( td("Produces:"), td($product->{portionSize}."x ".a({href=>"showinfo:".$product->{typeID},},$product->{typeName}). " - ".span({style=>'color: green',title=>"groupID:".$product->{groupID},},$product->{groupName}). " - ".span({style=>'color: green',title=>"categoryID:".$product->{categoryID},},$product->{categoryName}). " - ".a({href=>"/hist?type=".$product->{typeID},},"hist"), ), ),"\n" ; #print Tr( td("ProductGroup:"), td($product->{groupID}." - ".$product->{groupName})),"\n" ; #print Tr( td("ProductCategory:"), td($product->{categoryID}." - ".$product->{categoryName})),"\n" ; if ($product->{categoryName} eq 'Ship' && $product->{basePrice}) { my $col = "platinum"; my $bp = 1.0*$product->{basePrice}; my $ic = 0.3*$bp; print Tr( td("ProductInsurance:"), td( span({style=>'color: green',title=>"payout $col",}, &shortprettyisk($bp))." - ". span({style=>'color: green',title=>"cost $col",}, &shortprettyisk($ic))." == ". &shortprettyisk($bp-$ic) ) ),"\n" ; } #print Tr( td("ProductCategory:"), td($product->{categoryID}." - ".$product->{categoryName})),"\n" ; print Tr(),"\n"; print Tr( td("Techlevel:"), td($tl)),"\n"; print Tr( td("Baseprice:"), td(prettyisk($params->{basePrice}))),"\n" if $params->{basePrice}; print Tr( td("Sellers:"), td(join(br,@sellers))),"\n" if @sellers; print Tr(),"\n"; print Tr( td("Base ME Time:"), td(prettytime($params->{researchMaterialTime})), td(join br, map {a({href=>"showinfo:".$_->{typeID},}, $_->{typeName}." lvl ".$_->{quantity})} @skills_me),),"\n"; print Tr( td("Base Waste Factor:"), td($params->{wasteFactor}."%")),"\n"; print Tr(),"\n"; print Tr( td("Base PE Time:"), td(prettytime($params->{researchProductivityTime})), td(join br, map {a({href=>"showinfo:".$_->{typeID},}, $_->{typeName}." lvl ".$_->{quantity})} @skills_pe),),"\n"; print Tr( td("Base Build Time:"), td(prettytime($params->{productionTime})), td(join br, map {a({href=>"showinfo:".$_->{typeID},}, $_->{typeName}." lvl ".$_->{quantity})} @skills_build),),"\n"; print Tr(),"\n"; print Tr( td("Base Copy Time:"), td(prettytime(2*$params->{researchCopyTime}))),"\n"; #20:34 <%Veritech|AFK> ah the copy time #20:34 <%Veritech|AFK> multiply by 2 #20:34 <%Veritech|AFK> the x2 is a long story #$batch = $params->{maxProductionLimit} if $batch > $params->{maxProductionLimit}; print Tr( td("Max Runs:"), td($params->{maxProductionLimit}." (batch:$batch)")),"\n"; print end_table,hr,"\n"; if ($debug) { for (sort keys %$params) { printf "%s: %s
\n", $_, defined($params->{$_}) ? $params->{$_} : "[NULL]"; } print hr,"\n"; } #22:41 <+nagi> Chruker: current working theory ... invBlueprintTypes # productivitymodifier/productiontime #22:41 <+Chruker> IIIecho "\t\t\t\tLevel ".$industry.": # ".time_format(round(($blueprint_info["productionTime"] * (1 - # (($blueprint_info["productivityModifier"] / # $blueprint_info["productionTime"]) * ($productivity_level / (1 # + $productivity_level)))) * (1 - (0.04 * $industry))), # 0))."
\n"; #round(($blueprint_info["productionTime"] * # (1 - ( # ( $blueprint_info["productivityModifier"] / $blueprint_info["productionTime"]) * # ($productivity_level / (1 + $productivity_level)) # ) # ) # * (1 - (0.04 * $industry))), # 0)) for (0..5) { my $v = 2**$_; last if $v > $pwaste; last if $petime*$v > 365*24*60*60; $pe{$v} = "__exponential"; my $rev = int(($pwaste/$v)+0.5); next if $petime*$rev > 365*24*60*60; $pe{$rev} = "__reverse"; } my $lp; for (sort {$a <=> $b} keys %pe) { my $p = int($pwaste*(1/(1+$_))); if (defined $lp && $pe{$_} =~ /^__/ && $lp == $p) { delete $pe{$_}; } $lp = $p; } my @pe = sort {$a <=> $b} keys %pe; print start_table({border=>1,}),"\n", Tr( th(""), th([map("PE:$_", @pe),]),),"\n"; print Tr({align=>'right',},td("Build Time"), td([map(prettytime($ptime+($pwaste*(1/(1+$_)))), @pe),],),), "\n"; print Tr({align=>'right',},td("Build Time Waste"), td([map(prettytime(($pwaste*(1/(1+$_)))), @pe),],),), "\n"; my @ptimes = ( ['Base', 1,], ['POS', 0.75,], ); if ($skpe) { my $sk = 1-($skpe*0.05); unless ($skpe == 5) { push @ptimes, ['Skill', $sk,]; } push @ptimes, ['Skill & POS', $sk*0.75,]; }; for (sort {$b->[1] <=> $a->[1]} @ptimes) { my ($n, $f,) = @$_; print start_Tr, th("$n Lab time"), th(sprintf "x%.2f", $f), map($_ ? th(prettytime($petime*$_*$f)) : "", @pe), end_Tr, "\n"; } print end_table,"\n"; ######### print start_table({border=>1,}); my @me = sort {$a <=> $b} keys %me; print Tr( th(["Material", "ISK pu", "Base",]), th({colspan=>2}, [map("ME:$_", @me),]),), "\n"; print Tr( td({colspan=>3}, ""), td([map(("needed","wasted",), @me),]),), "\n"; use EVE::Market; my $market = EVE::Market->new( where => "connectedhighsec", when => 30*24*60*60, ) or die "cant get market"; my %cost = (); my $missing = 0; my %cnts = (); for (keys %reqs_wst) { $cnts{$_} += $reqs_wst{$_}{quant}; } for (keys %reqs_add) { $cnts{$_} += $reqs_add{$_}{quant}; } for (sort {$cnts{$b} <=> $cnts{$a}} keys %cnts) { my $wst = $reqs_wst{$_}||{}; my $add = $reqs_add{$_}||{}; my $id = $wst->{id} || $add->{id}; my $name = $wst->{name} || $add->{name}; my $qw = $wst->{quant}||0; my $qa = $add->{quant}||0; my $q = $qw + $qa; my $dmg = $add->{dmg}; my $p = eval { $market->get_price(typeID => $id)->{avg} } || 0; warn $@ if $@; my $busy; my $bpl = ""; my $ar = $data->{"rid:$id"}; if (defined $ar && @$ar) { die "more than one BP for $id" if scalar @$ar > 1; my ($bpid,$bpname,$bpt,) = @{$ar->[0]}; $bpl .= " (".a({href=>"showinfo:$bpid",},"BP"); my $turl = $url."?"; $turl .= "type=$bpid"; $turl .= "&patt=".&urlify($bpname); $bpl .= ",".a({href=>$turl,},"CALC").")"; if ($bpt && $params->{productionTime}) { # warn "BUSY: $bpt * $q / ".$params->{productionTime}; $busy = ($bpt*$q)/$params->{productionTime}; } } print start_Tr({align=>'right',}), td({align=>'left'}, a({href=>"showinfo:$id",}, #$r->{cat}.": ". $name,).$bpl), $p ? td(&shortprettyisk($p)) : td({bgcolor=>'red'}, "n/a"), td(defined $busy ? span({style=>'color: green',title=>sprintf("%.2f%% busy",$busy*100),},$q) : $q); $cost{base} += $q*$p; $missing++ unless $p; for (@me) { my $wf = $_ < 0 ? ($mwaste/100)*(abs($_)+1) : ($mwaste/100)/(1+$_); my $w = int(($wf*$qw*$wastebatch)+0.5); $cost{$_}{n} += $p*int($q+($w/$wastebatch)); $cost{$_}{w} += $p*int($w/$wastebatch); # printf STDERR "WASTE: ME:%i WF:%.5f W:%i\n", $_, $wf, $w; # if ((defined $r->{hasWaste} && $r->{hasWaste}) || # (!defined $r->{hasWaste} && $dmg == 1 && $r->{cat} =~ /^(Material|Commodity)$/)) { if ($qw) { if ($w) { print td([$batch*int($q+($w/$wastebatch)), $batch*$w,]); } else { print td({bgcolor=>'lightgreen'}, [$batch*$q, 0,]); } } else { if ($dmg > 0 && $dmg < 1) { my $d = sprintf "%ix%i%%", $batch, int($dmg*100); my $qq = int(($batch*$dmg*$q)+0.99); print td([$qq, $d,]); } else { print td([$batch*$q, " ",]); } } } print end_Tr, "\n"; } my $p = eval { $market->get_price(typeID => $product->{typeID})->{avg} } || 0; print start_Tr, th("ISK"), $p ? th(&shortprettyisk($product->{portionSize}*$p)) : th({bgcolor=>'red'}, "n/a"), th($missing ? {bgcolor=>'red'} : {}, $cost{base} ? &shortprettyisk($cost{base}) : "n/a"), th($missing ? {bgcolor=>'red'} : {}, [ map( ( &shortprettyisk($cost{$_}{n}), &shortprettyisk($cost{$_}{w}), ), @me), ]), end_Tr, "\n"; my @mtimes = ( ['Base', 1,], ['POS', 0.75,], ); if ($skme) { my $sk = 1-($skme*0.05); unless ($skme == 5) { push @mtimes, ['Skill', $sk,]; } push @mtimes, ['Skill & POS', $sk*0.75,]; }; for (sort {$b->[1] <=> $a->[1]} @mtimes) { my ($n, $f,) = @$_; print start_Tr, th({colspan=>4}, "$n Lab time"), th(sprintf "x%.2f", $f), map($_ ? $_ > 0 ? th({colspan=>2},prettytime($metime*$_*$f)) : th({colspan=>2}, "") : "", @me), end_Tr, "\n"; } print end_table,"\n"; EXITHTML: if ($debug) { print hr,"\n"; for (sort keys %ENV) { printf "%s: %s%s\n", $_, $ENV{$_}, br; } } my $runtime = time - $begin; print hr, "Database: ", $opt_d, br, "\n", $runtime ? sprintf "Completed in %.3f sec.", $runtime : "", end_html,"\n"; } # do_bpo die "never here"; # toolz sub load_data ($$) { my ($db, $type,) = @_; my $opt_d = $db->[1]; #printf STDERR "LOAD: %s ...\n", $opt_d; my $key = "bpodata:".$EVE::Db::vtag.":$opt_d:$type"; my $d; $d = $CC->get($key) if defined $CC; unless (defined $d && keys %$d) { my $sth_params = $dbh->prepare_cached(qq{ select i.groupID, i.typeID, i.typeName, i.basePrice, t.wasteFactor, t.researchMaterialTime, t.productivityModifier, t.researchProductivityTime, t.productionTime, t.productivityModifier, t.techLevel, t.researchCopyTime, t.maxProductionLimit, g.groupName, c.categoryID, c.categoryName from $opt_d.invBlueprintTypes t, $opt_d.invTypes i, $opt_d.invGroups g, $opt_d.invCategories c where i.typeID = ? and i.typeID = t.blueprintTypeID and i.groupID = g.groupID and g.categoryID = c.categoryID }) or die $dbh->errstr; $sth_params->execute($type) or die $sth_params->errstr; $d->{params} = $sth_params->fetchrow_hashref(); $sth_params->finish; my $sth_product = $dbh->prepare_cached(qq{ select i.typeID, i.typeName, i.groupID, i.basePrice, i.portionSize, g.groupName, c.categoryID, c.categoryName from $opt_d.invBlueprintTypes t, $opt_d.invTypes i, $opt_d.invGroups g, $opt_d.invCategories c where t.blueprintTypeID = ? and i.typeID = t.productTypeID and i.groupID = g.groupID and g.categoryID = c.categoryID }) or die $dbh->errstr; $sth_product->execute($type) or die $sth_product->errstr; $d->{product} = $sth_product->fetchrow_hashref(); $sth_product->finish; my $seedtab = "eve.invSeeds"; my $seedcond = ""; if ($db->[3] =~ /:trd:/) { $seedtab = "$opt_d.crpNPCCorporationTrades"; $seedcond = ""; } elsif ($db->[3] =~ /:trdsd:/) { $seedtab = "$opt_d.crpNPCCorporationTrades"; $seedcond = "and t.supplyDemand > 0"; } my $nametab; if ($db->[3] =~ /:en:/) { $nametab = "$opt_d.eveNames"; } elsif ($db->[3] =~ /:in:/) { $nametab = "$opt_d.invNames"; } else { die "no known name strategy"; } my $sth_sellers = $dbh->prepare_cached(qq{ select itemName, itemID, format(min(security),5), format(max(security),5) from ( select n.itemName, n.itemID, m.security from $seedtab t, $nametab n, $opt_d.staStations s, $opt_d.mapSolarSystems m where t.typeID = ? $seedcond and t.corporationID = n.itemID and s.corporationID = t.corporationID and s.solarSystemID = m.solarSystemID ) S group by itemName, itemID }) or die $dbh->errstr; $sth_sellers->execute($type) or die $sth_sellers->errstr; $d->{sellers} = $sth_sellers->fetchall_arrayref(); $sth_sellers->finish; my %rids = (); $d->{reqs} = []; $d->{materials} = []; if ($db->[3] =~ /:itm:/) { my $sth_reqs = $dbh->prepare_cached(qq{ select i.typeName, t.quantity, t.materialTypeID from $opt_d.invTypeMaterials t, $opt_d.invTypes i where t.typeID = ? and t.materialTypeID = i.typeID }) or die $dbh->errstr; $sth_reqs->execute($d->{product}->{typeID}) or die $sth_reqs->errstr; while (my $r = $sth_reqs->fetchrow_hashref()) { next unless $r; push @{$d->{reqs}}, $r; $rids{$r->{materialTypeID}}++; } $sth_reqs->finish(); my $sth_materials = $dbh->prepare_cached(qq{ select c.categoryName, a.activityName, i.typeID, i.typeName, t.quantity, t.damagePerJob, t.requiredTypeID, t.recycle from $opt_d.ramTypeRequirements t, $opt_d.ramActivities a, $opt_d.invTypes i, $opt_d.invGroups g, $opt_d.invCategories c where t.typeID = ? and t.activityID = a.activityID and t.requiredTypeID = i.typeID and i.groupID = g.groupID and g.categoryID = c.categoryID }) or die $dbh->errstr; $sth_materials->execute($type) or die $sth_materials->errstr; while (my $r = $sth_materials->fetchrow_hashref()) { next unless $r; if ($r->{recycle}) { $sth_reqs->execute($r->{requiredTypeID}) or die $sth_reqs->errstr; my $D = []; while (my $R = $sth_reqs->fetchrow_hashref()) { next unless $R; $R->{quantity} *= $r->{quantity}; push @$D, $R; } $sth_reqs->finish(); $r->{_recycle} = $D; } push @{$d->{materials}}, $r; $rids{$r->{requiredTypeID}}++; } $sth_materials->finish(); } elsif ($db->[3] =~ /:ta[rmt]:/) { my $rfrag = ($db->[3] =~ /:tar:/) ? "t.recycle" : "0 as recycle"; my $tfrag = ($db->[3] =~ /:tat:/) ? "TL2MaterialsForTypeWithActivity" : "typeActivityMaterials"; my $afrag = ($db->[3] =~ /:tat:/) ? "activity" : "activityID"; my $aname = ($db->[3] =~ /:bact:/) ? "dbo.ramActivities" : "$opt_d.ramActivities"; my $sth_materials = $dbh->prepare_cached(qq{ select c.categoryName, a.activityName, i.typeID, i.typeName, t.quantity, t.damagePerJob, t.requiredTypeID, 0 as recycle -- $rfrag from $opt_d.$tfrag t, $aname a, $opt_d.invTypes i, $opt_d.invGroups g, $opt_d.invCategories c where t.typeID = ? and t.$afrag = a.activityID and i.groupID = g.groupID and g.categoryID = c.categoryID and t.requiredTypeID = i.typeID }) or die $dbh->errstr; $sth_materials->execute($type) or die $sth_materials->errstr; while (my $r = $sth_materials->fetchrow_hashref()) { next unless $r; if ($r->{activityName} eq 'Manufacturing' && ($r->{damagePerJob} == 1 && $r->{categoryName} =~ /^(Material|Commodity)$/)) { my $R = { 'materialTypeID' => $r->{requiredTypeID}, 'quantity' => $r->{quantity}, 'typeName' => $r->{typeName}, }; push @{$d->{reqs}}, $R; } else { push @{$d->{materials}}, $r; } $rids{$r->{requiredTypeID}}++; } $sth_materials->finish(); } else { die "no known materials strategy: ".$db->[3]; } for my $id (keys %rids) { my $bpsth = $dbh->prepare_cached(qq{ select b.bluePrintTypeID, t.typeName, b.productionTime from $opt_d.invBlueprintTypes b, $opt_d.invTypes t where b.productTypeID = ? and b.bluePrintTypeID = t.typeID }) or die $dbh->errstr; $bpsth->execute($id) or die $bpsth->errstr; $d->{"rid:$id"} = $bpsth->fetchall_arrayref; $bpsth->finish; } #### if (defined $d && keys %$d) { $CC->set($key, $d) if defined $CC; } } return $d; } sub urlify ($){ my ($s,) = @_; $s =~ s/(\W)/sprintf("%%%02x", ord($1))/ige; return $s; }