PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/decision/k6.php

https://bitbucket.org/siosonel/flora
PHP | 311 lines | 190 code | 52 blank | 69 comment | 57 complexity | 16b331583369b9c86ef1a2b8384f5a1f MD5 | raw file
  1. <?php
  2. /*
  3. More intelligent decision engine that uses infrastructure module components
  4. Uses OCAUP accounting by brand
  5. Edgar Sioson
  6. 10/24/2011
  7. */
  8. header("content-type: text/plain");
  9. if ($_POST) $_GET = $_POST;
  10. $ledger = "k6";
  11. $pwd = "k6po";
  12. $IMMED_LOC = 30;
  13. $locBeg = 1;
  14. $pId = 0;
  15. $brandLocs = array(
  16. "abc.org" => array("0001"=>$locBeg+17, "2100"=>$locBeg+18, "2010"=>$locBeg+19, "2001"=>$locBeg+20),
  17. "def.com" => array("0010"=>$locBeg+21, "1200"=>$locBeg+22, "0210"=>$locBeg+23, "0201"=>$locBeg+24),
  18. "ghi.gov" => array("0100"=>$locBeg+25, "1020"=>$locBeg+26, "0120"=>$locBeg+27, "0021"=>$locBeg+28),
  19. "mno.edu" => array("1000"=>$locBeg+29, "1002"=>$locBeg+30, "0102"=>$locBeg+31, "0012"=>$locBeg+32)
  20. );
  21. if ($_GET['maxCycle']) { //set up ledger
  22. postHTTP("http://127.0.0.1/flora/infras/ocaup.php","ledger=$ledger&pwd=$pwd&brandLocs=". urlencode(json_encode($brandLocs)));
  23. exit('{"status":"ok"}');
  24. }
  25. else if (is_numeric($_GET['linearTick'])) {
  26. $locsToCheck = $locBeg+17;
  27. for($i=18; $i<33; $i++) $locsToCheck .= ",". ($locBeg+$i);
  28. //pay wages to location contributors
  29. postHTTP("http://127.0.0.1/flora/infras/ocaup.php","ledger=$ledger&pwd=$pwd&from=locs&locsToCheck=$locsToCheck");
  30. //purchase soon-to-be consumed resources
  31. include "k6_purchase.php"; //print_r($D);
  32. exit(json_encode(array("status"=>"ok", "data"=>$D)));
  33. }
  34. else if (is_numeric($_GET['person_id'])) { //set up activity cycle for person
  35. $person_id = $_GET['person_id'];
  36. include "k6_initCycle.php";
  37. }
  38. else {
  39. $jsondata = file_get_contents("php://input");
  40. $Person = json_decode($jsondata); //print_r($Person);
  41. if (!$Person) exit(json_encode(array("status"=>"error","message"=>$_GET)));
  42. if (is_array($Person->F)) $fitness = floor(array_sum($Person->F)/4);
  43. $fMin = min($Person->F);
  44. $pCache = json_decode(file_get_contents("cache/". $Person->id));
  45. if (!$pCache) exit(json_encode(array("status"=>"error")));
  46. $locRef = json_decode(file_get_contents("cache/k4_locRef"));
  47. $Accts = postHTTP("http://127.0.0.1/flora/infras/ocaup.php?ledger=$ledger&pwd=$pwd&acctId=$Person->id");
  48. if ($Accts->acctId != $Person->id) exit("k6 170: ". json_encode($Accts));
  49. //this part adjusts a person's cycle if the person's token balance falls below a certain amount
  50. //which indicates that the person produces something that is not selling
  51. /*if ($Accts->balance < 200) {
  52. $mostQty = 0;
  53. //determine what resource this person uses a lot
  54. foreach($pCache->interrupts AS $rId=>$qty) {
  55. if ($qty > $mostQty) {
  56. $mostQty = $qty;
  57. $mostUsed = $rId;
  58. }
  59. }
  60. //these are candidate cycle positions representing resources
  61. //that could be swapped for resources that are used more often
  62. $leastUsed = array(15,0,3,6,9,12);
  63. if (!is_array($pCache->swap)) $cyclePos = 15;
  64. else {
  65. foreach($leastUsed AS $pos) {
  66. if (!in_array($cyclePos, $pCache->swap)) {
  67. $cyclePos = $pos;
  68. break;
  69. }
  70. }
  71. }
  72. if ($cyclePos AND $mostUsed) {
  73. $locNum = $rLocs[$mostUsed];
  74. $pCache->cycle[$cyclePos] = array("P", $mostUsed, $pQty, $locNum);
  75. $pCache->cycle[$cyclePos+1] = array("P", $mostUsed, $pQty, $locNum);
  76. $pCache->cycle[$cyclePos+2] = array("C", $mostUsed, $cQty, $locNum);
  77. $pCache->swap[] = $cyclePos;
  78. $pCache->interrupts->$mostUsed=0;
  79. file_put_contents("cache/". $Person->id, json_encode($pCache));
  80. if (!in_array($Person->id, $locRef->$locNum)) array_push($locRef->$locNum, $Person->id);
  81. $cycle = $pCache->cycle;
  82. file_put_contents("cache/". $Person->id, json_encode(array(
  83. "interrupts"=>$pCache->interrupts,
  84. "cycle"=>$cycle,
  85. "swap" =>$pCache->swap
  86. )));
  87. }
  88. } */
  89. if ($fMin < 50) {
  90. $keyMin = array_search($fMin, $Person->F);
  91. $fMax = max($Person->F);
  92. $keyMax = array_search($fMax, $Person->F);
  93. $tempAveF = 0;
  94. //lump personal holding qty's by resource Id, i.e., pool qty's by expiration into one unexpired total
  95. foreach($Person->holding AS $rId => $qtyByExp) { //echo "\n117 $rId $qtyByExp";
  96. $avail = 0;
  97. foreach($qtyByExp AS $exp =>$qty) {
  98. if ($qty) $avail += $qty;
  99. }
  100. if ($avail) $H[] = array("", 0, $rId, $avail);
  101. }
  102. $H = array();
  103. //create a reference array for Person keys, to be used later for conveniently searching for accesible resource locations
  104. //keys format {"keystr1": [ [locId,qty,levels(...)], [...], ..., [...] ], "keystr2": [ [], [], [] ] }
  105. $locKeys = array();
  106. foreach($Person->keys AS $key => $locsArr) {
  107. foreach($locsArr AS $arr) {
  108. if (strpos($arr[2],"r") !== false) $locKeys[ $arr[0] ][] = array($key, $arr[1], $arr[2]);
  109. }
  110. }
  111. //locations to check will be all locations known to decision engine
  112. $locsToCheck = $locBeg;
  113. for($i=1; $i<16; $i++) $locsToCheck .= ",". ($locBeg+$i);
  114. if ($locsToCheck) {
  115. $reply = file_get_contents("http://127.0.0.1/flora/infras/ocaup.php?ledger=$ledger&pwd=$pwd&catalog=all");
  116. $Reply = json_decode($reply);
  117. if ($Reply AND $Reply->catalog) { //Reply->catalog item format: [brand, locId, rsrcId, qty]
  118. foreach($Reply->catalog AS $item) {
  119. if ($item[3] > 0) $H[] = $item;
  120. }
  121. }
  122. }
  123. //find viable options for resource consumption including personal + ** advertised location holdings **
  124. foreach($H AS $arr) {
  125. $to_brand = $arr[0];
  126. $locId = $arr[1];
  127. $rId = $arr[2];
  128. $qty = $arr[3];
  129. $rDigits = str_split($rId,1);
  130. for($i=0; $i<4; $i++) {
  131. if ($rDigits[$i] == 0) $qtyByDigit[$i] = "";
  132. else $qtyByDigit[$i] = floor((99 - $Person->F[$i]) / $rDigits[$i]);
  133. }
  134. for($i=0; $i<4; $i++) {
  135. if ($qtyByDigit[$i] == "") $qtyByDigit[$i] = max($qtyByDigit);
  136. }
  137. $tempQty = min(min($qtyByDigit), $qty);
  138. for($i=0; $i<4; $i++) $tempF[$i] = $Person->F[$i] + $tempQty*$rDigits[$i];
  139. //$currMinF = min($tempF); //echo "\n$rId $tempQty aveF: $currAveF vs $tempAveF ";
  140. $options[min($tempF)][] = array($to_brand, $locId, $rId, $tempQty);
  141. }
  142. //Select from options; if applicable, try to purchase resource
  143. //in contrast to other decision engines, k2 factors access by key and potential reputation/payment constraints
  144. if ($options) {
  145. krsort($options);
  146. foreach($options AS $optGrp) {
  147. foreach($optGrp AS $choice) {
  148. $to_brand = $choice[0];
  149. $locId = $choice[1];
  150. $rId = $choice[2];
  151. $qty = $choice[3];
  152. if (!$to_brand) { //indicates personal holding
  153. $bestLoc = "";
  154. $bestHeld = $rId;
  155. $rQty = $qty;
  156. break 2;
  157. }
  158. else {
  159. foreach($locKeys AS $key=> $locArr) {
  160. foreach($locArr AS $locNum => $accessInfo) {
  161. if ($locId == $locNum) { //see if person already has access to location by key
  162. if (strpos($accessInfo[2],"r") !== false) { //see if access level includes resource removal privileges
  163. if ($accessInfo[1] == "*" OR $accessInfo[1] >= $choice[2]) {
  164. $bestLoc = $locNum;
  165. $bestHeld = $rId;
  166. $rQty = $qty;
  167. break 2;
  168. }
  169. else {
  170. $claimKey = $accessInfo[0];
  171. $tempQty = $qty - $accessInfo[1];
  172. }
  173. } else {echo "\nk6 215"; print_r($accessInfo);}
  174. }
  175. }
  176. }
  177. if (!$rQty) {
  178. if (!$tempQty) $tempQty = $qty;
  179. $balance = 0;
  180. $from_brand = '';
  181. if (is_object($Accts->balance)) {
  182. foreach($Accts->balance AS $fbrand => $bal) { $fBrandList[] = $fbrand;
  183. if ($bal > $balance) {
  184. $balance = $bal;
  185. $from_brand = $fbrand;
  186. }
  187. }
  188. }
  189. if ($balance >= $tempQty AND $from_brand) { //pay for access
  190. $bestLoc = $locId;
  191. $bestHeld = $rId;
  192. $rQty = $tempQty; //not tempQty since tempQty just tops off existing remover access
  193. //submit request to flora to grant key-based access to locations
  194. if (!$claimKey) $claimKey = mt_rand(0,1000) ."_". $Person->id;
  195. $keyInfo = array($claimKey, $locId, $rQty, "r");
  196. $context = stream_context_create(array("http"=>array(
  197. "timeout" => 1,
  198. "content" => json_encode(array("$locId" => array("remover" => array( $claimKey=> $rQty))))
  199. )));
  200. $reply = file_get_contents("http://127.0.0.1/flora/loc.php",false,$context); $locReply = json_decode($reply);
  201. if (!$locReply OR $locReply->status != "ok") echo "\n247 $reply";
  202. //debit and credit accounts
  203. postHTTP("http://127.0.0.1/flora/infras/ocaup.php","ledger=$ledger&pwd=$pwd&from=$from_brand&from_acct=".$Person->id."&to=$to_brand&amount=$tempQty&locQty=$locId,$rQty");
  204. break 2;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }
  211. //prepare decision response
  212. if ($bestHeld AND $rQty AND $rQty > 0) {
  213. $act = array("C","$bestHeld",$rQty,$bestLoc);
  214. $pCache->interrupts->$bestHeld += $rQty;
  215. file_put_contents("cache/". $Person->id, json_encode($pCache));
  216. //to-do: submit key to allow person to remove quantity from a location
  217. }
  218. else {
  219. $act = $pCache->cycle[$Person->currTick];
  220. }
  221. $D = array("person_id" => $Person->id, "act" => $act, "key" => $keyInfo, "cycle" => $cycle);
  222. }
  223. else {
  224. $act = $pCache->cycle[$Person->currTick];
  225. $D = array("person_id" => $Person->id, "act" => $act);
  226. }
  227. if (!$act) $D = array("person_id" => $Person->id, "act" => $pCache->cycle[$Person->currTick]);
  228. }
  229. echo json_encode(array("status"=>"ok", "data"=> $D));//, "jsondata"=> $jsondata));
  230. if ($_GET['test'] AND $D['act'][0] == "C") {
  231. echo "\n\nOld fitness: ". json_encode($Person->F);
  232. echo "\nNew fitness: ";
  233. $i=0;
  234. foreach($Person->F AS $f) {
  235. echo $f + $D['act'][2]*substr($D['act'][1],$i,1) ." ";
  236. $i++;
  237. }
  238. }
  239. function postHTTP($url, $data='') {
  240. if ($data) $context = stream_context_create(array("http" => array("timeout"=>1,"content"=>$data,"method" => "POST")));
  241. else $context = stream_context_create(array("http" => array("timeout"=>1,"content"=>"","method" => "POST")));
  242. $reply = file_get_contents($url,false,$context);
  243. $Reply = json_decode($reply);
  244. if (!$Reply OR $Reply->status != "ok") {
  245. echo "\ntrace: $trace "; global $Accts; print_r($Accts); global $from_brand; echo " $from_brand "; global $to_brand ; echo " $to_brand "; global $fBrandList; print_r($fBrandList);
  246. exit("300 k6 call to $url: ". $reply ." --$fbrand-- $data ");
  247. }
  248. return $Reply;
  249. }
  250. ?>