<?php

class cs6120_cf
{
    var 
$db_connect_id null;
    var 
$is_connected false;

    function 
cs6120_cf($dbhost$dbuser$dbpasswd$dbname)
    {
        
$this->db_connect_id mysql_connect($dbhost$dbuser$dbpasswd);
        if(
$this->db_connect_id)
        {
            
$dbselect mysql_select_db($dbname);
            if(!
$dbselect)
            {
                
mysql_close($this->db_connect_id);
                return 
false;
            }
            
$this->is_connected true;
            return 
$this->db_connect_id;
        }
        else
        {
            return 
false;
        }
    }
    
    
// Get the k nearest users to active user a_id.
    // Optionally, the set is confined to those who have rated item i_id. 
    // In this case, the neighbour's rating for i_id is included in the result.    
    
function get_k_nearest_users($k$user_id$i_id null)
    {
        
// Check arguments
        
if (!isset($user_id) || !is_numeric($user_id) || 
            !isset(
$k) || !is_numeric($k) || $k 1)
        {
            return 
false;
        }
        if (isset(
$i_id) && !is_numeric($i_id))
        {
            return 
false;
        }    
        
// k nearest neighbours
        
$knn = array();
        
        
// Retrieve all users who have at least one co-rated item in common with $user_id and,
        // optionally, have rated item $i_id
        
$sql = <<<EOF
SELECT b_user_id b_id, a_b_sim, a_mean, b_mean
FROM user_sims
WHERE a_user_id = 
{$user_id}
EOF;
        if (isset(
$i_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND b_user_id IN
(SELECT user_id FROM ratings WHERE item_id = 
{$i_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such user, decide whether they are a member of the knn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together
            
$sim $srow['a_b_sim'];
            
$b_id $srow['b_id'];
            
$a_mean $srow['a_mean'];
            
$b_mean $srow['b_mean'];
            
$candidate = array('u_id' => $b_id'a_u_sim' => $sim,
                
'a_mean' => $a_mean'u_mean' => $b_mean);
            
// If we only want nbrs who have rated i_id, include b_id's rating for i_id 
            
if (isset($i_id))
            {
                
$candidate['u_i_rating'] = 
                    
$this->get_rating($b_id$i_id);
            }
            
// Possibly insert this candidate into the top k
            
$knn[count($knn)] = $candidate;
            
$last_idx count($knn) - 1;
            if (
count($knn) > $k)
            {
                for (
$i 0$i $last_idx$i++)
                {
                    if (
$knn[$i]['a_u_sim'] < $knn[$last_idx]['a_u_sim'])
                    {
                        
$temp $knn[$i];
                        
$knn[$i] = $knn[$last_idx];
                        
$knn[$last_idx] = $temp;
                    }
                }
                unset(
$knn[$last_idx]);
            }
        }
        
mysql_free_result($sresult);
        return 
$knn;
    }
    
    
// Get the users who are more than $threshold similar to active user a_id.
    // Optionally, the set is confined to those who have rated item i_id. 
    // In this case, the neighbour's rating for i_id is included in the result.    
    
function get_thresholded_nearest_users($threshold$user_id$i_id null)
    {
        
// Check arguments
        
if (!isset($user_id) || !is_numeric($user_id) || 
            !isset(
$threshold) || !is_numeric($threshold) ||
            
$threshold < -1.0 || $threshold 1.0)
        {
            return 
false;
        }
        if (isset(
$i_id) && !is_numeric($i_id))
        {
            return 
false;
        }    
        
// thresholded nearest neighbours
        
$nn = array();
        
        
// Retrieve all users who have at least one co-rated item in common with $user_id and,
        // optionally, have rated item $i_id
        
$sql = <<<EOF
SELECT b_user_id b_id, a_b_sim, a_mean, b_mean
FROM user_sims
WHERE a_user_id = 
{$user_id}
EOF;
        if (isset(
$i_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND b_user_id IN
(SELECT user_id FROM ratings WHERE item_id = 
{$i_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such user, decide whether they are a member of the nn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together and into $nn if its sim to $user_id is high enough
            
$sim $srow['a_b_sim'];
            if (
$sim $threshold)
            {
                
$b_id $srow['b_id'];
                
$a_mean $srow['a_mean'];
                
$b_mean $srow['b_mean'];
                
$candidate = array('u_id' => $b_id'a_u_sim' => $sim,
                    
'a_mean' => $a_mean'u_mean' => $b_mean);
                
// If we only want nbrs who have rated i_id, include b_id's rating for i_id 
                
if (isset($i_id))
                {
                    
$candidate['u_i_rating'] = 
                        
$this->get_rating($b_id$i_id);
                }
                
$nn[] = $candidate;
            }
        }
        
mysql_free_result($sresult);
        return 
$nn;
    }
    
    
// Get the k nearest users to active user a_id that are more than $threshold similar to $a_id.
    // Optionally, the set is confined to those who have rated item i_id. 
    // In this case, the neighbour's rating for i_id is included in the result.    
    
function get_k_thresholded_nearest_users($k$threshold$user_id$i_id null)
    {
        
// Check arguments
        
if (!isset($user_id) || !is_numeric($user_id) || 
            !isset(
$k) || !is_numeric($k) || $k ||
            !isset(
$threshold) || !is_numeric($threshold) ||
            
$threshold < -1.0 || $threshold 1.0)
        {
            return 
false;
        }
        if (isset(
$i_id) && !is_numeric($i_id))
        {
            return 
false;
        }    
        
// k nearest neighbours
        
$knn = array();
        
        
// Retrieve all users who have at least one co-rated item in common with $user_id and,
        // optionally, have rated item $i_id
        
$sql = <<<EOF
SELECT b_user_id b_id, a_b_sim, a_mean, b_mean
FROM user_sims
WHERE a_user_id = 
{$user_id}
EOF;
        if (isset(
$i_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND b_user_id IN
(SELECT user_id FROM ratings WHERE item_id = 
{$i_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such user, decide whether they are a member of the knn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together and possibly into $knn if its sim to $user_id is high enough
            
$sim $srow['a_b_sim'];
            if (
$sim $threshold)
            {
                
$b_id $srow['b_id'];
                
$a_mean $srow['a_mean'];
                
$b_mean $srow['b_mean'];
                
$candidate = array('u_id' => $b_id'a_u_sim' => $sim,
                    
'a_mean' => $a_mean'u_mean' => $b_mean);
                
// If we only want nbrs who have rated i_id, include b_id's rating for i_id 
                
if (isset($i_id))
                {
                    
$candidate['u_i_rating'] = 
                        
$this->get_rating($b_id$i_id);
                }
                
// Possibly insert this candidate into the top k
                
$knn[count($knn)] = $candidate;
                
$last_idx count($knn) - 1;
                if (
count($knn) > $k)
                {
                    for (
$i 0$i $last_idx$i++)
                    {
                        if (
$knn[$i]['a_u_sim'] < $knn[$last_idx]['a_u_sim'])
                        {
                            
$temp $knn[$i];
                            
$knn[$i] = $knn[$last_idx];
                            
$knn[$last_idx] = $temp;
                        }
                    }
                    unset(
$knn[$last_idx]);
                }
            }
        }
        
mysql_free_result($sresult);
        return 
$knn;
    }

    
// Get the k nearest items to item i_id.
    // Optionally, the set is confined to items that have been rated by usr $user_id. 
    // In this case, the user's rating for i_id is included in the result.    
    
function get_k_nearest_items($k$i_id$user_id null)
    {
        
// Check arguments
        
if (!isset($i_id) || !is_numeric($i_id) || 
            !isset(
$k) || !is_numeric($k) || $k 1)
        {
            return 
false;
        }
        if (isset(
$user_id) && !is_numeric($user_id))
        {
            return 
false;
        }    
        
// k nearest neighbours
        
$knn = array();
        
        
// Retrieve all items which have at least one co-rating user in common with $i_id and,
        // optionally, have been rated by user $user_id
        
$sql = <<<EOF
SELECT j_item_id j_id, i_j_sim
FROM item_sims
WHERE i_item_id = 
{$i_id}
EOF;
        if (isset(
$user_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND j_item_id IN
(SELECT item_id FROM ratings WHERE user_id = 
{$user_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such item, decide whether they are a member of the knn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together
            
$sim $srow['i_j_sim'];
            
$j_id $srow['j_id'];
            
$candidate = array('j_id' => $j_id'i_j_sim' => $sim);
            
// If we only want nbrs who have been rated by user_id, include user_id's rating for j_id 
            
if (isset($user_id))
            {
                
$candidate['a_j_rating'] = 
                    
$this->get_rating($user_id$j_id);
            }
            
// Possibly insert this candidate into the top k
            
$knn[count($knn)] = $candidate;
            
$last_idx count($knn) - 1;
            if (
count($knn) > $k)
            {
                for (
$i 0$i $last_idx$i++)
                {
                    if (
$knn[$i]['i_j_sim'] < $knn[$last_idx]['i_j_sim'])
                    {
                        
$temp $knn[$i];
                        
$knn[$i] = $knn[$last_idx];
                        
$knn[$last_idx] = $temp;
                    }
                }
                unset(
$knn[$last_idx]);
            }
        }
        
mysql_free_result($sresult);
        return 
$knn;
    }

    
// Get the items which are more than $threshold similar to item $i_id.
    // Optionally, the set is confined to items that have been rated by usr $user_id. 
    // In this case, the user's rating for i_id is included in the result.    
    
function get_thresholded_nearest_items($threshold$i_id$user_id null)
    {
        
// Check arguments
        
if (!isset($i_id) || !is_numeric($i_id) || 
            !isset(
$threshold) || !is_numeric($threshold) || 
            
$threshold < -1.0 || $threshold 1.0)
        {
            return 
false;
        }
        if (isset(
$user_id) && !is_numeric($user_id))
        {
            return 
false;
        }    
        
// thresholded nearest neighbours
        
$knn = array();
        
        
// Retrieve all items which have at least one co-rating user in common with $i_id and,
        // optionally, have been rated by user $user_id
        
$sql = <<<EOF
SELECT j_item_id j_id, i_j_sim
FROM item_sims
WHERE i_item_id = 
{$i_id}
EOF;
        if (isset(
$user_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND j_item_id IN
(SELECT item_id FROM ratings WHERE user_id = 
{$user_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such item, decide whether they are a member of the nn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together and into $nn if its sim to $i_id is high enough
            
$sim $srow['i_j_sim'];
            if (
$sim $threshold)
            {
                
$j_id $srow['j_id'];
                
$candidate = array('j_id' => $j_id'i_j_sim' => $sim);
                
// If we only want nbrs who have been rated by user_id, include user_id's rating for j_id 
                
if (isset($user_id))
                {
                    
$candidate['a_j_rating'] = 
                        
$this->get_rating($user_id$j_id);
                }
                
$nn[] = $candidate;
            }
        }
        
mysql_free_result($sresult);
        return 
$nn;
    }
    
    
// Get the k nearest items to item i_id that are more than $threshold similar to $i_id.
    // Optionally, the set is confined to items that have been rated by usr $user_id. 
    // In this case, the user's rating for i_id is included in the result.    
    
function get_k_thresholded_nearest_items($k$threshold$i_id$user_id null)
    {
        
// Check arguments
        
if (!isset($i_id) || !is_numeric($i_id) || 
            !isset(
$k) || !is_numeric($k) || $k ||
            !isset(
$threshold) || !is_numeric($threshold) || 
            
$threshold < -1.0 || $threshold 1.0)
        {
            return 
false;
        }
        if (isset(
$user_id) && !is_numeric($user_id))
        {
            return 
false;
        }    
        
// k nearest neighbours
        
$knn = array();
        
        
// Retrieve all items which have at least one co-rating user in common with $i_id and,
        // optionally, have been rated by user $user_id
        
$sql = <<<EOF
SELECT j_item_id j_id, i_j_sim
FROM item_sims
WHERE i_item_id = 
{$i_id}
EOF;
        if (isset(
$user_id))
        {
            
$sql .= ' ';
            
$sql .= <<<EOF
AND j_item_id IN
(SELECT item_id FROM ratings WHERE user_id = 
{$user_id})
EOF;
        }
        
$sql .= ';';
        if ( !(
$sresult mysql_query($sql) ) )
        {
            return 
false;
        }
        
// For each such item, decide whether they are a member of the knn
        
while ($srow mysql_fetch_assoc($sresult)) 
        {
            
//  Put this candidate together and possibly into $knn if its sim to $i_id is high enough
            
$sim $srow['i_j_sim'];
            if (
$sim $threshold)
            {
                
$j_id $srow['j_id'];
                
$candidate = array('j_id' => $j_id'i_j_sim' => $sim);
                
// If we only want nbrs who have been rated by user_id, include user_id's rating for j_id 
                
if (isset($user_id))
                {
                    
$candidate['a_j_rating'] = 
                        
$this->get_rating($user_id$j_id);
                }
                
// Possibly insert this candidate into the top k
                
$knn[count($knn)] = $candidate;
                
$last_idx count($knn) - 1;
                if (
count($knn) > $k)
                {
                    for (
$i 0$i $last_idx$i++)
                    {
                        if (
$knn[$i]['i_j_sim'] < $knn[$last_idx]['i_j_sim'])
                        {
                            
$temp $knn[$i];
                            
$knn[$i] = $knn[$last_idx];
                            
$knn[$last_idx] = $temp;
                        }
                    }
                    unset(
$knn[$last_idx]);
                }
            }
        }
        
mysql_free_result($sresult);
        return 
$knn;
    }
    
    function 
get_user_num_ratings($user_id)
    {
        if (!isset(
$user_id) || !is_numeric($user_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT count(*) AS number_of_ratings
FROM ratings
WHERE user_id = 
{$user_id}
EOF;
        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$row mysql_fetch_assoc($result);
        
$num $row['number_of_ratings'];
        
mysql_free_result($result);
        return 
$num;
    }

    function 
get_user_average_rating($user_id)
    {
        if (!isset(
$user_id) || !is_numeric($user_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT avg(rating) AS average
FROM ratings
WHERE user_id = 
{$user_id}
EOF;

        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$row mysql_fetch_assoc($result);
        
$avg $row['average'];
        
mysql_free_result($result);
        if (
$avg == null)
        {
            return 
0.0;
        }
        return 
$avg;
    }

    function 
get_user_ratings($user_id)
    {
        if (!isset(
$user_id) || !is_numeric($user_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT item_id, rating
FROM ratings
WHERE user_id = 
{$user_id}
EOF;

        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$arr = array();
        while (
$row mysql_fetch_assoc($result))
        {
            
$arr[] = array('item_id' => $row['item_id'], 'rating'=>$row['rating']);
        }
        
mysql_free_result($result);
        return 
$arr;
    }

    function 
get_item_num_ratings($item_id)
    {
        if (!isset(
$item_id) || !is_numeric($item_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT count(*) AS number_of_ratings
FROM ratings
WHERE item_id = 
{$item_id}
EOF;
        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$row mysql_fetch_assoc($result);
        
$num $row['number_of_ratings'];
        
mysql_free_result($result);
        return 
$num;
    }

    function 
get_item_average_rating($item_id)
    {
        if (!isset(
$item_id) || !is_numeric($item_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT avg(rating) AS average
FROM ratings
WHERE item_id = 
{$item_id}
EOF;

        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$row mysql_fetch_assoc($result);
        
$avg $row['average'];
        
mysql_free_result($result);
        if (
$avg == null)
        {
            return 
0.0;
        }
        return 
$avg;
    }

    function 
get_item_ratings($item_id)
    {
        if (!isset(
$item_id) || !is_numeric($item_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT user_id, rating
FROM ratings
WHERE item_id = 
{$item_id}
EOF;

        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$arr = array();
        while (
$row mysql_fetch_assoc($result))
        {
            
$arr[] = array('user_id' => $row['user_id'], 'rating'=>$row['rating']);
        }
        
mysql_free_result($result);
        return 
$arr;
    }
    
    function 
get_rating($user_id$item_id)
    {
        if (!isset(
$user_id) || !is_numeric($user_id) || !isset($item_id) || !is_numeric($item_id))
        {
            return 
false;
        }

        
$sql = <<<EOF
SELECT rating
FROM ratings
WHERE user_id = 
{$user_id}
AND item_id = 
{$item_id}
EOF;
        if ( !(
$result mysql_query($sql)) )
        {
            return 
false;
        }

        
$row mysql_fetch_assoc($result);
        
$rating $row['rating'];
        
mysql_free_result($result);
        return 
$rating;
    }
// end of class

?>