#1470 base class update; AVL trees added; some cleanup

--HG--
branch : gsoc2012-achievements
This commit is contained in:
SirCotare 2012-07-01 20:04:01 +02:00
parent a02851452b
commit ad0bbe922f
19 changed files with 579 additions and 69 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 KiB

View file

@ -0,0 +1,329 @@
<?php
class AVLTree {
private $root;
private $debug;
function AVLTree($log = false) {
$this->root = null;
$this->debug = $log;
}
function preorder() {
$this->AVLpreorder($this->root);
}
private function AVLpreorder($p) {
if($p != null) {
echo $p->getID().", ";
$this->AVLpreorder($p->getLeft());
$this->AVLpreorder($p->getRight());
}
}
function inorder() {
#echo "<br>inorder: ";
$this->AVLinorder($this->root);
}
private function AVLinorder($p) {
if($p != null) {
$this->AVLinorder($p->getLeft());
echo $p->getID().", ";
$this->AVLinorder($p->getRight());
}
}
function insert($node) {
if($this->root == null) {
$this->root = new AVLTreeNode($node);
}
else {
$this->root = $this->AVLinsert($this->root,new AVLTreeNode($node));
}
}
function remove($id) {
$n = $this->AVLfind($id,$this->root);
if($n != null) {
$this->AVLremove($this->root,$n);
return $n->getNode();
}
return null;
}
function find($id) {
#echo "<br>search!";
$res = $this->AVLfind($id,$this->root);
if($res != null) {
return $res->getNode();
}
return null;
}
private function AVLfind($id,$n) {
#echo "<br>".$id;
if($n != null) {
#echo "<br>searching for ".$id." compare to ".$n->getID();
if($n->getID() != $id) {
if($n->getID() > $id) {
$n = $this->AVLfind($id,$n->getLeft());
}
else {
$n = $this->AVLfind($id,$n->getRight());
}
}
}
return $n;
}
private function AVLremove($r,$n) {
if($n->getLeft() == null || $n->getRight() == null) {
$s = $n;
}
else {
$s = $this->Successor($n);
$n->setNode($r->getNode());
}
if($r->getLeft() != null) {
$p = $s->getLeft();
}
else {
$p = $s->getRight();
}
if($p != null) {
$p->setParent($s->getParent());
}
if($r->getParent() == null) {
$r = $p;
}
else {
$tmp = $s->getParent();
if($s == $tmp->getLeft()) {
$tmp->setLeft($p);
}
else {
$tmp->setRight($p);
}
}
return $r;
}
private function AVLinsert($r,$n) {
if($r == null) {
$r = $n;
}
else {
if($n->getID() < $r->getID()) {
$r->setLeft($this->AVLinsert($r->getLeft(),$n));
$r = $this->balance($r);
}
elseif($n->getID() > $r->getID()) {
$r->setRight($this->AVLinsert($r->getRight(),$n));
$r = $this->balance($r);
}
$r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1);
}
return $r;
}
private function balance($r) {
if($r->bal() == -2) {
$lc = $r->getLeft();
if($lc->getHeightLeft() >= $lc->getHeightRight()) {
$r = $this->RotateToRight($r);
}
else {
$r = $this->DoubleRotateLeftRight($r);
}
}
if($r->bal() == 2) {
$rc = $r->getRight();
if($rc->getHeightRight() >= $rc->getHeightLeft()) {
$r = $this->RotateToLeft($r);
}
else {
$r = $this->DoubleRotateRightLeft($r);
}
}
return $r;
}
private function Successor($r) {
#echo "succ: ".$r->getID();
if($r->getRight() != null) {
return $this->Minimum($r->getRight());
}
else {
$n = $r->getParent();
while($n != null && $r == $n->getRight()) {
$r = $n;
$n = $n->getParent();
}
return $n;
}
}
private function Minimum($r) {
if($r == null) {
return null;
}
if($r->getLeft() == null) {
return $r;
}
$p = $r->getLeft();
while($p->getLeft() != null) {
$p = $p->getLeft();
}
return $p;
}
private function RotateToRight($r) {
if($this->debug) {
echo "rotaRight<br>";
}
$v = $r->getLeft();
$r->setLeft($v->getRight());
$v->setRight($r);
$r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1);
$v->setHeight(max($v->getHeightLeft(),$r->getHeight())+1);
return $v;
}
private function DoubleRotateLeftRight($r) {
$r->setLeft($this->RotateToLeft($r->getLeft()));
return $this->RotateToRight($r);
}
private function RotateToLeft($r) {
if($this->debug) {
echo "rotaLeft<br>";
}
$v = $r->getRight();
$r->setRight($v->getLeft());
$v->setLeft($r);
$r->setHeight(max($r->getHeightLeft(),$r->getHeightRight())+1);
$v->setHeight(max($v->getHeightRight(),$r->getHeight())+1);
return $v;
}
private function DoubleRotateRightLeft($r) {
$r->setRight($this->RotateToRight($r->getRight()));
return $this->RotateToLeft($r);
}
}
class AVLTreeNode {
private $height;
private $left;
private $right;
private $node;
private $parent;
function AVLTreeNode($node) {
$this->height = 0;
$this->left = null;
$this->right = null;
$this->node = $node;
$this->parent = null;
}
function getParent() {
return $this->parent;
}
function setParent($p) {
$this->parent = $p;
}
function getNode() {
return $this->node;
}
function getLeft() {
return $this->left;
}
function getRight() {
return $this->right;
}
function getHeightLeft() {
if($this->left == null) {
return -1;
}
return $this->left->getHeight();
}
function getHeightRight() {
if($this->right == null) {
return -1;
}
return $this->right->getHeight();
}
function bal() {
$r = -1;
$l = -1;
if($this->right != null) {
$r = $this->right->getHeight();
}
if($this->left != null) {
$l = $this->left->getHeight();
}
return ($r-$l);
}
function getID() {
return $this->node->getID();
}
function getHeight() {
return $this->height;
}
function setHeight($h) {
$this->height = $h;
}
function setRight($r) {
$this->right = $r;
if($r != null) {
$r->setParent($this);
}
}
function setLeft($l) {
$this->left = $l;
if($l != null) {
$l->setParent($this);
}
}
function setNode($n) {
$this->node = $n;
}
}
?>

View file

@ -1,6 +1,6 @@
<?php
class AchAchievement extends AchList {
use Node;
use Node,InDev;
protected $parent_id;
protected $category;
@ -10,7 +10,6 @@
protected $image;
protected $name;
protected $template;
protected $dev;
function AchAchievement($data,$parent) {
global $DBc,$_USER;
@ -74,22 +73,22 @@
$val = 0;
$iter = $this->getDone();
while($iter->hasNext()) {
$curr = $this->findNodeIdx($iter->getNext());
$curr = $this->getChildByIdx($iter->getNext());
$val += $curr->getValue();
}
return $val;
}
function getValueOpen() {
$iter = $this->getDone();
$iter = $this->getOpen();
if($iter->hasNext()) {
$curr = $this->findNodeIdx($iter->getNext());
$curr = $this->getChildByIdx($iter->getNext());
return $curr->getValue();
}
return 0;
}
function getTemplate($insert = array()) {
function fillTemplate($insert = array()) {
if($this->template == null) {
return implode(";",$insert);
}
@ -103,9 +102,14 @@
return $tmp;
}
}
function inDev() {
return ($this->dev == 1);
function getTemplate() {
return $this->template;
}
function getCategory() {
return $this->category;
}
}
?>

View file

@ -27,13 +27,95 @@
$this->child_done[] = $this->addChild($n);
}
function removeChild() {
$idx = $this->getIdx($id);
if($idx != null) {
unset($this->child_open[$idx]);
unset($this->child_done[$idx]);
parent::removeIdx($idx);
final function setChildDone($idx) {
$this->addChildDone($idx);
$this->removeChildOpen($idx);
}
final function addChildDone($idx) {
echo "try adding done child: ".$idx;
if(!in_array($idx,$this->child_done)) {
$this->child_done[] = $idx;
echo " ... done<br>";
}
echo var_export($this->child_done,true);
}
final function removeChildDone($idx) {
echo "try removing done child: ".$idx;
#$res = array_search($idx,$this->child_done);
#if($res != false) {
# unset($this->child_done[$res]);
# echo " ... done<br>";
#}
foreach($this->child_done as $key=>$elem) {
if($elem == $idx) {
unset($this->child_done[$key]);
echo " ... done<br>";
break;
}
}
echo var_export($this->child_done,true);
}
final function setChildOpen($idx) {
$this->addChildOpen($idx);
$this->removeChildDone($idx);
}
final function addChildOpen($idx) {
echo "try adding open child: ".$idx;
if(!in_array($idx,$this->child_open)) {
$this->child_open[] = $idx;
echo " ... done<br>";
}
echo var_export($this->child_open,true);
}
final function removeChildOpen($idx) {
echo "try removing open child: ".$idx;
#$res = array_search($idx,$this->child_open);
#if($res != false) {
# unset($this->child_open[$res]);
# echo " ... done<br>";
#}
foreach($this->child_open as $key=>$elem) {
if($elem == $idx) {
unset($this->child_open[$key]);
echo " ... done<br>";
break;
}
}
echo var_export($this->child_open,true);
}
/*final function unsetOpen($idx) {
foreach($this->child_open as $key=>$elem) {
if($elem == $idx) {
unset($this->child_open[$key]);
break;
}
}
}
final function unsetDone($idx) {
foreach($this->child_done as $key=>$elem) {
if($elem == $idx) {
unset($this->child_done[$key]);
break;
}
}
}*/
#OVERRIDE Parentum::removeChild()
function removeChild($id) {
$n = parent::removeChild($id);
if($n != false && $n != null) {
unset($this->child_open[$n->getIdx()]);
unset($this->child_done[$n->getIdx()]);
}
return $n;
}
}
?>

View file

@ -13,21 +13,21 @@
$this->open = $open;
// the summary page is autogenerated and has no database entry. We add it manually here.
$tmp = array();
/*$tmp = array();
$tmp['ac_id'] = 0;
$tmp['ac_parent'] = null;
$tmp['acl_name'] = get_translation('ach_summary',$_USER->getLang());
$tmp['ac_image'] = "test.png";
$tmp['ac_order'] = -1;
$tmp['open'] = $open;
$this->nodes[] = new AchMenuNode($tmp,$this);
$this->addChild(new AchMenuNode($tmp,$this));*/
$res = $DBc->sqlQuery("SELECT * FROM ach_category LEFT JOIN (ach_category_lang) ON (acl_lang='".$_USER->getLang()."' AND acl_category=ac_id) WHERE ac_parent IS NULL ORDER by ac_order ASC, acl_name ASC");
$sz = sizeof($res);
for($i=0;$i<$sz;$i++) {
$res[$i]['open'] = $open;
$this->nodes[] = $this->makeChild($res[$i]);
$this->addChild($this->makeChild($res[$i]));
}
}

View file

@ -60,6 +60,10 @@
return $this->name;
}
function getDisplayName() {
return $this->parent->fillTemplate(explode(";",$this->name));
}
function getDisplay() {
return $this->display;
}

View file

@ -1,12 +1,13 @@
<?php
class AchPerk extends Parentum {
use Node;
use Node,InDev;
protected $achievement;
protected $value;
protected $name;
protected $done;
protected $dev;
protected $template;
protected $parent_id;
function AchPerk($data,$parent) {
global $DBc,$_USER;
@ -18,6 +19,8 @@
$this->name = $data['apl_name'];
$this->done = $data['app_date'];
$this->dev = $data['ap_dev'];
$this->template = $data['apl_template'];
$this->parent_id = $data['ap_parent'];
$res = $DBc->sqlQuery("SELECT * FROM ach_objective LEFT JOIN (ach_objective_lang) ON (aol_lang='".$_USER->getLang()."' AND aol_objective=ao_id) LEFT JOIN (ach_player_objective) ON (apo_objective=ao_id AND apo_player='".$_USER->getID()."') LEFT JOIN (ach_achievement) ON (aa_id=ao_metalink) WHERE ao_perk='".$this->id."'");
$sz = sizeof($res);
@ -38,8 +41,12 @@
return $this->value;
}
function getDisplayName() {
return $this->parent->fillTemplate(explode(";",$this->name));
}
function getName() {
return $this->parent->getTemplate(explode(";",$this->name));
return $this->name;
}
function objDrawable() {
@ -62,8 +69,34 @@
return $this->done;
}
function inDev() {
return ($this->dev == 1);
function fillTemplate($insert = array()) {
if($this->template == null) {
return implode(";",$insert);
}
else {
$tmp = $this->template;
$match = array();
preg_match_all('#\[([0-9]+)\]#', $this->template, $match);
foreach($match[0] as $key=>$elem) {
$tmp = str_replace("[".$match[1][$key]."]",$insert[$key],$tmp);
}
return $tmp;
}
}
function getTemplate() {
return $this->template;
}
function getParentID() {
return $this->parent_id;
}
function setParentID($p) {
if($this->parent_id != null) {
}
$this->parent_id = $p;
}
}
?>

View file

@ -17,6 +17,8 @@
for($i=0;$i<$sz;$i++) {
$this->addDone($this->makeChild($res[$i]));
}
#echo var_export($this->child_done,true);
}
protected function makeChild($a) {
@ -31,11 +33,15 @@
$iter = $this->menu->getIterator();
while($iter->hasNext()) {
#echo "1";
$curr = $iter->getNext();
if($curr->getID() == 0 || $curr->inDev()) {
continue; // skip summary page
}
#echo $curr->getID().",";
#echo var_export($curr,true);
$res = $this->sumStats($curr);
$this->stats[] = array($curr->getName(),$res[0],$res[1]);
}
@ -47,6 +53,10 @@
private function sumStats(&$node) {
global $DBc,$_USER;
#return array(0,0);
#echo ">".gettype($node)."<";
$done = 0;
$total = 0;
@ -62,7 +72,7 @@
while($iter->hasNext()) {
$curr = $iter->getNext();
$res = $this->sumStats($elem);
$res = $this->sumStats($curr);
$done += $res[0];
$total += $res[1];
}

View file

@ -0,0 +1,13 @@
<?php
trait InDev {
protected $dev;
function inDev() {
return ($this->dev == 1);
}
function getDev() {
return $this->dev;
}
}
?>

View file

@ -1,5 +1,6 @@
<?php
trait Node {
protected $idx;
protected $id;
protected $parent;
@ -7,15 +8,23 @@
return $this->id;
}
final function getIdx() {
return $this->idx;
}
final function getParent() {
return $this->parent;
}
final protected function setID($id) {
final function setIdx($i) {
$this->idx = $i;
}
final function setID($id) {
$this->id = $id;
}
final protected function setParent($p) {
final function setParent($p) {
$this->parent = $p;
}
}

View file

@ -4,10 +4,21 @@
This class allows external access to the child-node list.
Use the NodeIterator to iterate through the list since
the numeric array keys might have gaps due to node removals!
Once init() has been called, an AVLTree is used to support the
functions removeChild() and findChild(). init() must be called
before adding any nodes!
---------------------------*/
protected $nodes = array();
protected $avl = null;
abstract protected function makeChild($args); // overwriteable child generator; allows to define child type (eg.: admin classes that inherit base class)
protected function init() {
#echo "init()";
$this->nodes = array();
$this->avl = new AVLTree();
}
abstract protected function makeChild($args); // overwriteable child generator; allows to define child type (eg.: admin classes that inherit from base class)
final function getSize() {
return sizeof($this->nodes);
@ -23,46 +34,59 @@
final function addChild($n) {
$tmp = sizeof($this->nodes);
$n->setIdx($tmp);
$this->nodes[] = $n;
if($this->avl != null) {
$this->avl->insert($n);
}
return $tmp;
}
#function drawTree() {
# $this->avl->inorder();
#}
function removeChild($id) {
$this->removeIdx($this->getIdx($id));
}
function removeNode($n) {
$this->removeIdx($this->findNode($n));
}
final protected function removeIdx($idx) {
if($idx != null) {
unset($this->nodes[$idx]);
if($this->isEmpty()) {
return null;
}
}
final protected function findNode($n) {
foreach($this->nodes as $key=>$elem) {
if($this->nodes[$key] === $n) {
return $key;
if($this->avl == null) {
return false;
}
$n = $this->avl->remove($id);
#echo var_export($n,true);
if($n != null) {
if($n->getIdx() != null) {
unset($this->nodes[$n->getIdx()]);
}
return $n;
}
return null;
}
final protected function findNodeIdx($idx) {
final function getChildByID($id) {
if($this->isEmpty()) {
return null;
}
if($this->avl == null) {
return false;
}
#$this->avl->inorder();
return $this->avl->find($id);
}
final function getChildByIdx($idx) {
if($this->isEmpty()) {
return null;
}
return $this->nodes[$idx];
}
final protected function getIdx($id) {
foreach($this->nodes as $key=>$elem) {
if($elem->getID() == $id) {
return $key;
}
}
return null;
}
}
?>

View file

@ -7,7 +7,7 @@
}
function getID() {
return 1;
return $this->data["id"];
}
function getLang() {

View file

@ -182,7 +182,7 @@
$iter = $cat->getDone();
while($iter->hasNext()) {
$curr = $cat->findNodeIdx($iter->getNext());
$curr = $cat->getChildByIdx($iter->getNext());
#$sz = sizeof($tmp);
#for($i=0;$i<$sz;$i++) {
#echo "A";
@ -194,14 +194,14 @@
$iter = $cat->getOpen();
while($iter->hasNext()) {
$curr = $cat->findNodeIdx($iter->getNext());
$curr = $cat->getChildByIdx($iter->getNext());
#$sz = sizeof($tmp);
#for($i=0;$i<$sz;$i++) {
#echo "B";
if($curr->inDev()) {
continue;
}
$html .= ach_render_achievement_open($curr));
$html .= ach_render_achievement_open($curr);
}
return $html;
@ -259,7 +259,7 @@
$html = "";
$perk_list = $ach->getOpen();
$perk = $ach->findNodeIdx($perk_list->getNext());
$perk = $ach->getChildByIdx($perk_list->getNext());
if($perk->inDev()) {
return $html;
@ -269,7 +269,7 @@
$html .= "<tr><td><font color='#999999' size='12px'><b>".$perk->getName()."</b></font></td></tr><tr><td>&nbsp;</td></tr>";
}
if($perk->objDrawable()) {
$html .= "<tr><td>".ach_render_obj_list($perk->getChildren())."</td></tr>";
$html .= "<tr><td>".ach_render_obj_list($perk->getIterator())."</td></tr>";
}
return $html;
@ -281,7 +281,7 @@
$perk_list = $ach->getDone();
while($perk_list->hasNext()) {
$perk = $this->findNodeIdx($perk_list->getNext());
$perk = $ach->getChildByIdx($perk_list->getNext());
#foreach($perk_list as $elem) {
#$perk = $ach->getChild($elem);
@ -294,7 +294,7 @@
return $html;
}
function ach_render_obj_list(&$obj) {
function ach_render_obj_list($obj) {
$html = "<table width='90%'>";
$i = 0;

View file

@ -195,7 +195,7 @@
$iter = $cat->getDone();
while($iter->hasNext()) {
$curr = $cat->findNodeIdx($iter->getNext());
$curr = $cat->getChildByIdx($iter->getNext());
#$sz = sizeof($tmp);
#for($i=0;$i<$sz;$i++) {
#echo "A";
@ -207,14 +207,14 @@
$iter = $cat->getOpen();
while($iter->hasNext()) {
$curr = $cat->findNodeIdx($iter->getNext());
$curr = $cat->getChildByIdx($iter->getNext());
#$sz = sizeof($tmp);
#for($i=0;$i<$sz;$i++) {
#echo "B";
if($curr->inDev()) {
continue;
}
$html .= ach_render_achievement_open($curr));
$html .= ach_render_achievement_open($curr);
}
return $html;
@ -295,7 +295,7 @@
$html = "";
$perk_list = $ach->getOpen();
$perk = $ach->findNodeIdx($perk_list->getNext());
$perk = $ach->getChildByIdx($perk_list->getNext());
#$perk = $ach->getChild($perk_list[0]);
@ -319,7 +319,7 @@
$perk_list = $ach->getDone();
while($perk_list->hasNext()) {
$perk = $this->findNodeIdx($perk_list->getNext());
$perk = $ach->getChildByIdx($perk_list->getNext());
#foreach($perk_list as $elem) {
#$perk = $ach->getChild($elem);
if($perk->inDev()) {
@ -331,7 +331,7 @@
return $html;
}
function ach_render_obj_list(&$obj) {
function ach_render_obj_list($obj) {
$html = "<center><table width='90%'>";
$i = 0;

View file

@ -21,6 +21,7 @@ $user['race'] = "r_matis";
$user['civilization'] = "c_neutral";
$user['cult'] = "c_neutral";
$user['ig'] = ($_REQUEST['ig']==1);
#$user['ig'] = true;
require_once("class/RyzomUser_class.php");
$_USER = new RyzomUser($user);
@ -33,6 +34,7 @@ else {
}
require_once("include/ach_render_common.php");
require_once("class/AVLTree_class.php");
require_once("class/Parentum_abstract.php");
require_once("class/AchList_abstract.php");
require_once("class/Tieable_inter.php");
@ -50,8 +52,8 @@ require_once("class/AchObjective_class.php");
// Update user acces on Db
//$db = ryDB::getInstance(APP_NAME);
$DBc = ryDB::getInstance("ahufler");
$DBc = ryDB::getInstance(APP_NAME);
#$DBc = ryDB::getInstance("ahufler");
if(!$_USER->isIG && $_CONF['enable_webig'] == false) {