Mercurial > hg > reproctool-df
view reproctool.cgi @ 54:7e8040e64051 default tip
removed stray text
author | df |
---|---|
date | Tue, 03 Feb 2009 11:53:35 +0000 |
parents | 421e17de31af |
children |
line wrap: on
line source
#!/usr/bin/perl -T # # CGI script for assessing reprocessing value of items in EVE-Online based # on mineral prices. # # Released under the revised BSD licence # Copyright (c) 2009 Dominic Cleal # Portions copyright (c) 2009 Bjorn Hamels use warnings; use strict; use Switch; use CGI; use DBI; use LWP::UserAgent; use Storable qw/store_fd fd_retrieve/; # Settings from params.cgi our (@dbparams, $img_http_path, $eve_central_url, $marks_cache, $marks_cache_expiry); $img_http_path = '/itemimgs'; $eve_central_url = 'http://eve-central.com/api/evemon'; $marks_cache = 'minerals.cache'; $marks_cache_expiry = 4 * 60 * 60; # 4 hours require './params.cgi'; # Begin script my $cgi = new CGI; print $cgi->header(-type => 'text/html', -pragma => 'no-cache', -expires => '-365d'); sub user_error { my $text = shift; print<<END; <html><head><title>Error</title></head> <body><font color="#FF0000"><b>Error:</b></font> $text</body></html> END exit; } # Inputs my $cols = $cgi->param('cols') || 4; my $str_items = $cgi->param('items'); # Generate the first page, where eve-central mineral prices are prefilled. unless ($str_items) { # Try and pull the marks out of a stored cache my $marks; if (-e $marks_cache) { open CACHE, "< $marks_cache" || die("Can't open cache $marks_cache: $!"); $marks = fd_retrieve(*CACHE) || die("Can't read marks from cache: $!"); close CACHE; # Check expiry time if (time > ($marks->{timestamp} + $marks_cache_expiry)) { $marks = undef; } } unless ($marks) { # User can enter their own numbers if eve-central was down $marks->{$_} = 1 foreach ('Tritanium', 'Pyerite', 'Mexallon', 'Isogen', 'Nocxium', 'Zydrine', 'Megacyte', 'Morphite'); # If cache was unavailable or had expired, pull again from eve-central my $ua = LWP::UserAgent->new; $ua->agent('reproctool'); my $resp = $ua->request(HTTP::Request->new(GET => $eve_central_url)); if ($resp->is_success) { # Store as Mineral => 1234 $marks = { timestamp => time }; foreach (split(/[\n\r]/, $resp->content)) { next unless (/<name>(.+)<\/name>.*<price>([0-9\.]+)<\/price>/i); $marks->{$1} = $2; } if (-e $marks_cache) { unlink $marks_cache || die("Unable to unlink cache $marks_cache: $!"); } # Store into the cache open CACHE, "> $marks_cache" || die("Can't open cache $marks_cache to write: $!"); store_fd($marks, *CACHE) || die("Can't write to cache: $!"); close CACHE; } } delete $marks->{timestamp} if exists $marks->{timestamp}; # What evenutally will be printed. print<<END; <html><head><title>Ramm's RDI's reprocessing tool</title></head> <body> Welcome to the sell, reprocess or keep tool. :) <p /> Here's a <a href="http://rammsrdi.com/img/reproctool.png">screenshot</a> on how it looks in game. <p /> Mineral prices below are empire averages from <a href="http://www.eve-central.com/">EVE-Central</a>. Usually you dont need to update those yourself, unless the EVE-Central is down, or you live in special areas and are not welcome in empire space anymore. <p /> How does this work? Well, you need to copy paste an item list (text) in the input box below, then press submit. Getting this item list from your inventory is simple, albeit unusual. Follow these steps: <ol> <li>Put all the items in a container in your station</li> <li>Richt click to container and select 'Create contract'.</li> <li>Click 'Next' and then again 'Next'.</li> <li>A popup will appear which will list the items in the container! Richt click the text area of the popup, and select 'Copy'.</li> <li>Cancel the contract creation! (We only needed the item list, there is no contract needed).</li> <li>Paste the text you just copied in the text box below, and click 'Submit'.</li> <li>The page will take some seconds to load, be patient. If the server gives you an error, you just copy pasted too many items. Try again with half the list.</li> </ol> <p /> Tip: Set the number of columns to match your inventory columns for easy comparison. <p /> <hr> <form method="post"> <textarea rows="5" cols="80" name="items"></textarea> <table border="0" cellspacing="4"> <tr> END # Lists the name of the minerals. print "<td>$_</td>\n" foreach (keys %{$marks}); print "</tr><tr>"; foreach (keys %{$marks}) { my $sname = lc substr($_, 0, 4); my $fmt = sprintf('%.2f', $marks->{$_}); print "<td><input type='text' name='$sname' size='7' value='$fmt' /></td>\n"; } print <<END; </tr> </table> Columns: <input type='text' name='cols' size='2' value='4' /><br /><br /> <input type="submit" /> </form> <br /> Mineral prices are empire averages from <a href="http://www.eve-central.com/">EVE-Central</a>. </body> </html> END exit; } # Load mineral prices my $trit = $cgi->param('trit') || user_error('No tritanium price'); my $pyer = $cgi->param('pyer') || user_error('No pyerite price'); my $mexa = $cgi->param('mexa') || user_error('No mexallon price'); my $isog = $cgi->param('isog') || user_error('No isogen price'); my $nocx = $cgi->param('nocx') || user_error('No nocxium price'); my $zydr = $cgi->param('zydr') || user_error('No zydrine price'); my $mega = $cgi->param('mega') || user_error('No megacyte price'); my $morp = $cgi->param('morp') || user_error('No morphite price'); my $db = DBI->connect(@dbparams) or die("Database connection failure: $DBI::errstr"); # Strip out line endings $str_items =~ s/[\n\r]+//g; # If the items string contains the contract info too, strip it out $str_items = $1 if ($str_items =~ /The container .+ contains the following items:(.+)/); $str_items = $1 if ($str_items =~ /(.+)Are you sure you want to continue?/); my @item_names = split(/\s*,\s*/, $str_items); # SQL fragment to match all items my $sql_typenames = ''; $sql_typenames = 'types.typeName = ?' if ($#item_names >= 0); $sql_typenames .= " OR types.typeName = ?" foreach (1..$#item_names); # SQL lookup for reprocessing amounts my $sql_reprocess = <<END; SELECT types.typeID, types.typeName, groups.groupName, attrs.valueInt, -- metaLevel types.basePrice, graphics.icon, SUM(CASE WHEN m1.requiredTypeID = 34 THEN m1.quantity ELSE 0 END), -- [Tritanium] SUM(CASE WHEN m1.requiredTypeID = 35 THEN m1.quantity ELSE 0 END), -- [Pyerite] SUM(CASE WHEN m1.requiredTypeID = 36 THEN m1.quantity ELSE 0 END), -- [Mexallon] SUM(CASE WHEN m1.requiredTypeID = 37 THEN m1.quantity ELSE 0 END), -- [Isogen] SUM(CASE WHEN m1.requiredTypeID = 38 THEN m1.quantity ELSE 0 END), -- [Nocxium] SUM(CASE WHEN m1.requiredTypeID = 39 THEN m1.quantity ELSE 0 END), -- [Zydrine] SUM(CASE WHEN m1.requiredTypeID = 40 THEN m1.quantity ELSE 0 END), -- [Megacyte] SUM(CASE WHEN m1.requiredTypeID = 11399 THEN m1.quantity ELSE 0 END) -- [Morphite] FROM invTypes types LEFT JOIN dgmTypeAttributes attrs ON types.typeID = attrs.typeID AND attrs.attributeID = 633 INNER JOIN typeActivityMaterials m1 ON types.typeID = m1.typeID INNER JOIN invGroups groups ON types.groupID = groups.groupID INNER JOIN eveGraphics graphics ON types.graphicID = graphics.graphicID WHERE $sql_typenames GROUP BY types.typeID ORDER BY typeName ASC END my $pre_reprocess = $db->prepare($sql_reprocess); # Global statistical vars my ($totalTrit, $totalPyer, $totalMexa, $totalIsog, $totalNocx, $totalZydr, $totalMega, $totalMorp, $totalIsk, $meta0, $meta1, $meta2, $meta3, $meta4, $meta5, $meta6Plus ); # Execute, bring back one row per item my ($tid, $tname, $gname, $meta, $basePrice, $icon, $ttrit, $tpyer, $tmexa, $tisog, $tnocx, $tzydr, $tmega, $tmorp); $pre_reprocess->execute(@item_names) or die("Can't lookup items: $DBI::errstr"); $pre_reprocess->bind_columns(undef, \$tid, \$tname, \$gname, \$meta, \$basePrice, \$icon, \$ttrit, \$tpyer, \$tmexa, \$tisog, \$tnocx, \$tzydr, \$tmega, \$tmorp); my $item_lookup = {}; my @output = (); while ($pre_reprocess->fetch()) { my $item = {}; my $isk = ($trit * $ttrit) + ($pyer * $tpyer) + ($mexa * $tmexa) + ($isog * $tisog) + ($nocx * $tnocx) + ($zydr * $tzydr) + ($mega * $tmega) + ($morp * $tmorp); my $repDetails = sprintf( "Trit=%s Py=%s Mex=%s Iso=%s Nocx=%s " . "Zyd=%s Mega=%s Morp=%s Isk=%s", pretty_numbers( $ttrit ), pretty_numbers( $tpyer ), pretty_numbers( $tmexa ), pretty_numbers( $tisog ), pretty_numbers( $tnocx ), pretty_numbers( $tzydr ), pretty_numbers( $tmega ), pretty_numbers( $tmorp ), pretty_numbers( $isk ) ); # End statistics. $totalTrit += $ttrit; $totalPyer += $tpyer; $totalMexa += $tmexa; $totalIsog += $tisog; $totalNocx += $tnocx; $totalZydr += $tzydr; $totalMega += $tmega; $totalMorp += $tmorp; $totalIsk += $isk; $meta = 0 unless defined $meta; $item = { id => $tid, name => $tname, meta => $meta, icon => $icon, price => $basePrice, reprocessIsk => $isk, reprocessDetails => $repDetails }; $item_lookup->{$tname} = $item; } # Now match up the item lookups to the input list foreach (sort { lc $a cmp lc $b } @item_names) { push @output, (exists $item_lookup->{$_} ? $item_lookup->{$_} : { name => $_ } ); } my $col = 0; print<<END; <html><head><title>Ramm's RDI's reprocessing tool</title></head> <head> <style type="text/css"> .reg { text-align: center; } </style> </head> <body> <h1>Results</h1> Here is how it works, the colour coding: <ul> <li>Items in <font color='#666600'>dark yellow</font> are meta 0.</li> <li>Items in grey to white are meta 1, 2 or 3.</li> <li>Items in <font color='#4444FF'>blue</font> are meta 4.</li> <li>Items in <font color='#FF0000'>red</font> are T2 (meta 5).</li> <li>items in <font color='#00FF00'>green</font> are above meta 5.</li> </ul> <p /> The number below the item represents the item's value if you would reprocess and sell the minerals on the market. Basically, if you have the option of selling that item for a price below that number, its better to keep the item and reprocess it. (Depending what you need more, mins or isk you are free to sell or reprocess ofcourse.) <p /> As you might see, the items are listed similarly to your inventory in EVE. You will need to sort your inventory window in EVE <b>by name</b> to match. If you have this browser window next to your inventory window, matching the columns(!), it is very easy to pick out those valuable items. <p /> Tip: Because this can be a huge page to load in EVE, resizing might freeze the game a bit.<br /> Also, clicking on the item gives you the general information of that item. It is not the same as clicking 'Show info' on the real item. (For example: the real item might be damaged.)<br /> <a href="http://rammsrdi.com/">Ramm's RDI</a>, or <a href="reproctool.cgi">back</a> to the start page of this tool. <p /> <hr> <p /> <table> END sub pretty_numbers { my $num = shift; $num = int($num); $num = reverse $num; $num =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g; return reverse $num; } my $igb = ($ENV{HTTP_USER_AGENT} =~ /EVE-minibrowser/i); for my $item (@output) { if ($col == $cols) { print "</tr><tr>\n"; $col = 0; } my ($img, $alt, $text, $link, $colour); $alt = $item->{name}; if (defined $item->{id}) { if ($igb) { $img = "typeicon:$item->{id}"; $link = "showinfo:$item->{id}"; } else { $img = "$img_http_path/icons/icons_items_png/64_64/icon$item->{icon}.png"; } switch ($item->{meta}) { case 0 { $colour = "#666600"; $meta0 += 1; } case 1 { $colour = "#777777"; $meta1 += 1; } case 2 { $colour = "#BBBBBB"; $meta2 += 1; } case 3 { $colour = "#FFFFFF"; $meta3 += 1; } case 4 { $colour = "#4444FF"; $meta4 += 1; } case 5 { $colour = "#FF0000"; $meta5 += 1; } case [6..30]{ $colour = "#00FF00"; $meta6Plus += 1; } } if ($item->{meta} >= 4) { $text = $item->{name}; } else { $text = pretty_numbers($item->{reprocessIsk}); } $alt .= " ($item->{reprocessDetails})"; } else { $text = 'Unknown item'; $img = "typeicon:07_15"; } print "<td width='64' class='reg'>"; print "<a href='$link'>" if defined $link; print "<img src='$img' width='64' height='64' border='1' "; print "title=\"$alt\" alt=\"$alt\" />"; print "</a>" if defined $link; print "<br />"; print "<font color='$colour'>" if defined $colour; print $text; print "</font>" if defined $colour; print "</td>\n"; $col++; } print<<END; </tr> </table> <hr> <p /> <h1>Totals</h1> Note: This is assuming you exactly got 1 item stacked per item listed. (This tool does not take the stacked size into account.<br /> END # TODO: df wonders if there is a std::map :) print "Total ISK for raw reprocessed materials: " . pretty_numbers( $totalIsk ) . "<br />\n"; print "<br />Trit: " . pretty_numbers( $totalTrit ) if ($totalTrit>0); print "<br />Py: " . pretty_numbers( $totalPyer ) if ($totalPyer>0); print "<br />Mex: " . pretty_numbers( $totalMexa ) if ($totalMexa>0); print "<br />Iso: " . pretty_numbers( $totalIsog ) if ($totalIsog>0); print "<br />Nox: " . pretty_numbers( $totalNocx ) if ($totalNocx>0); print "<br />Zyd: " . pretty_numbers( $totalZydr ) if ($totalZydr>0); print "<br />Mega: " . pretty_numbers( $totalMega ) if ($totalMega>0); print "<br />Morp: " . pretty_numbers( $totalMorp ) if ($totalMorp>0); print "<br />\n"; print "<br /><font color='#666600'>Meta 0: " . pretty_numbers( $meta0 ) . "</font>" if ($meta0>0); print "<br /><font color='#777777'>Meta 1: " . pretty_numbers( $meta1 ) . "</font>" if ($meta1>0); print "<br /><font color='#BBBBBB'>Meta 2: " . pretty_numbers( $meta2 ) . "</font>" if ($meta2>0); print "<br /><font color='#FFFFFF'>Meta 3: " . pretty_numbers( $meta3 ) . "</font>" if ($meta3>0); print "<br /><font color='#4444FF'>Meta 4: " . pretty_numbers( $meta4 ) . "</font>" if ($meta4>0); print "<br /><font color='#FF0000'>Meta 5: " . pretty_numbers( $meta5 ) . " (T2)</font>" if ($meta5>0); print "<br /><font color='#00FF00'>Meta 6+: " . pretty_numbers( $meta6Plus ) . "</font>" if ($meta6Plus>0); print<<END; <hr> <p /> <h1>Credits</h1> By an idea of <a href="showinfo:1383//1374652644">hfo ohforf</a>, coded by <a href="showinfo:1384//689057791">hfo Omnix</a>. From <a href="showinfo:2//1176688893">Ramm's RDI</a>.<br /> How about you donate 0.1% of your total (which got calucalted at END # TODO: Weird things happen when you use the pretty numbers function here :( (replace int) print int( $totalIsk /1000 ); print<<END ISK) to <a href="showinfo:1386//532549592">hfo</a> which will distribute it towards the creators and corperation of this tool that you are using now :). Thanks! </body> </html> END