1<?php 2/** 3 * pData - Simplifying data population for pChart 4 * @copyright 2008 Jean-Damien POGOLOTTI 5 * @version 2.0 6 * 7 * http://pchart.sourceforge.net 8 * 9 * This program is free software: you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation, either version 1,2,3 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23require_once dirname(__FILE__).'/DataDescription.php'; 24require_once dirname(__FILE__).'/CSVImporter.php'; 25 26class pData { 27 private $Data = array(); 28 private $dataDescription = array(); 29 30 /** 31 * An entry for each series giving the maximum value in that 32 * series, if we've previously calculated it 33 */ 34 private $seriesMinimums = array(); 35 36 /** 37 * An entry for each series giving the minimum value in that 38 * series, if we've previously calculated it 39 */ 40 private $seriesMaximums = array(); 41 42 public function __construct() { 43 $this->dataDescription = new DataDescription('Name', 44 'number', 'number', 45 null, null); 46 } 47 48 /** 49 * Add a single point to the data set 50 */ 51 public function addPoint($value, $series = "Series1", $Description = "") { 52 if (is_array($value)) { 53 throw new InvalidArgumentException("Can't pass an array to addPoint()"); 54 } 55 56 return $this->addPoints(array($value), 57 $series, 58 $Description); 59 } 60 61 /** 62 * Add an array of one or more points to the data set. 63 * 64 * @param $Value If this is an associative array the key values 65 * are ignored. The members of the array are added sequentially to 66 * the data set, taking on auto-incremented ID values based on the 67 * current state of the data set. 68 */ 69 public function addPoints(array $Value, $Serie = "Series1", $Description = "") { 70 $ID = 0; 71 for($i = 0; $i < count ( $this->Data ); $i ++) { 72 if (isset ( $this->Data [$i] [$Serie] )) { 73 $ID = $i + 1; 74 } 75 } 76 77 foreach ( $Value as $Val ) { 78 $this->Data [$ID] [$Serie] = $Val; 79 if ($Description != "") { 80 $this->Data[$ID]["Name"] = $Description; 81 } 82 elseif (! isset ( $this->Data [$ID] ["Name"] )) { 83 $this->Data [$ID] ["Name"] = $ID; 84 } 85 $ID ++; 86 } 87 } 88 89 public function addSeries($SerieName = "Series1") { 90 if (!isset($this->dataDescription->values)) { 91 $this->dataDescription->values[] = $SerieName; 92 } else { 93 $Found = FALSE; 94 foreach ( $this->dataDescription->values as $Value ) 95 if ($Value == $SerieName) { 96 $Found = TRUE; 97 } 98 99 if (! $Found) 100 $this->dataDescription->values[] = $SerieName; 101 } 102 } 103 104 public function addAllSeries() { 105 unset($this->dataDescription->values); 106 107 if (isset ( $this->Data [0] )) { 108 foreach (array_keys($this->Data [0]) as $Key) { 109 if ($Key != "Name") { 110 $this->dataDescription->values[] = $Key; 111 } 112 } 113 } 114 } 115 116 public function removeSeries($SerieName = "Series1") { 117 if (! isset($this->dataDescription->values)) 118 return; 119 120 foreach ( $this->dataDescription->values as $key => $Value ) { 121 if ($Value == $SerieName) 122 unset ( $this->dataDescription->values[$key] ); 123 } 124 } 125 126 public function setAbscissaLabelSeries($seriesName = "Name") { 127 $this->dataDescription->setPosition($seriesName); 128 } 129 130 public function setSeriesName($Name, $SeriesName = "Series1") { 131 $this->dataDescription->description[$SeriesName] = $Name; 132 } 133 134 public function setXAxisName($Name) { 135 $this->dataDescription->setXAxisName($Name); 136 } 137 138 public function setYAxisName($Name) { 139 $this->dataDescription->setYAxisName($Name); 140 } 141 142 public function setSeriesSymbol($Name, $Symbol) { 143 $this->dataDescription->seriesSymbols[$Name] = $Symbol; 144 } 145 146 /** 147 * @param unknown_type $SerieName 148 */ 149 public function removeSeriesName($SerieName) { 150 if (isset ( $this->dataDescription->description[$SerieName] )) 151 unset ( $this->dataDescription->description[$SerieName] ); 152 } 153 154 public function removeAllSeries() { 155 $this->dataDescription->values = array(); 156 } 157 158 public function getData() { 159 return $this->Data; 160 } 161 162 public function getDataDescription() { 163 return $this->dataDescription; 164 } 165 166 /** 167 * @brief Get the minimum data value in the specified series 168 */ 169 public function getSeriesMin($seriesName) { 170 if (isset($this->seriesMinimums[$seriesName])) { 171 return $this->seriesMinimums[$seriesName]; 172 } 173 174 /** 175 * @todo This algorithm assumes that the data set contains a 176 * value at index 0 for the specified series - but this is the 177 * way it's always worked. 178 */ 179 $this->seriesMinimums[$seriesName] = $this->Data[0][$seriesName]; 180 181 foreach ($this->Data as $valueSet) { 182 if (isset($valueSet[$seriesName])) { 183 $this->seriesMinimums[$seriesName] = 184 min($this->seriesMinimums[$seriesName], 185 $valueSet[$seriesName]); 186 } 187 } 188 189 return $this->seriesMinimums[$seriesName]; 190 } 191 192 /** 193 * @brief Get the maximum data value in the specified series 194 */ 195 public function getSeriesMax($seriesName) { 196 $this->seriesMaximums[$seriesName] = $this->Data[0][$seriesName]; 197 198 foreach ($this->Data as $valueSet) { 199 if (isset($valueSet[$seriesName])) { 200 $this->seriesMaximums[$seriesName] = 201 max($this->seriesMaximums[$seriesName], 202 $valueSet[$seriesName]); 203 } 204 } 205 206 return $this->seriesMaximums[$seriesName]; 207 } 208 209 /** 210 * Get the numeric X and Y values, for a given series. 211 * 212 * Ugly interface, but this is a step towards refactoring 213 * duplicated code 214 * 215 * For some reason, the data set is assumed to start at (0, 0). 216 * 217 * @param[out] $xIn Returns an array of numeric X values 218 * @param[out] $yIn Returns an array of Y values, corresponding 219 * to the array of X values. Non-numeric values are omitted 220 * 221 * @param $index Returns the number of values in the specified 222 * data set, including any non-numeric values (thus this is not 223 * necessarily equal to the size of the $xIn or $yIn arrays), minus 224 * one (to account for the bogus (0, 0) value added to the X and Y 225 * arrays?) 226 * 227 * @param $missing Returns the X values for which no Y value is 228 * available. The missing keys form the keys of the $missing array, 229 * and the corresponding value in the associative array is always 230 * true 231 * 232 * @return Null 233 */ 234 public function getXYMap($colName, array &$xIn, array & $yIn, array & $missing, & $index) { 235 $xIn [0] = 0; 236 $yIn [0] = 0; 237 238 $index = 1; 239 240 foreach (array_keys($this->Data) as $Key) { 241 if (isset ( $this->Data[$Key] [$colName] )) { 242 $Value = $this->Data[$Key] [$colName]; 243 $xIn [$index] = $index; 244 $yIn [$index] = $Value; 245 if (! is_numeric ( $Value )) { 246 $missing [$index] = TRUE; 247 } 248 $index ++; 249 } 250 } 251 $index --; 252 } 253}