These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace smtech\GradingAnalytics\Snapshots; |
||
4 | |||
5 | use smtech\GradingAnalytics\Snapshots\Exception\SnapshotException; |
||
6 | |||
7 | class Snapshot extends CacheableDatabase |
||
8 | { |
||
9 | const NOT_ASSOCIATED_WITH_COURSE = 'n/a'; |
||
10 | |||
11 | /** |
||
12 | * History of the course specified by `$courseOrDepartmentId` in constructor |
||
13 | * @var History |
||
14 | */ |
||
15 | protected $history; |
||
16 | |||
17 | /** |
||
18 | * Department ID given as `$courseOrDepartmentId` in constructor |
||
19 | * @var [type] |
||
20 | */ |
||
21 | protected $departmentId = false; |
||
22 | |||
23 | /** |
||
24 | * The domain of this snapshot |
||
25 | * @var Domain |
||
26 | */ |
||
27 | protected $domain; |
||
28 | |||
29 | /** |
||
30 | * Date timestamp of this snapshot |
||
31 | * @var string |
||
32 | */ |
||
33 | protected $timestamp = false; |
||
34 | |||
35 | /** |
||
36 | * Course statistics records that make up the snapshot |
||
37 | * @var array |
||
38 | */ |
||
39 | protected static $data; |
||
40 | |||
41 | /** |
||
42 | * Averages calculated from the data |
||
43 | * @var array |
||
44 | */ |
||
45 | protected $averages; |
||
46 | |||
47 | public function __construct($databaseProvider, Domain $domain, $courseOrDepartmentId, $isCourseId = true) |
||
48 | { |
||
49 | parent::__construct($databaseProvider); |
||
50 | |||
51 | $this->domain = $domain; |
||
52 | |||
53 | if ($isCourseId) { |
||
54 | $this->history = new History($this, $courseOrDepartmentId); |
||
55 | } elseif (is_numeric($courseOrDepartmentId)) { |
||
56 | $this->departmentId = $courseOrDepartmentId; |
||
57 | } |
||
58 | } |
||
59 | |||
60 | public function getCourseId() |
||
61 | { |
||
62 | if (!empty($this->history)) { |
||
63 | return $this->history->getCourseId(); |
||
64 | } |
||
65 | return self::NOT_ASSOCIATED_WITH_COURSE; |
||
66 | } |
||
67 | |||
68 | public function getDepartmentId() |
||
69 | { |
||
70 | if ($this->departmentId === false) { |
||
71 | $this->departmentId = $this->history->getDepartmentId(); |
||
72 | } |
||
73 | return $this->departmentId; |
||
74 | } |
||
75 | |||
76 | public function getDomain() |
||
77 | { |
||
78 | return $this->domain; |
||
79 | } |
||
80 | |||
81 | public function getTimestamp() |
||
82 | { |
||
83 | if ($this->timestamp === false) { |
||
84 | if (!empty($this->history)) { |
||
85 | $this->timestamp = $this->history->getCurrentTimestamp(); |
||
86 | } else { |
||
87 | if ($response = $this->sql->query(" |
||
88 | SELECT * FROM `course_statistics` |
||
89 | WHERE |
||
90 | `course[account_id]` = '" . $this->getDepartmentId() . "' |
||
91 | ORDER BY |
||
92 | `timestamp` DESC |
||
93 | LIMIT 1 |
||
94 | ")) { |
||
95 | if ($row = $response->fetch_assoc()) { |
||
96 | $this->timestamp = substr($row['timestamp'], 0, 10); |
||
97 | } |
||
98 | } |
||
99 | } |
||
100 | } |
||
101 | return $this->timestamp; |
||
102 | } |
||
103 | |||
104 | public function getAverage(Average $average) |
||
105 | { |
||
106 | if ($this->cacheSnapshot()) { |
||
107 | return $this->averages[$average]; |
||
108 | } |
||
109 | return false; |
||
110 | } |
||
111 | public function getSnapshot($teacherFilter = false) |
||
112 | { |
||
113 | if ($this->domain == Domain::COURSE()) { |
||
114 | $snapshot = $this->history->getHistory(); |
||
115 | if (is_array($snapshot) && count($snapshot) > 0) { |
||
116 | return $snapshot[0]; |
||
117 | } |
||
118 | } elseif ($this->cacheSnapshot()) { |
||
119 | if ($teacherFilter) { |
||
120 | return array_filter( |
||
121 | static::$data[$this->getCourseId()][$this->getDomain()][$this->getTimestamp()], |
||
122 | function ($elt) { |
||
123 | return array_search( |
||
124 | $teacherFilter, |
||
125 | unserialize($elt['teacher[id]s']) |
||
126 | ) !== false; |
||
127 | } |
||
128 | ); |
||
129 | } |
||
130 | return static::$data[$this->getCourseId()][$this->getDomain()][$this->getTimestamp()]; |
||
131 | } |
||
132 | return false; |
||
133 | } |
||
134 | |||
135 | /* |
||
136 | * need to cache snapshots per timestamp, since different courses |
||
137 | * may have different most recent records that require comparison |
||
138 | * to different snapshots (e.g. a course ending June 1 should be |
||
139 | * compared to June 1 snapshots, but a course ending January 20 |
||
140 | * should be compared to January 20 snapshots) |
||
141 | */ |
||
142 | public function cacheSnapshot() |
||
143 | { |
||
144 | $domain = $this->getDomain(); |
||
145 | if ($domain == Domain::Course()) { |
||
146 | return $this->history->cacheHistory(); |
||
147 | } else { |
||
148 | $courseId = $this->getCourseId(); |
||
149 | $timestamp = $this->getTimestamp(); |
||
150 | if (empty(static::$data[$courseId][$domain][$timestamp])) { |
||
151 | $cache->pushKey(($domain == Domain::DEPARTMENT() ? $this->getDepartmentId() : 'school')); |
||
152 | static::$data[$courseId][$domain][$timestamp] = $cache->getCache($timestamp); |
||
153 | $this->averages = $cache->getCache("$timestamp-averages"); |
||
154 | if (empty(static::$data[$courseId][$domain][$timestamp])) { |
||
155 | if ($response = $this->mysql_query(" |
||
156 | SELECT * FROM `course_statistics` |
||
157 | WHERE |
||
158 | " . ($domain == Domain::DEPARTMENT() ? |
||
159 | "`course[account_id]` = '" . $this->getDepartmentId() . "' AND" : |
||
160 | '' |
||
161 | ) . " |
||
162 | `timestamp` LIKE '$timestamp%' |
||
163 | GROUP BY |
||
164 | `course[id]` |
||
165 | ORDER BY |
||
166 | `timestamp` DESC |
||
167 | ")) { |
||
168 | $total = [ |
||
169 | self::AVERAGE_TURN_AROUND => 0, |
||
170 | self::AVERAGE_ASSIGNMENT_COUNT => 0 |
||
171 | ]; |
||
172 | $divisor = [ |
||
173 | self::AVERAGE_TURN_AROUND => 0, |
||
174 | self::AVERAGE_ASSIGNMENT_COUNT => $response->num_rows |
||
175 | ]; |
||
176 | |||
177 | while ($row = $response->fetch_assoc()) { |
||
178 | static::$data[$courseId][$domain][$timestamp][] = $row; |
||
179 | |||
180 | $total[self::AVERAGE_TURN_AROUND] += |
||
181 | $row['average_grading_turn_around'] * |
||
182 | $row['student_count'] * |
||
183 | $row['graded_assignment_count']; |
||
184 | $divisor[self::AVERAGE_TURN_AROUND] += |
||
185 | $row['student_count'] * |
||
186 | $row['graded_assignment_count']; |
||
187 | |||
188 | $total[self::AVERAGE_ASSIGNMENT_COUNT] += |
||
189 | $row['assignments_due_count'] + |
||
190 | $row['dateless_assignment_count']; |
||
191 | } |
||
192 | |||
193 | for ($i = 0; $i < count($total); $i++) { |
||
0 ignored issues
–
show
|
|||
194 | $this->averages[$i] = $total[$i] / $divisor[$i]; |
||
195 | } |
||
196 | |||
197 | $cache->setCache($timestamp, static::$data[$courseId][$domain][$timestamp]); |
||
198 | $cache->setCache("$timestamp-averages", $this->averages); |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | return is_array(static::$data) && |
||
203 | is_array(static::$data[$courseId]) && |
||
204 | is_array(static::$data[$courseId][$domain]) && |
||
205 | is_array(static::$data[$courseId][$domain][$timestamp]) && |
||
206 | count(static::$data[$courseId][$domain][$timestamp]) > 0; |
||
207 | } |
||
208 | } |
||
209 | } |
||
210 |
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: