changeset 161:b666a36d7655 misc

Added PHP-based merchant price calculation page kludge.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 30 Dec 2010 01:21:30 +0000
parents 1dcef20c57fd
children 5130fd11e400
files prices.php
diffstat 1 files changed, 627 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/prices.php	Thu Dec 30 01:21:30 2010 +0000
@@ -0,0 +1,627 @@
+<?
+// General settings
+$pageIndex = "prices.php";
+$pageTitle = "Ggr's Merchant Pricelist";
+$pageCharset = "ISO-8859-1";
+
+// Enabled service and product sections
+$sections = array(
+  "services1"  => true,
+  "services2"  => true,
+  "reagents"   => true,
+  "arrows"     => true,
+  "salves"     => true,
+  "potions"    => false,
+);
+
+// Service prices with discount thresholds
+$services1_prices = array(
+  "fw" => array(
+    "name" => "Feather weight",
+    "subj" => "cast",
+    "tresh" => 20,
+    "price1" => 2500,
+    "base" => 10000,
+    "price2" => 1750
+  ),
+  "prot" => array(
+    "name" => "Protect armour/weapon/item",
+    "subj" => "cast",
+    "tresh" => 20,
+    "price1" => 3000,
+    "base" => 10000,
+    "price2" => 2000
+  ),
+  "repair" => array(
+    "name" => "Repair armour/weapon/item",
+    "tresh" => 6,
+    "subj" => "item",
+    "price1" => 10000,
+    "price2" => 7500,
+    "extra" => " + materials"
+  ),
+);
+
+
+// Services without discount threshold
+$services2_prices = array(
+  "labels" => array(
+    "name" => "Labelling",
+    "subj" => "item",
+    "price" => 3000
+  ),
+  "surg80" => array(
+    "name" => "Surgery to 80%",
+    "subj" => "item",
+    "price" => 10000,
+  ),
+  "surg100" => array(
+    "name" => "Surgery to 100", 
+    "subj" => "item",
+    "price" => 15000,
+  ),
+  "mip" => array(
+    "name" => "Money is Power",
+    "subj" => "cast",
+    "price" => 10000,
+  ),
+  "makegear" => array(
+    "name" => "Make mount gear",
+    "subj" => "item",
+    "price" => 20000,
+    "extra" => " + materials",
+  ),
+  "refitgear" => array(
+    "name" => "Refit mount gear",
+    "subj" => "item",
+    "tresh" => -1,
+    "price" => 10000,
+    "extra" => " + materials"
+  ),
+);
+
+
+// Mage reagents
+$reagent_prices = array(
+  "Blast reagents" => array(
+  "acid1" => array("acid", "Acid Blast", "handful of olivine powder", 125),
+  "acid2" => array("acid", "Acid Storm", "pair of interlocked rings", 125),
+
+  "asph1" => array("asph", "Blast Vacuum", "bronze marble", 150),
+  "asph2" => array("asph", "Vacuum Globe", "small fan", 150),
+
+  "elec1" => array("elec", "Electrocution", "small piece of electrum wire", 125),
+  "elec2" => array("elec", "Lightning Storm", "cluster of tungsten wires", 125),
+
+  "cold1" => array("cold", "Cold Ray", "steel arrowhead", 200),
+  "cold2" => array("cold", "Hailstorm", "handful of onyx gravel", 125),
+
+  "pois1" => array("pois", "Summon Carnal Spores", "silvery bark chip", 150),
+  "pois2" => array("pois", "Killing Cloud", "ebony tube", 100),
+
+  "fire1" => array("fire", "Lava Blast", "granite sphere", 125),
+  "fire2" => array("fire", "Lava Storm", "blue cobalt cup", 125),
+
+  "mana1" => array("mana", "Golden Arrow", "copper rod", 125),
+  "mana2" => array("mana", "Magic Eruption", "tiny platinum hammer", 125),
+  ),
+  
+  "Prot reagents" => array(
+  "phys3" => array("phys", "Armour of Aether", "small highsteel disc", 200),
+  "acid3" => array("acid", "Acid Shield", "stone cube", 125),
+  "asph3" => array("asph", "Aura of Wind", "tiny leather bag", 275),
+  "fire3" => array("fire", "Flame Shield", "small glass cone", 150),
+  "cold3" => array("cold", "Frost Shield", "grey fur triangle", 275),
+  "elec3" => array("elec", "Lightning Shield", "small iron rod", 100),
+  "mana3" => array("mana", "Repulsor Aura", "quartz prism", 125),
+  "pois3" => array("pois", "Shield of Detoxification", "tiny amethyst crystal", 125),
+  )
+);
+
+
+// Ammunition
+$arrows = array(
+  "name" => "arrow",
+  "title" => "Ammunition",
+  "desc" => "Only advertised <b>damage types</b> are available. If you want
+other material combos for base ammunition, these may be negotiable. Feel
+free to inquire about other ammunition types (bullets, etc.).
+",
+  "base" => 300,
+  "discount" => true,
+
+  "i_fields" => 2,
+  "i_price" => 2,
+  "i_titles" => array("Type", "Materials", "Price / arrow", "#"),
+  "prices" => array(
+    "phys" => array("Normal (phys)", "ebony, feathers, diamond", 0),
+    "psi"  => array("Psi",    "* + brain",         100),
+    "acid" => array("Acid",   "* + stomach",       100),
+    "elec" => array("Elec",   "* + tungsten",      100),
+    "mana" => array("Mana",   "* + crystalline",   150),
+    "cold" => array("Cold",   "* + ice",           150),
+    "fire" => array("Fire",   "* + fire",          250),
+    "asph" => array("Asphyx", "* + toadstool",     350),
+//    "arr_pois" => array("Poison", "* + h'cliz",        300),
+  )
+);
+
+
+// Salves
+$salves = array(
+  "name" => "salve",
+  "title" => "Salves",
+  "desc" => "All salves sold by me are <b>+25 to stat</b> with <b>10 min</b>
+duration. Salves of same type do not stack, so you can't get +50 or such,
+but different types of salves can be used simultaneously (like int and wis).
+One salve has 4 portions (e.g. 4 uses) and weighs about 1kg.
+<br />
+<b>Salve orders will take some time to complete, I don't keep much stock on these currently.</b>
+",
+  "base" => 4000,
+  "discount" => false,
+
+  "i_fields" => 1,
+  "i_price" => 1,
+  "i_titles" => array("Salve", "Price / piece", "#"),
+  "prices" => array(
+    "str" => array("+str", 0),
+    "con" => array("+con", 0),
+    "int" => array("+int", 0),
+    "wis" => array("+wis", 0),
+    "pack" => array("white cloth pack for holding salves [0/15]", 31000),
+  )
+);
+
+
+// Alchemist potions
+$potions = array(
+  "name" => "potion",
+  "title" => "Alchemist potions",
+  "desc" => "Potion orders have no guaranteed completion time! If you want
+potions sooner rather than later, ask someone else!
+",
+
+  "base" => 5000,
+  "discount" => false,
+
+  "i_fields" => 1,
+  "i_price" => 1,
+  "i_titles" => array("Potion", "Price / piece", "#"),
+  "prices" => array(
+    "generic" => array("Generic potion", 0),
+  ),
+);
+
+
+function convPrice($val)
+{
+  if ($val > 1000000)
+    return round($val / 1000000.0, 4)."M";
+  elseif ($val > 1000)
+    return round($val / 1000.0, 2)."k";
+  else
+    return $val;
+}
+
+
+function getVal($name, &$val) 
+{
+  if (isset($_POST["num_".$name]) && is_numeric($_POST["num_".$name])) {
+    $val = $_POST["num_".$name];
+    if ($val != 0)
+      return TRUE;
+  } else
+    $val = -1;
+
+  return FALSE;
+}
+
+
+function getField($name)
+{
+  if (getVal($name, $val))
+    $s = " value=\"".$val."\"";
+  else
+    $s = "";
+
+  return "<input type=\"text\" name=\"num_".$name."\" size=\"10\" class=\"itext\"".$s." />";
+}
+
+
+function getDiscount($dfield, &$dfactor, &$dstr)
+{
+  $dfactor = 1.0;
+  $dstr = "";
+
+  if (getVal($dfield, $dval)) {
+    addVal($dfield, $dval);
+
+    if ($dval > 0 && $dval <= 100) {
+      $dfactor = $dval / 100.0;
+      $dstr = " [".-(100 - $dval)."%]";
+    } elseif ($dval < 0 && $dval >= -100) {
+      $dfactor = (100 + $dval) / 100.0;
+      $dstr = " [".$dval."%]";
+    }
+  }
+}
+
+
+echo "<?xml version=\"1.0\" encoding=\"".$pageCharset."\"?>";
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=<? echo $pageCharset; ?>" />
+ <title><? echo $pageTitle; ?></title>
+ <style type="text/css">
+ <!--
+ body { background: black; color: white; font-family: Arial, Verdana, sans-serif; font-size: 10pt; }
+ th   { background: gray; }
+
+ table.pritab { width: 70%; }
+ table.pritab tr:hover td { background: green; }
+ tr.a td { background: #333; }
+ tr.b td { background: #444; }
+ 
+ h1,h2,h3,h4  { color: #f00; border-bottom: 1px solid #c00; }
+
+ .phys { color: #ddd; }
+ .fire { color: #f00; }
+ .cold { color: #00f; }
+ .mana { color: #ff0; }
+ .asph { color: #8ff; }
+ .pois { color: #0f0; }
+ .elec { color: #08f; }
+ -->
+ </style>
+</head>
+<body>
+<?
+//============================================================================
+// Data input mode
+//============================================================================
+if (!isset($_POST["ok"])) {
+?>
+<h1><? echo $pageTitle; ?></h1>
+
+<div style="border: 1px solid #0f0; padding: 15px; color: #ff0; text-align: center; font-size: 8pt;">
+<span style="font-size: 20pt;">I do NOT make alchemist potions or rings*, or any SHIP stuff.</span><br />
+<br />
+(*) Well, actually I do make rings, but only for personal amusement. I do
+not wish to spend time trying to come up with some specific ring type.)
+</div>
+
+<form action="<? echo $pageIndex; ?>" method="post" autocomplete="off">
+
+<?
+if ($sections["services1"] || $sections["services2"]) {
+?>
+<h2>Generic services</h2>
+<p>
+As one might expect, <b>I have most of the relevant skills/spells/masteries at 100%</b>.
+</p>
+<table class="pritab">
+<?
+if ($sections["services1"]) {
+foreach ($services1_prices as $key => $item) {
+  $s = isset($item["extra"]) ? $item["extra"] : "";
+  echo
+  " <tr>\n".
+  "  <th>".$item["name"]."</th>\n".
+  "  <th>Cost</th>\n".
+  "  <th>#</th>\n".
+  " </tr>\n".
+  " <tr><td>1-".($item["tresh"]-1)." ".$item["subj"]."s</td><td>".convPrice($item["price1"])." / ".$item["subj"].$s."</td><td>-</td></tr>\n".
+  " <tr><td>".$item["tresh"]."+ ".$item["subj"]."s</td><td>";
+
+  if (isset($item["base"])) {
+    echo convPrice($item["base"])." initial fee + ".convPrice($item["price2"])." / ".$item["subj"].$s;
+  } else {
+    echo convPrice($item["price2"])." / ".$item["subj"].$s;
+  }
+
+  echo "</td><td>".getField($key)."</td>";
+  
+  if (isset($item["extra"])) {
+    echo "<td>+ ".getField($key."_extra")."</td>";
+  }
+  
+  echo "</tr>\n";
+}
+} // services1 enabled
+
+
+if ($sections["services2"]) {
+?>
+ <tr>
+  <th>Service</th>
+  <th>Cost</th>
+  <th>#</th>
+ </tr>
+<?
+foreach ($services2_prices as $key => $item) {
+  echo " <tr><td>".$item["name"]."</td><td>".convPrice($item["price"])." / ".$item["subj"]."</td>".
+  "<td>".getField($key)."</td>";
+
+  if (isset($item["extra"])) {
+    echo "<td>+ ".getField($key."_extra")."</td>";
+  }
+  
+  echo "</tr>\n";
+}
+}
+?>
+</table>
+<p>
+Services total discount %: <? echo getField("services_discount"); ?>
+<br />
+<input type="submit" value=" Calculate " class="isubmit" />
+</p>
+<?
+} // services1 || services2 enabled
+?>
+
+<h2>Power Reagents</h2>
+<p>
+Bulk orders may require time to complete, inquire. I keep some stock on reagents, though.
+</p>
+<table class="pritab">
+<?
+foreach ($reagent_prices as $fkey => $flist) {
+  echo "<tr><th colspan=\"5\">".$fkey."</th></tr>\n".
+  " <tr>\n".
+  "  <th>Type</th>\n".
+  "  <th>Spell</th>\n".
+  "  <th>Reagent</th>\n".
+  "  <th>Price</th>\n".
+  "  <th>#</th>\n".
+  " </tr>";
+  
+  $row = 1;
+  foreach ($flist as $key => $item) {
+    $s = ($row % 2 == 1) ? "a" : "b";
+    echo " <tr class=\"".$s."\"><td class=\"".$item[0]."\">".$item[0].
+    "</td><td>".$item[1]."</td><td>".$item[2]."</td><td>".$item[3]."</td>".
+    "<td>".getField($key)."</td></tr>\n";
+    $row++;
+  }
+}
+?>
+</table>
+<p>
+Reagent total discount %: <? echo getField("reagent_discount"); ?>
+<br />
+<input type="submit" value=" Calculate " class="isubmit" />
+</p>
+
+<?
+function printSection($sec)
+{
+  $name = $sec["name"];
+  
+  echo "<h2>".$sec["title"]."</h2>\n";
+
+  if (isset($sec["desc"]))
+    echo "<p>".$sec["desc"]."</p>\n";
+  
+  echo "<table class=\"pritab\">\n".
+  " <tr>\n";
+  foreach ($sec["i_titles"] as $title)
+    echo "  <th>".$title."</th>\n";
+  echo " </tr>\n";
+
+
+  $base = isset($sec["base"]) ? $sec["base"] : 0;
+  $row = 1;
+  foreach ($sec["prices"] as $key => $item) {
+    $s = ($row % 2 == 1) ? "a" : "b";
+
+    echo " <tr class=\"".$s."\">";
+    
+    for ($i = 0; $i < $sec["i_fields"]; $i++)
+      echo "<td>".$item[$i]."</td>";
+    
+    $add = isset($sec["i_price"]) ? $item[$sec["i_price"]] : 0;
+    
+    echo "<td><b>".($base + $add)."</b></td>".
+    "<td>".getField($name."_".$key)."</td></tr>\n";
+    $row++;
+  }
+
+  echo "</table>\n<p>\n";
+  
+  if ($sec["discount"]) {
+    echo "<p>".$sec["title"]." total discount %: ".
+    getField($name."_discount")."<br />\n".
+    "";
+  }
+
+  echo "<input type=\"submit\" value=\" Calculate \" class=\"isubmit\" />\n".
+  "</p>\n\n";
+}
+
+
+if ($sections["arrows"]) printSection($arrows);
+if ($sections["potions"]) printSection($potions);
+if ($sections["salves"]) printSection($salves);
+
+?>
+<input type="hidden" name="ok" value="ok" />
+</form>
+<?
+
+} else {
+
+//============================================================================
+// Billing result mode
+//============================================================================
+function printLine($name, $num, $price, $header = FALSE)
+{
+  global $billText;
+  $td1 = $header ? "<th>" : "<td>";
+  $td2 = $header ? "</th>" : "</td>";
+
+  echo " <tr>".$td1.$name.$td2.$td1.$num.$td2.$td1."<b>".convPrice($price)."</b>".$td2."</tr>\n";
+
+  $s = sprintf("%-55s | %-6d | %s", $name, $num, convPrice($price));
+  if ($header)
+    $billText .= str_repeat("-", 75)."\n".$s."\n\n";
+  else
+    $billText .= $s."\n";
+}
+
+function addLine($name, $num, $price)
+{
+  global $totalPrice, $subTotal;
+  $totalPrice += $price;
+  $subTotal += $price;
+  printLine($name, $num, $price);
+}
+
+function addVal($key, $val)
+{
+  global $formText;
+  $formText .= "<input type=\"hidden\" name=\"num_".$key."\" value=\"".$val."\" />\n";
+}
+
+
+//============================================================================
+// Services
+//============================================================================
+?>
+<h1>Totals</h1>
+<table class="pritab">
+ <tr>
+  <th>Item</th>
+  <th>#</th>
+  <th>Total</th>
+ </tr>
+<?
+$subTotal = $totalPrice = 0;
+$billText = "";
+$formText = "";
+
+getDiscount("services_discount", $factor, $str);
+
+if ($sections["services1"]) {
+foreach ($services1_prices as $key => $item)
+if (getVal($key, $val)) {
+  addVal($key, $val);
+
+  if ($val >= $item["tresh"]) {
+    if (isset($item["base"]))
+      $total = $item["base"] + ($val * $item["price2"]);
+    else
+      $total = $val * $item["price2"];
+
+    $s = " (discount for >= ".$item["tresh"].")";
+  } else {
+    $total = $val * $item["price1"];
+    $s = "";
+  }
+
+  addLine($item["name"].$s.$str, $val, $total * $factor);
+
+  // Extra does not get discount
+  if (isset($item["extra"]) && getVal($key."_extra", $tmp)) {
+    addVal($key."_extra", $tmp);
+    addLine("|".$item["extra"], $val, $tmp);
+  }
+}
+}
+
+if ($sections["services2"]) {
+foreach ($services2_prices as $key => $item)
+if (getVal($key, $val)) {
+  addVal($key, $val);
+
+  $total = $val * $item["price"];
+
+  addLine($item["name"].$str, $val, $total * $factor);
+
+  // Extra does not get discount
+  if (isset($item["extra"]) && getVal($key."_extra", $tmp)) {
+    addVal($key."_extra", $tmp);
+    addLine("|".$item["extra"], $val, $tmp);
+  }
+}
+}
+
+if ($subTotal > 0)
+  printLine("Services subtotal", "", $subTotal, TRUE);
+
+
+//============================================================================
+// Reagents
+//============================================================================
+if ($sections["reagents"]) {
+getDiscount("reagent_discount", $factor, $s);
+$numReagents = 0;
+$subTotal = 0;
+foreach ($reagent_prices as $fkey => $flist) {
+  foreach ($flist as $key => $item) {
+    if (getVal($key, $val) && $val > 0) {
+      addVal($key, $val);
+      addLine($item[2]." (".$item[1].")".$s, $val, $val * $item[3] * $factor);
+      $numReagents += $val;
+    }
+  }
+}
+if ($numReagents > 0)
+  printLine("Total reagents", $numReagents, $subTotal, TRUE);
+}
+
+//============================================================================
+// Generic sections
+//============================================================================
+function calculateSection($sec)
+{
+  $name = $sec["name"];
+
+  if ($sec["discount"])
+    getDiscount("arrow_discount", $factor, $str);
+  else {
+    $str = "";
+    $factor = 1;
+  }
+  
+  $base = isset($sec["base"]) ? $sec["base"] : 0;
+  $numItems = 0;
+  $subTotal = 0;
+  foreach ($sec["prices"] as $key => $item) {
+    if (getVal($name."_".$key, $val) && $val > 0) {
+      addVal($name."_".$key, $val);
+
+      $add = isset($sec["i_price"]) ? $item[$sec["i_price"]] : 0;
+
+      addLine($item[0]." (".convPrice($base + $add)." / ".$name.")".$str, $val,
+      $val * ($base + $add) * $factor);
+
+      $numItems += $val;
+    }
+  }
+
+  if ($numItems > 0)
+    printLine("Total ".$name."s", $numItems, $subTotal, TRUE);
+}
+
+if ($sections["arrows"]) calculateSection($arrows);
+if ($sections["potions"]) calculateSection($potions);
+if ($sections["salves"]) calculateSection($salves);
+
+echo  "</table>\n".
+"<p>Final total: <b>".$totalPrice."</b> gold (".convPrice($totalPrice).")</p>\n".
+"<hr />\n".
+"<textarea rows=\"15\" cols=\"80\">\n".
+"Services bill\n".
+"=============\n\n".
+addslashes($billText."\nFinal total: ".$totalPrice." gold (".convPrice($totalPrice).")\n").
+"</textarea>\n".
+"<hr />\n<form action=\"".$pageIndex."\" method=\"post\">\n".$formText.
+"<input type=\"submit\" value=\" Back \" class=\"isubmit\" />\n</form>\n";
+}
+?>
+</body>
+</html>