<commit_before><?php
/**
 * File for class Assignment
 *
 * PHP version 5
 *
 * @author <NAME> (<EMAIL>)
 * @copyright Copyright (C) 2014 <NAME>
 * @license <http://www.gnu.org/licenses/agpl-3.0.txt> GNU Affero General Public License v3
 *
 * This file is part of Journal Club Manager.
 *
 * Journal Club Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Journal Club Manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Journal Club Manager.  If not, see <http://www.gnu.org/licenses/>.
 */


/**
 * Class Assignment
 *
 * Class that handles speaker assignment routines
 */
class Assignment extends AppTable {

    /**
     * @var array
     */
    protected $table_data = array(
        "id"=>array("INT NOT NULL AUTO_INCREMENT",false),
        "username"=>array("CHAR(255)",false),
        "primary"=>'id'
    );

    /**
     * @var Session
     */
    private static $session;

    /**
     * Constructor
     * @param AppDb $db
     */
    public function __construct(AppDb $db) {
        parent::__construct($db, 'Assignment', $this->table_data);
        $this->registerDigest();
    }

    /**
     * Check correspondences between table
     */
    public function check() {
        if ($this->db->tableExists($this->tablename)) {
            $this->getSession();
            $this->addSessionType();
            $this->addUsers();
        }
    }

    /**
     * Get user's assignments
     * @param $username
     * @return array
     */
    public function get($username) {
        $sql = "SELECT * FROM {$this->tablename} WHERE username='{$username}'";
        return $this->db->send_query($sql)->fetch_assoc();
    }

    /**
     * Register into DigestMaker table
     */
    public function registerDigest() {
        $DigestMaker = new DigestMaker($this->db);
        $DigestMaker->register(get_class());
    }

    /**
     * Get session instance
     */
    private function getSession() {
        if (is_null(self::$session)) {
            self::$session = new Session($this->db);
        }
        return self::$session;
    }

    /**
     * Beautify session type name
     * @param $string
     * @param bool $encode
     * @return mixed
     */
    public static function prettyName($string, $encode=true) {
        if ($encode) {
            return strtolower(str_replace(" ", "_", $string));
        } else {
            return ucfirst(str_replace("_", " ", $string));
        }
    }

    /**
     * Adds session type to Assignment table
     * @return bool
     */
    private function addSessionType() {
        $AppConfig = new AppConfig($this->db);

        // Get session types
        $session_types = array();
        foreach ($AppConfig->session_type as $type=>$info) {
            $session_types[] = self::prettyName($type, true);
        }

        $reg_types = $this->db->getcolumns($this->tablename);
        $reg_types = array_values(array_diff($reg_types, array_keys($this->table_data)));
        $diff = (array_diff($session_types, $reg_types));

        if (!empty($diff)) {
            foreach ($diff as $type) {
                if (!$this->db->addcolumn($this->tablename, $type, 'INT NOT NULL DEFAULT 0')) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Update members' presentation number based on presentations registered in the Presentation table
     */
    public function getPresentations() {
        // Step 1: get users' presentations sorted by session type
        $sql = "SELECT * FROM " . $this->db->tablesname['Presentation'];
        $req = $this->db->send_query($sql);
        $list = array();

        while ($row = $req->fetch_assoc()) {
            $Session = new Session($this->db, $row['date']);
            if ($Session->type === 'none' || empty($row['orator'])) continue;

            if (!isset($list[$row['orator']][$Session->type])) {
                $list[$row['orator']][$Session->type] = 1;
            } else {
                $list[$row['orator']][$Session->type] += 1;
            }
        }

        // Step 2: update table
        foreach ($list as $username=>$info) {
            foreach ($info as $type=>$value) {
                $type = self::prettyName($type, true);
                var_dump($username, $type, $value);
                $this->db->updatecontent($this->tablename, array($type=>$value), array('username'=>$username));
            }
        }
    }

    /**
     * Add users to assignment table
     *
     * @return bool
     */
    public function addUsers() {
        // Get users list
        $Users = new Users($this->db);
        $usersList = array();
        foreach ($Users->getUsers(false) as $key=>$user) {
            $usersList[] = $user['username'];
        }

        // Get list of users currently registered into the assignment table
        $req = $this->db->send_query("SELECT username FROM {$this->tablename}");
        $data = array();
        while ($row = $req->fetch_assoc()) {
            $data[] = $row;
        }

        $AssignUsers = array();
        foreach ($data as $key=>$user) {
            $AssignUsers[] = $user['username'];
        }

        // Add users to the assignment table if not present yet
        $diff = array_values(array_diff($usersList, $AssignUsers));
        foreach ($diff as $user) {
            if (!$this->db->addcontent($this->tablename, array('username'=>$user))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Get list of assignable users
     *
     * @param string $session_type : session type (pretty formatted: eg. "Journal Club" => "journal_club")
     * @param int $max : maximum number of presentations
     * @param $date: session date
     * @return mixed
     */
    public function getAssignable($session_type, $max, $date) {
        $req = $this->db->send_query("
            SELECT * 
            FROM {$this->tablename} a
            INNER JOIN ".$this->db->tablesname['User']." u
            ON a.username=u.username
            WHERE (a.$session_type<$max)
                AND u.assign=1 AND u.status!='admin'
            ");

        // Check users availability for this day
        $Availability = new Availability($this->db);
        $data = array();
        while ($row = $req->fetch_assoc()) {
            $availability = array();
            foreach ($Availability->get($row['username']) as $key=>$info) {
                $availability[] = $info['date'];
            }
            if (empty($availability) || !in_array($date, $availability)) {
                $data[] = $row;
            }
        }
        return $data;
    }

    /**
     * Get Maximum number of presentations
     *
     * @param $session_type
     * @return mixed
     */
    public function getMax($session_type) {
        $sql = "SELECT MAX($session_type) as maximum FROM $this->tablename";
        $data = $this->db->send_query($sql)->fetch_assoc();
        return (int)$data['maximum'];
    }

    /**
     * Update user's number of presentations
     * @param $session_type
     * @param $speaker
     * @param bool $add: if true, then increase the number of presentations by 1, or decrease by 1 if false
     * @return bool
     */
    public function updateTable($session_type, $speaker, $add=true) {
        if ($session_type === 'none') return true;
        $inc = ($add) ? 1:-1; // increase or decrease number of presentations
        $value = $this->db->send_query("SELECT {$session_type} 
                                        FROM {$this->tablename} 
                                        WHERE username='{$speaker}'")->fetch_array();
        $value = ((int)$value > 0) ? (int)$value[$session_type] + $inc: 0; // Assignment number can be negative
        return $this->db->updatecontent($this->tablename, array($session_type=>$value), array("username"=>$speaker));
    }

    /**
     * Update speaker assignment: update assignment table and notify user
     * @param User $user
     * @param array $info: array('type'=>session_type, 'date'=>session_date, 'presid'=>presentation_id)
     * @param bool $assign : assign (true) or unassign (false) user
     * @param bool $notify: notify user by email
     * @return bool
     */
    public function updateAssignment(User $user, array $info, $assign=true, $notify=false) {
        $session = new Session($this->db, $info['date']);
        if ($this->updateTable(self::prettyName($session->type, true), $user->username, $assign)) {
            if ($notify) {
                $session->notify_session_update($user, $info, $assign);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     *
     * @param null $username
     * @return mixed
     */
    public function makeMail($username=null) {
        $user = new User($this->db, $username);
        $content['body'] = $user->getAssignments(true, $username);;
        $content['title'] = 'Your assignments';
        return $content;
    }

    /**
     * Returns all list of members with their corresponding number of assignments per sessions type
     * (used in admin>assignments page)
     * @return string
     */
    public function showAll() {
        $data = $this->all();
        return self::showList($data);
    }

    /**
     * Renders members list and their corresponding number of assignments per sessions type
     * @param array $data
     * @return string
     */
    public static function showList(array $data) {
        $content = "";
        $headers = array_diff(array_keys($data[0]), array('id', 'fullname', 'username'));
        foreach ($data as $key=>$info) {
            $content .= self::showSingle($info, $headers);
        }
        
        $headings = "";
        foreach ($headers as $heading) {
            $headings .= "<div>" . self::prettyName($heading, false) . "</div>";
        }
        
        return "
        <div class='table_container'>
            <div class='list-heading'>
                <div>Name</div>
                {$headings}
            </div>
            {$content}
        </div>
        ";
    }

    /**
     * Renders member's number of assignments per sessions type
     * @param array $info
     * @param array $session_types
     * @return string
     */
    public static function showSingle(array $info, array $session_types) {
        $session_type = "";
        foreach ($session_types as $heading) {
            $session_type .= "<div>{$info[$heading]}</div>";
        }
        return "
            <div class='list-container'>
                <div>{$info['fullname']}</div>   
                {$session_type}
            </div>";
    }

}<commit_msg>removed var_dump<commit_after><?php
/**
 * File for class Assignment
 *
 * PHP version 5
 *
 * @author <NAME> (<EMAIL>)
 * @copyright Copyright (C) 2014 <NAME>
 * @license <http://www.gnu.org/licenses/agpl-3.0.txt> GNU Affero General Public License v3
 *
 * This file is part of Journal Club Manager.
 *
 * Journal Club Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Journal Club Manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Journal Club Manager.  If not, see <http://www.gnu.org/licenses/>.
 */


/**
 * Class Assignment
 *
 * Class that handles speaker assignment routines
 */
class Assignment extends AppTable {

    /**
     * @var array
     */
    protected $table_data = array(
        "id"=>array("INT NOT NULL AUTO_INCREMENT",false),
        "username"=>array("CHAR(255)",false),
        "primary"=>'id'
    );

    /**
     * @var Session
     */
    private static $session;

    /**
     * Constructor
     * @param AppDb $db
     */
    public function __construct(AppDb $db) {
        parent::__construct($db, 'Assignment', $this->table_data);
        $this->registerDigest();
    }

    /**
     * Check correspondences between table
     */
    public function check() {
        if ($this->db->tableExists($this->tablename)) {
            $this->getSession();
            $this->addSessionType();
            $this->addUsers();
        }
    }

    /**
     * Get user's assignments
     * @param $username
     * @return array
     */
    public function get($username) {
        $sql = "SELECT * FROM {$this->tablename} WHERE username='{$username}'";
        return $this->db->send_query($sql)->fetch_assoc();
    }

    /**
     * Register into DigestMaker table
     */
    public function registerDigest() {
        $DigestMaker = new DigestMaker($this->db);
        $DigestMaker->register(get_class());
    }

    /**
     * Get session instance
     */
    private function getSession() {
        if (is_null(self::$session)) {
            self::$session = new Session($this->db);
        }
        return self::$session;
    }

    /**
     * Beautify session type name
     * @param $string
     * @param bool $encode
     * @return mixed
     */
    public static function prettyName($string, $encode=true) {
        if ($encode) {
            return strtolower(str_replace(" ", "_", $string));
        } else {
            return ucfirst(str_replace("_", " ", $string));
        }
    }

    /**
     * Adds session type to Assignment table
     * @return bool
     */
    private function addSessionType() {
        $AppConfig = new AppConfig($this->db);

        // Get session types
        $session_types = array();
        foreach ($AppConfig->session_type as $type=>$info) {
            $session_types[] = self::prettyName($type, true);
        }

        $reg_types = $this->db->getcolumns($this->tablename);
        $reg_types = array_values(array_diff($reg_types, array_keys($this->table_data)));
        $diff = (array_diff($session_types, $reg_types));

        if (!empty($diff)) {
            foreach ($diff as $type) {
                if (!$this->db->addcolumn($this->tablename, $type, 'INT NOT NULL DEFAULT 0')) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Update members' presentation number based on presentations registered in the Presentation table
     */
    public function getPresentations() {
        // Step 1: get users' presentations sorted by session type
        $sql = "SELECT * FROM " . $this->db->tablesname['Presentation'];
        $req = $this->db->send_query($sql);
        $list = array();

        while ($row = $req->fetch_assoc()) {
            $Session = new Session($this->db, $row['date']);
            if ($Session->type === 'none' || empty($row['orator'])) continue;

            if (!isset($list[$row['orator']][$Session->type])) {
                $list[$row['orator']][$Session->type] = 1;
            } else {
                $list[$row['orator']][$Session->type] += 1;
            }
        }

        // Step 2: update table
        foreach ($list as $username=>$info) {
            foreach ($info as $type=>$value) {
                $type = self::prettyName($type, true);
                $this->db->updatecontent($this->tablename, array($type=>$value), array('username'=>$username));
            }
        }
    }

    /**
     * Add users to assignment table
     *
     * @return bool
     */
    public function addUsers() {
        // Get users list
        $Users = new Users($this->db);
        $usersList = array();
        foreach ($Users->getUsers(false) as $key=>$user) {
            $usersList[] = $user['username'];
        }

        // Get list of users currently registered into the assignment table
        $req = $this->db->send_query("SELECT username FROM {$this->tablename}");
        $data = array();
        while ($row = $req->fetch_assoc()) {
            $data[] = $row;
        }

        $AssignUsers = array();
        foreach ($data as $key=>$user) {
            $AssignUsers[] = $user['username'];
        }

        // Add users to the assignment table if not present yet
        $diff = array_values(array_diff($usersList, $AssignUsers));
        foreach ($diff as $user) {
            if (!$this->db->addcontent($this->tablename, array('username'=>$user))) {
                return false;
            }
        }
        return true;
    }


    /**
     * Get list of assignable users
     *
     * @param string $session_type : session type (pretty formatted: eg. "Journal Club" => "journal_club")
     * @param int $max : maximum number of presentations
     * @param $date: session date
     * @return mixed
     */
    public function getAssignable($session_type, $max, $date) {
        $req = $this->db->send_query("
            SELECT * 
            FROM {$this->tablename} a
            INNER JOIN ".$this->db->tablesname['User']." u
            ON a.username=u.username
            WHERE (a.$session_type<$max)
                AND u.assign=1 AND u.status!='admin'
            ");

        // Check users availability for this day
        $Availability = new Availability($this->db);
        $data = array();
        while ($row = $req->fetch_assoc()) {
            $availability = array();
            foreach ($Availability->get($row['username']) as $key=>$info) {
                $availability[] = $info['date'];
            }
            if (empty($availability) || !in_array($date, $availability)) {
                $data[] = $row;
            }
        }
        return $data;
    }

    /**
     * Get Maximum number of presentations
     *
     * @param $session_type
     * @return mixed
     */
    public function getMax($session_type) {
        $sql = "SELECT MAX($session_type) as maximum FROM $this->tablename";
        $data = $this->db->send_query($sql)->fetch_assoc();
        return (int)$data['maximum'];
    }

    /**
     * Update user's number of presentations
     * @param $session_type
     * @param $speaker
     * @param bool $add: if true, then increase the number of presentations by 1, or decrease by 1 if false
     * @return bool
     */
    public function updateTable($session_type, $speaker, $add=true) {
        if ($session_type === 'none') return true;
        $inc = ($add) ? 1:-1; // increase or decrease number of presentations
        $value = $this->db->send_query("SELECT {$session_type} 
                                        FROM {$this->tablename} 
                                        WHERE username='{$speaker}'")->fetch_array();
        $value = ((int)$value > 0) ? (int)$value[$session_type] + $inc: 0; // Assignment number can be negative
        return $this->db->updatecontent($this->tablename, array($session_type=>$value), array("username"=>$speaker));
    }

    /**
     * Update speaker assignment: update assignment table and notify user
     * @param User $user
     * @param array $info: array('type'=>session_type, 'date'=>session_date, 'presid'=>presentation_id)
     * @param bool $assign : assign (true) or unassign (false) user
     * @param bool $notify: notify user by email
     * @return bool
     */
    public function updateAssignment(User $user, array $info, $assign=true, $notify=false) {
        $session = new Session($this->db, $info['date']);
        if ($this->updateTable(self::prettyName($session->type, true), $user->username, $assign)) {
            if ($notify) {
                $session->notify_session_update($user, $info, $assign);
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     *
     * @param null $username
     * @return mixed
     */
    public function makeMail($username=null) {
        $user = new User($this->db, $username);
        $content['body'] = $user->getAssignments(true, $username);;
        $content['title'] = 'Your assignments';
        return $content;
    }

    /**
     * Returns all list of members with their corresponding number of assignments per sessions type
     * (used in admin>assignments page)
     * @return string
     */
    public function showAll() {
        $data = $this->all();
        return self::showList($data);
    }

    /**
     * Renders members list and their corresponding number of assignments per sessions type
     * @param array $data
     * @return string
     */
    public static function showList(array $data) {
        $content = "";
        $headers = array_diff(array_keys($data[0]), array('id', 'fullname', 'username'));
        foreach ($data as $key=>$info) {
            $content .= self::showSingle($info, $headers);
        }
        
        $headings = "";
        foreach ($headers as $heading) {
            $headings .= "<div>" . self::prettyName($heading, false) . "</div>";
        }
        
        return "
        <div class='table_container'>
            <div class='list-heading'>
                <div>Name</div>
                {$headings}
            </div>
            {$content}
        </div>
        ";
    }

    /**
     * Renders member's number of assignments per sessions type
     * @param array $info
     * @param array $session_types
     * @return string
     */
    public static function showSingle(array $info, array $session_types) {
        $session_type = "";
        foreach ($session_types as $heading) {
            $session_type .= "<div>{$info[$heading]}</div>";
        }
        return "
            <div class='list-container'>
                <div>{$info['fullname']}</div>   
                {$session_type}
            </div>";
    }

}
{'fraction_non_alphanumeric': 0.1443391565994521, 'fraction_numerical': 0.0022454753671352226, 'mean_word_length': 2.0701778574383014, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 229, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6924065', 'n_tokens_mistral': 6289, 'n_tokens_neox': 6105, 'n_words': 1668}