public static function similar($item) { //make sure $item is an object if( !($item instanceof Item) ) { if( is_integer($item) ) { $item = Item::getByID($item); } else { return false; } } $CHARADD = .1;//each matching characteristic = .1 $CATADD = .01;//each matching category level = .01 $VOADD = .025;//a user viewed one and ordered other = .025 $UGTMADD = -.35;//more unmatched characteristics than matched = -.35 $NOMATCHTOPLVLADD = -.15;//top level category doesn't match = -.15 $chars = Base::toArray($item->characteristics); $views = Base::toArray(View::getByItem($item->itemid)); //yes that's right, go get ALL of the items that have ANY of the characteristics $items = array(); foreach( $chars as $char ) { $itms = Base::toArray(Item::getByCharacteristic($char->characteristicid)); $items = array_merge($items, $itms); } //now go get all the items in the category chain $numbers = explode('.', $item->category->number); $itms = array(); while( count($numbers) > 0 ) { $newtms = Base::toArray(Item::getByCategorySearch(implode('.',$numbers).'%')); //mmm, delicious Newtms. $tmp = array(); foreach( $newtms as $i ) { //disallow the same item if( $i->itemid != $item->itemid ) { //just push the ids now, so the array_diff doesn't choke array_push($tmp, $i->itemid); } } $itms = array_merge($itms, array_diff($tmp, $itms)); array_pop($numbers); } //itemset is all chars + all categories foreach( $itms as $num ) { //go get all the items and push them onto the itemlist array_push($items, Item::getByID($num)); } $similarities = array(); foreach( $items as $itm ) { $charcount['num'] = 0; $charcount['match'] = 0; $itch = Base::toArray($itm->characteristics); foreach( $itch as $ch ) { if( in_array($ch, $chars) ) { $charcount['match']++; } $charcount['num']++; } $itmNum = explode('.', $item->category->number); $thisNum = explode('.', $itm->category->number); $catcount['topmatch'] = false; $catcount['num'] = 0; $catcount['match'] = 0; for($i = 0; $i<count($itmNum); $i++) { if( $itmNum[$i] == $thisNum[$i] ) { if( $i == 0 ) { $catcount['topmatch'] = true; } $catcount['match']++; } $catcount['num']++; } $similarity = 0; if( ($charcount['num'] / 2) > $charcount['match'] ) { $similarity += $UGTMADD; } if( !$catcount['topmatch'] ) { $similarity += $NOMATCHTOPLVLADD; } $similarity += ($CATADD * $catcount['match']); $similarity += ($CHARADD * $charcount['match']); $similarities = array_merge($similarities, array($itm->itemid => array("itemid" => $itm->itemid, "characteristic" => $charcount, "category" => $catcount, "similarity" => $similarity))); } if(usort($similarities, array(Predict, 'sortSimilarities'))) { return $similarities; } else { return false; } }