<commit_before><?php
/*	Project:	EQdkp-Plus
 *	Package:	EQdkp-plus
 *	Link:		http://eqdkp-plus.eu
 *
 *	Copyright (C) 2006-2016 EQdkp-Plus Developer Team
 *
 *	This program 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.
 *
 *	This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

if ( !defined('EQDKP_INC') ){
	die('Do not access this file directly.');
}

if ( !class_exists( "pdh_r_points" ) ) {
	class pdh_r_points extends pdh_r_generic{
		public static $shortcuts = array('apa' => 'auto_point_adjustments');

		public $default_lang = 'english';

		private $cache;
		public $points;
		// initialise array to store multipools which are decayed
		private $decayed = array();
		private $hardcap = array();
		private $arrCalculatedSingle = array();
		private $arrCalculatedMulti = array();
		private $arrSnapshotTime = array();
		private $initiatedMultiPools = array();

		public $hooks = array(
			'adjustment_update',
			'event_update',
			'item_update',
			'member_update',
			'raid_update',
			'multidkp_update',
			'itempool_update',
		);

		public $presets = array(
			'earned' => array('earned', array('%member_id%', '%dkp_id%', 0, '%with_twink%'), array('%dkp_id%')),
			'spent' => array('spent', array('%member_id%', '%dkp_id%', 0, 0, '%with_twink%'), array('%dkp_id%')),
			'adjustment' => array('adjustment', array('%member_id%', '%dkp_id%', 0, '%with_twink%'), array('%dkp_id%')),
			'current' => array('current', array('%member_id%', '%dkp_id%', 0, 0, '%with_twink%'), array('%dkp_id%', false, true)),
			'all_current' => array('current', array('%member_id%', '%ALL_IDS%', 0, 0, '%with_twink%'), array('%ALL_IDS%', true, true)),
		);

		public $detail_twink = array(
			'earned' => 'summed_up',
			'spent' => 'summed_up',
			'adjustment' => 'summed_up',
			'current' => 'summed_up',
		);

		public function reset($affected_ids=array(), $strHook='', $arrAdditionalData=array()){
			$arrTotalAffected = array();

			//For Hooks with additional data
			foreach($arrAdditionalData as $arrData){
				if(isset($arrData['action'])){
					$strAction = $arrData['action'];
					if($strHook == 'member_update' && $strAction == 'update_points') return true;

					if((isset($arrData['apa']) && $arrData['apa']) || ($strAction == 'add' && ($strHook == 'itempool_update' || $strHook == 'multidkp_update' || $strHook == 'member_update'))){
						//Nothing to do with APA or member_cache
					} else {
						$arrAffectedMembers = (isset($arrData['members']) && is_array($arrData['members'])) ? $arrData['members'] : $this->pdh->get('member', 'id_list');
						$intAffectedTime = (isset($arrData['time'])) ? $arrData['time'] : 0;

						$arrTotalAffected = array_merge($arrTotalAffected, $arrAffectedMembers);
						$this->get_delete_from_snapshot($intAffectedTime, $arrAffectedMembers);

						//Reset the APA Cache for the affected members
						$apaAffectedIDs = array();
						foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
							foreach($arrAffectedMembers as $memberid){
								$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
							}
						}
						$this->apa->enqueue_update('current', $apaAffectedIDs);
					}

				}
			}
			if((isset($arrData['apa']) && $arrData['apa']) || ($strAction == 'add' && ($strHook == 'itempool_update' || $strHook == 'multidkp_update' || ($strHook == 'member_update'  && !is_array($affected_ids))))){
				//Nothing to do with APA or member_cache
			} elseif($strHook == 'member_update' && is_array($affected_ids) && count($affected_ids)) {
				$apaAffectedIDs = array();
				$arrTotalAffected = array_merge($arrTotalAffected, $affected_ids);
				foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
					foreach($affected_ids  as $memberid){
						$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
					}
				}
				$this->apa->enqueue_update('current', $apaAffectedIDs);
			} elseif(count($arrAdditionalData) == 0) {
				//Reset the APA Cache for all members
				$apaAffectedIDs = array();
				foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
					foreach($this->pdh->get('member', 'id_list')  as $memberid){
						$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
					}
				}
				$this->apa->enqueue_update('current', $apaAffectedIDs);
				$arrTotalAffected = false;
			}

			$this->pdc->del('pdh_points_snapshot_mapping');
			$this->pdc->del('pdh_points_table');

			//Reset the member point cache for affected members only
			if(is_array($arrTotalAffected)) $arrTotalAffected = array_unique($arrTotalAffected);
			$this->pdh->put('member', 'reset_points', array($arrTotalAffected));

			$this->arrCalculatedMulti = array();
			$this->arrCalculatedSingle = array();
			$this->points = NULL;
			$this->initiatedMultiPools = array();
		}

		public function init() {
			$this->arrSnapshotTime = $this->pdc->get('pdh_points_snapshot_mapping');
			if($this->arrSnapshotTime === NULL){
				$this->snapshot_mapping();
			}
		}
		
		public function _init($multidkp_id){
			if(isset($this->initiatedMultiPools[$multidkp_id])) return;
			$this->initiatedMultiPools[$multidkp_id] = $multidkp_id;
				
			//cached data not outdated?
			$this->points[$multidkp_id] = $this->pdc->get('pdh_points_table_'.$multidkp_id);
			
			if($this->points[$multidkp_id] !== NULL){
				$this->arrCalculatedMulti = array();
				$this->arrCalculatedSingle = array();
				
				return true;
			}
			
			$this->points[$multidkp_id] = $arrLocalPoints = array();			
			$mdkpids = $this->pdh->maget('multidkp', array('event_ids', 'itempool_ids'), 0, array($this->pdh->get('multidkp', 'id_list')));
			
			$arrMultidkpData = $mdkpids[$multidkp_id];
			$dkp_id = $multidkp_id;
			$evip = $arrMultidkpData;

			$raid2event = array();
			
			if((!is_array($evip['event_ids']) || count($evip['event_ids']) < 1) && (!is_array($evip['itempool_ids']) || count($evip['itempool_ids']) < 1)) return;
			//earned
			if(is_array($evip['event_ids'])) {
				foreach($evip['event_ids'] as $event_id) {
					$raid_ids = $this->pdh->get('raid', 'raidids4eventid', array($event_id));
					foreach($raid_ids as $raid_id) {
						$raid2event[$raid_id] = $event_id;
						$attendees = $this->pdh->get('raid', 'raid_attendees', array($raid_id));
						if( !is_array($attendees) ) continue;
						$value = $this->pdh->get('raid', 'value', array($raid_id, $dkp_id));
						foreach($attendees as $attendee){
							if(!isset($arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id]))
								$arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id] = 0;
							$arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id] += $value;
						}
					}
				}
			}
			
			//spent
			if(is_array($evip['itempool_ids'])) {
				foreach($evip['itempool_ids'] as $itempool_id) {
					$item_ids = $this->pdh->get('item', 'item_ids_of_itempool', array($itempool_id));
					if(is_array($item_ids)) {
						foreach($item_ids as $item_id){
							$member_id = $this->pdh->get('item', 'buyer', array($item_id));
							$value = $this->pdh->get('item', 'value', array($item_id, $dkp_id));
							$raid_id = $this->pdh->get('item', 'raid_id', array($item_id));
							if(!isset($arrLocalPoints[$dkp_id])) $arrLocalPoints[$dkp_id] = array();
							if(!isset($arrLocalPoints[$dkp_id][$member_id])) $arrLocalPoints[$dkp_id][$member_id] = array('single' => array('earned' => array(), 'spent' => array()));
							$eventID = (isset($raid2event[$raid_id])) ? $raid2event[$raid_id] : 0;
							if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID])) $arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID] = array();
							
							if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id]))
								$arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id] = 0;
								$arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id] += $value;
						}
					}
				}
			}
			
			//adjustment
			if(is_array($evip['event_ids'])) {
				foreach($evip['event_ids'] as $event_id) {
					$adjustment_ids = $this->pdh->get('adjustment', 'adjsofeventid', array($event_id));
					foreach($adjustment_ids as $adjustment_id) {
						$member_id = $this->pdh->get('adjustment', 'member', array($adjustment_id));
						$value = $this->pdh->get('adjustment', 'value', array($adjustment_id, $dkp_id));
						if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id]))
							$arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id] = 0;
							$arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id] += $value;
					}
				}
			}

			$this->points[$multidkp_id] = $arrLocalPoints[$multidkp_id];
			$this->pdc->put('pdh_points_table_'.$multidkp_id, $arrLocalPoints[$multidkp_id], null);
		}

		public function get_earned($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id])){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['earned'][$event_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['earned'][$event_id];
		}

		public function get_html_earned($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			return '<span class="positive">'.runden($this->get_earned($member_id, $multidkp_id, $event_id, $with_twink)).'</span>';
		}

		public function get_spent($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id]) ){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['spent'][$event_id][$itempool_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['spent'][$event_id][$itempool_id];
		}

		public function get_html_spent($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true){
			return '<span class="negative">'.runden($this->get_spent($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink)).'</span>';
		}

		public function get_adjustment($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id])){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['adjustment'][$event_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['adjustment'][$event_id];
		}

		public function get_html_adjustment($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			return '<span class="'.color_item($this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink)).'">'.runden($this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink)).'</span>';
		}


		/**
		 * Default without APA decay!
		 */
		public function get_current_history($member_id, $multidkp_id, $from=0, $to=PHP_INT_MAX, $event_id=0, $itempool_id=0, $with_twink=true, $blnWithAPA=false){
			if(!isset($this->decayed[$multidkp_id])) $this->decayed[$multidkp_id] = $this->apa->is_decay('current', $multidkp_id);

			if($blnWithAPA && $this->decayed[$multidkp_id]){
				$data =  array(
						'id'			=> $multidkp_id.'_'.$member_id,
						'member_id'		=> $member_id,
						'dkp_id'		=> $multidkp_id,
						'event_id'		=> $event_id,
						'itempool_id'	=> $itempool_id,
						'with_twink'	=> ($with_twink) ? true : false,
						'date'			=> $to,
				);

				$toPoints = $this->apa->get_value('current', $multidkp_id, $to, $data);

				if($from > 0) {
					$fromPoints = $this->apa->get_value('current', $multidkp_id, $from, $data);
					return $toPoints - $fromPoints;
				} else {
					return $toPoints;
				}

			} else {
				$arrPoints = $this->pdh->get('points_history', 'points', array($member_id, $multidkp_id, $from, $to, $event_id, $itempool_id, $with_twink));

				$earned = (float)$arrPoints['earned'][$event_id];
				$spent = (float)$arrPoints['spent'][$event_id][$itempool_id];
				$adj = (float)$arrPoints['adjustment'][$event_id];
				return (float)($earned - $spent + $adj);
			}
		}

		/**
		 * Default with APA decay!
		 */
		public function get_current($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true, $with_apa=true){
			if(!isset($this->decayed[$multidkp_id])) $this->decayed[$multidkp_id] = $this->apa->is_decay('current', $multidkp_id);
			if(!isset($this->hardcap[$multidkp_id])) $this->hardcap[$multidkp_id] = $this->apa->is_hardcap('current_hardcap', $multidkp_id);

			if($with_apa && $this->decayed[$multidkp_id]) {
				$data =  array(
					'id'			=> $multidkp_id.'_'.$member_id,
					'member_id'		=> $member_id,
					'dkp_id'		=> $multidkp_id,
					'event_id'		=> $event_id,
					'itempool_id'	=> $itempool_id,
					'with_twink'	=> ($with_twink) ? true : false,
					'date'			=> $this->time->time,
				);
				$value = $this->apa->get_value('current', $multidkp_id, $this->time->time, $data);
			} else {
				$value = ($this->get_earned($member_id, $multidkp_id, $event_id, $with_twink) - $this->get_spent($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink) + $this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink));
			}

			if($with_apa && $this->hardcap[$multidkp_id]){
				$data =  array(
						'id'			=> $multidkp_id.'_'.$member_id,
						'val'			=> $value,
				);
				$value = $this->apa->get_value('current_cap', $multidkp_id, $this->time->time, $data);
			}
			return $value;
		}

		public function get_html_current($member_id, $multidkp_id,  $event_id=0, $itempool_id=0, $with_twink=true){
			$with_twink = (int)$with_twink;
			$current = $this->get_current($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink);
			return '<span class="'.color_item($current).'">'.runden($current).'</span>';
		}

		public function get_html_caption_current($mdkpid, $showname, $showtooltip, $tt_options = array()){
			if($showname){
				$text = $this->pdh->get('multidkp', 'name', array($mdkpid));
			}else{
				$text = $this->pdh->get_lang('points', 'current');
			}

			if($showtooltip){
				$tooltip = $this->user->lang('events').": <br />";<commit_msg>Fixed current hartcap<commit_after><?php
/*	Project:	EQdkp-Plus
 *	Package:	EQdkp-plus
 *	Link:		http://eqdkp-plus.eu
 *
 *	Copyright (C) 2006-2016 EQdkp-Plus Developer Team
 *
 *	This program 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.
 *
 *	This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

if ( !defined('EQDKP_INC') ){
	die('Do not access this file directly.');
}

if ( !class_exists( "pdh_r_points" ) ) {
	class pdh_r_points extends pdh_r_generic{
		public static $shortcuts = array('apa' => 'auto_point_adjustments');

		public $default_lang = 'english';

		private $cache;
		public $points;
		// initialise array to store multipools which are decayed
		private $decayed = array();
		private $hardcap = array();
		private $arrCalculatedSingle = array();
		private $arrCalculatedMulti = array();
		private $arrSnapshotTime = array();
		private $initiatedMultiPools = array();

		public $hooks = array(
			'adjustment_update',
			'event_update',
			'item_update',
			'member_update',
			'raid_update',
			'multidkp_update',
			'itempool_update',
		);

		public $presets = array(
			'earned' => array('earned', array('%member_id%', '%dkp_id%', 0, '%with_twink%'), array('%dkp_id%')),
			'spent' => array('spent', array('%member_id%', '%dkp_id%', 0, 0, '%with_twink%'), array('%dkp_id%')),
			'adjustment' => array('adjustment', array('%member_id%', '%dkp_id%', 0, '%with_twink%'), array('%dkp_id%')),
			'current' => array('current', array('%member_id%', '%dkp_id%', 0, 0, '%with_twink%'), array('%dkp_id%', false, true)),
			'all_current' => array('current', array('%member_id%', '%ALL_IDS%', 0, 0, '%with_twink%'), array('%ALL_IDS%', true, true)),
		);

		public $detail_twink = array(
			'earned' => 'summed_up',
			'spent' => 'summed_up',
			'adjustment' => 'summed_up',
			'current' => 'summed_up',
		);

		public function reset($affected_ids=array(), $strHook='', $arrAdditionalData=array()){
			$arrTotalAffected = array();

			//For Hooks with additional data
			foreach($arrAdditionalData as $arrData){
				if(isset($arrData['action'])){
					$strAction = $arrData['action'];
					if($strHook == 'member_update' && $strAction == 'update_points') return true;

					if((isset($arrData['apa']) && $arrData['apa']) || ($strAction == 'add' && ($strHook == 'itempool_update' || $strHook == 'multidkp_update' || $strHook == 'member_update'))){
						//Nothing to do with APA or member_cache
					} else {
						$arrAffectedMembers = (isset($arrData['members']) && is_array($arrData['members'])) ? $arrData['members'] : $this->pdh->get('member', 'id_list');
						$intAffectedTime = (isset($arrData['time'])) ? $arrData['time'] : 0;

						$arrTotalAffected = array_merge($arrTotalAffected, $arrAffectedMembers);
						$this->get_delete_from_snapshot($intAffectedTime, $arrAffectedMembers);

						//Reset the APA Cache for the affected members
						$apaAffectedIDs = array();
						foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
							foreach($arrAffectedMembers as $memberid){
								$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
							}
						}
						$this->apa->enqueue_update('current', $apaAffectedIDs);
					}

				}
			}
			if((isset($arrData['apa']) && $arrData['apa']) || ($strAction == 'add' && ($strHook == 'itempool_update' || $strHook == 'multidkp_update' || ($strHook == 'member_update'  && !is_array($affected_ids))))){
				//Nothing to do with APA or member_cache
			} elseif($strHook == 'member_update' && is_array($affected_ids) && count($affected_ids)) {
				$apaAffectedIDs = array();
				$arrTotalAffected = array_merge($arrTotalAffected, $affected_ids);
				foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
					foreach($affected_ids  as $memberid){
						$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
					}
				}
				$this->apa->enqueue_update('current', $apaAffectedIDs);
			} elseif(count($arrAdditionalData) == 0) {
				//Reset the APA Cache for all members
				$apaAffectedIDs = array();
				foreach($this->pdh->get('multidkp', 'id_list') as $mdkpid){
					foreach($this->pdh->get('member', 'id_list')  as $memberid){
						$apaAffectedIDs[] = $mdkpid.'_'.$memberid;
					}
				}
				$this->apa->enqueue_update('current', $apaAffectedIDs);
				$arrTotalAffected = false;
			}

			$this->pdc->del('pdh_points_snapshot_mapping');
			$this->pdc->del('pdh_points_table');

			//Reset the member point cache for affected members only
			if(is_array($arrTotalAffected)) $arrTotalAffected = array_unique($arrTotalAffected);
			$this->pdh->put('member', 'reset_points', array($arrTotalAffected));

			$this->arrCalculatedMulti = array();
			$this->arrCalculatedSingle = array();
			$this->points = NULL;
			$this->initiatedMultiPools = array();
		}

		public function init() {
			$this->arrSnapshotTime = $this->pdc->get('pdh_points_snapshot_mapping');
			if($this->arrSnapshotTime === NULL){
				$this->snapshot_mapping();
			}
		}
		
		public function _init($multidkp_id){
			if(isset($this->initiatedMultiPools[$multidkp_id])) return;
			$this->initiatedMultiPools[$multidkp_id] = $multidkp_id;
				
			//cached data not outdated?
			$this->points[$multidkp_id] = $this->pdc->get('pdh_points_table_'.$multidkp_id);
			
			if($this->points[$multidkp_id] !== NULL){
				$this->arrCalculatedMulti = array();
				$this->arrCalculatedSingle = array();
				
				return true;
			}
			
			$this->points[$multidkp_id] = $arrLocalPoints = array();			
			$mdkpids = $this->pdh->maget('multidkp', array('event_ids', 'itempool_ids'), 0, array($this->pdh->get('multidkp', 'id_list')));
			
			$arrMultidkpData = $mdkpids[$multidkp_id];
			$dkp_id = $multidkp_id;
			$evip = $arrMultidkpData;

			$raid2event = array();
			
			if((!is_array($evip['event_ids']) || count($evip['event_ids']) < 1) && (!is_array($evip['itempool_ids']) || count($evip['itempool_ids']) < 1)) return;
			//earned
			if(is_array($evip['event_ids'])) {
				foreach($evip['event_ids'] as $event_id) {
					$raid_ids = $this->pdh->get('raid', 'raidids4eventid', array($event_id));
					foreach($raid_ids as $raid_id) {
						$raid2event[$raid_id] = $event_id;
						$attendees = $this->pdh->get('raid', 'raid_attendees', array($raid_id));
						if( !is_array($attendees) ) continue;
						$value = $this->pdh->get('raid', 'value', array($raid_id, $dkp_id));
						foreach($attendees as $attendee){
							if(!isset($arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id]))
								$arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id] = 0;
							$arrLocalPoints[$dkp_id][$attendee]['single']['earned'][$event_id] += $value;
						}
					}
				}
			}
			
			//spent
			if(is_array($evip['itempool_ids'])) {
				foreach($evip['itempool_ids'] as $itempool_id) {
					$item_ids = $this->pdh->get('item', 'item_ids_of_itempool', array($itempool_id));
					if(is_array($item_ids)) {
						foreach($item_ids as $item_id){
							$member_id = $this->pdh->get('item', 'buyer', array($item_id));
							$value = $this->pdh->get('item', 'value', array($item_id, $dkp_id));
							$raid_id = $this->pdh->get('item', 'raid_id', array($item_id));
							if(!isset($arrLocalPoints[$dkp_id])) $arrLocalPoints[$dkp_id] = array();
							if(!isset($arrLocalPoints[$dkp_id][$member_id])) $arrLocalPoints[$dkp_id][$member_id] = array('single' => array('earned' => array(), 'spent' => array()));
							$eventID = (isset($raid2event[$raid_id])) ? $raid2event[$raid_id] : 0;
							if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID])) $arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID] = array();
							
							if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id]))
								$arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id] = 0;
								$arrLocalPoints[$dkp_id][$member_id]['single']['spent'][$eventID][$itempool_id] += $value;
						}
					}
				}
			}
			
			//adjustment
			if(is_array($evip['event_ids'])) {
				foreach($evip['event_ids'] as $event_id) {
					$adjustment_ids = $this->pdh->get('adjustment', 'adjsofeventid', array($event_id));
					foreach($adjustment_ids as $adjustment_id) {
						$member_id = $this->pdh->get('adjustment', 'member', array($adjustment_id));
						$value = $this->pdh->get('adjustment', 'value', array($adjustment_id, $dkp_id));
						if(!isset($arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id]))
							$arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id] = 0;
							$arrLocalPoints[$dkp_id][$member_id]['single']['adjustment'][$event_id] += $value;
					}
				}
			}

			$this->points[$multidkp_id] = $arrLocalPoints[$multidkp_id];
			$this->pdc->put('pdh_points_table_'.$multidkp_id, $arrLocalPoints[$multidkp_id], null);
		}

		public function get_earned($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id])){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['earned'][$event_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['earned'][$event_id];
		}

		public function get_html_earned($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			return '<span class="positive">'.runden($this->get_earned($member_id, $multidkp_id, $event_id, $with_twink)).'</span>';
		}

		public function get_spent($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id]) ){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['spent'][$event_id][$itempool_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['spent'][$event_id][$itempool_id];
		}

		public function get_html_spent($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true){
			return '<span class="negative">'.runden($this->get_spent($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink)).'</span>';
		}

		public function get_adjustment($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			if($with_twink){
				if(!isset($this->arrCalculatedMulti[$member_id.'_'.$multidkp_id])){
					$this->calculate_multi_points($member_id, $multidkp_id);
					$this->arrCalculatedMulti[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'multi';
			} else {
				if(!isset($this->arrCalculatedSingle[$member_id.'_'.$multidkp_id])){
					$this->calculate_single_points($member_id, $multidkp_id);
					$this->arrCalculatedSingle[$member_id.'_'.$multidkp_id] = 1;
				}
				$with_twink = 'single';
			}

			if(!isset($this->points[$multidkp_id][$member_id][$with_twink]['adjustment'][$event_id])) return 0;
			return $this->points[$multidkp_id][$member_id][$with_twink]['adjustment'][$event_id];
		}

		public function get_html_adjustment($member_id, $multidkp_id, $event_id=0, $with_twink=true){
			return '<span class="'.color_item($this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink)).'">'.runden($this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink)).'</span>';
		}


		/**
		 * Default without APA decay!
		 */
		public function get_current_history($member_id, $multidkp_id, $from=0, $to=PHP_INT_MAX, $event_id=0, $itempool_id=0, $with_twink=true, $blnWithAPA=false){
			if(!isset($this->decayed[$multidkp_id])) $this->decayed[$multidkp_id] = $this->apa->is_decay('current', $multidkp_id);

			if($blnWithAPA && $this->decayed[$multidkp_id]){
				$data =  array(
						'id'			=> $multidkp_id.'_'.$member_id,
						'member_id'		=> $member_id,
						'dkp_id'		=> $multidkp_id,
						'event_id'		=> $event_id,
						'itempool_id'	=> $itempool_id,
						'with_twink'	=> ($with_twink) ? true : false,
						'date'			=> $to,
				);

				$toPoints = $this->apa->get_value('current', $multidkp_id, $to, $data);

				if($from > 0) {
					$fromPoints = $this->apa->get_value('current', $multidkp_id, $from, $data);
					return $toPoints - $fromPoints;
				} else {
					return $toPoints;
				}

			} else {
				$arrPoints = $this->pdh->get('points_history', 'points', array($member_id, $multidkp_id, $from, $to, $event_id, $itempool_id, $with_twink));

				$earned = (float)$arrPoints['earned'][$event_id];
				$spent = (float)$arrPoints['spent'][$event_id][$itempool_id];
				$adj = (float)$arrPoints['adjustment'][$event_id];
				return (float)($earned - $spent + $adj);
			}
		}

		/**
		 * Default with APA decay!
		 */
		public function get_current($member_id, $multidkp_id, $event_id=0, $itempool_id=0, $with_twink=true, $with_apa=true){
			if(!isset($this->decayed[$multidkp_id])) $this->decayed[$multidkp_id] = $this->apa->is_decay('current', $multidkp_id);
			if(!isset($this->hardcap[$multidkp_id])) $this->hardcap[$multidkp_id] = $this->apa->is_hardcap('current_hardcap', $multidkp_id);

			if($with_apa && $this->decayed[$multidkp_id]) {
				$data =  array(
					'id'			=> $multidkp_id.'_'.$member_id,
					'member_id'		=> $member_id,
					'dkp_id'		=> $multidkp_id,
					'event_id'		=> $event_id,
					'itempool_id'	=> $itempool_id,
					'with_twink'	=> ($with_twink) ? true : false,
					'date'			=> $this->time->time,
				);
				$value = $this->apa->get_value('current', $multidkp_id, $this->time->time, $data);
			} else {
				$value = ($this->get_earned($member_id, $multidkp_id, $event_id, $with_twink) - $this->get_spent($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink) + $this->get_adjustment($member_id, $multidkp_id, $event_id, $with_twink));
			}

			if($with_apa && $this->hardcap[$multidkp_id]){
				$data =  array(
						'id'			=> $multidkp_id.'_'.$member_id,
						'val'			=> $value,
				);
				$value = $this->apa->get_value('current_hardcap', $multidkp_id, $this->time->time, $data);
			}
			return $value;
		}

		public function get_html_current($member_id, $multidkp_id,  $event_id=0, $itempool_id=0, $with_twink=true){
			$with_twink = (int)$with_twink;
			$current = $this->get_current($member_id, $multidkp_id, $event_id, $itempool_id, $with_twink);
			return '<span class="'.color_item($current).'">'.runden($current).'</span>';
		}

		public function get_html_caption_current($mdkpid, $showname, $showtooltip, $tt_options = array()){
			if($showname){
				$text = $this->pdh->get('multidkp', 'name', array($mdkpid));
			}else{
				$text = $this->pdh->get_lang('points', 'current');
			}

			if($showtooltip){
				$tooltip = $this->user->lang('events').": <br />";
{'fraction_non_alphanumeric': 0.19792326199822718, 'fraction_numerical': 0.0035456502469292136, 'mean_word_length': 4.792958004768018, 'pattern_counts': {'":': 2, '<': 29, '<?xml version=': 0, '>': 357, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7661091', 'n_tokens_mistral': 13936, 'n_tokens_neox': 11671, 'n_words': 1762}