switch to explode since split deprecated
[openemr.git] / interface / reports / football_injury_report.php
blobfce90af4c4c9d875ae5bbb624b0063f604c4ed3c
1 <?php
2 // This module is for team sports use and reports on various attributes
3 // of injuries for a given time period and reporting key.
5 include_once("../globals.php");
6 include_once("../../library/patient.inc");
7 include_once("../../library/acl.inc");
8 include_once("../../contrib/forms/football_injury_audit/fia.inc.php");
10 // Might want something different here.
12 // if (! acl_check('acct', 'rep')) die("Unauthorized access.");
14 $from_date = fixDate($_POST['form_from_date']);
15 $to_date = fixDate($_POST['form_to_date'], date('Y-m-d'));
16 $form_by = $_POST['form_by']; // this is a scalar
17 $form_show = $_POST['form_show']; // this is an array
18 $form_squads = $_POST['form_squads']; // this is an array
20 // One of these is chosen as the left column, or Y-axis, of the report.
22 $arr_by = array(
23 1 => xl('Activity Type'),
24 2 => xl('Body Region'),
25 3 => xl('Footwear Type'),
26 4 => xl('Game Period'),
27 5 => xl('Injury Mechanism'),
28 6 => xl('Injury Type'),
29 7 => xl('Player'),
30 8 => xl('Playing Position'),
31 9 => xl('Sanction Type'),
32 10 => xl('Surface Type'),
33 11 => xl('Training Type')
36 // A reported value is either scalar, or an array listed horizontally. If
37 // multiple items are chosen then each starts in the next available column.
39 $arr_show = array(
40 1 => array('Number of Injuries'),
41 2 => array('Days/Games Missed'),
42 3 => array('Body Region'),
43 4 => array('Injury Type'),
44 5 => array('Issue Title'),
47 $arr_regions_osi10 = array(
48 'A' => xl('Ankle'),
49 'B' => xl('Pelvis and buttock'),
50 'C' => xl('Chest'),
51 'D' => xl('Thoracic spine'),
52 'E' => xl('Elbow'),
53 'F' => xl('Foot'),
54 'G' => xl('Hip and groin'),
55 'H' => xl('Head'),
56 'I' => xl('Congenital'),
57 'J' => xl('Paedeatric'),
58 'K' => xl('Knee'),
59 'L' => xl('Lumbar spine'),
60 'M' => xl('Medical problem'),
61 'N' => xl('Neck'),
62 'O' => xl('Trunk and abdomen'),
63 'Q' => xl('Lower leg'),
64 'R' => xl('Forearm'),
65 'S' => xl('Shoulder'),
66 'T' => xl('Thigh'),
67 'U' => xl('Upper arm'),
68 'V' => xl('Disabled'),
69 'W' => xl('Wrist and hand'),
70 'X' => xl('Location unspecified'),
71 'Y' => xl('Post surgical'),
72 'Z' => xl('No presenting illness/injury'),
75 $arr_regions_osics = array(
76 'A' => xl('Ankle + heel'),
77 'B' => xl('Buttock + S.I.'),
78 'C' => xl('Chest'),
79 'D' => xl('Thoracic spine'),
80 'E' => xl('Elbow'),
81 'F' => xl('Foot'),
82 'G' => xl('Hip + groin'),
83 'H' => xl('Head'),
84 'K' => xl('Knee'),
85 'L' => xl('Lumbar spine'),
86 'M' => xl('Medical problem'),
87 'N' => xl('Neck'),
88 'O' => xl('Abdominal'),
89 'P' => xl('Hand + fingers'),
90 'Q' => xl('Lower leg'),
91 'R' => xl('Forearm'),
92 'S' => xl('Shoulder + clavicle'),
93 'T' => xl('Thigh + hamstring'),
94 'U' => xl('Upper arm'),
95 'W' => xl('Wrist'),
96 'X' => xl('Multiple areas'),
97 'Z' => xl('Area not specified')
100 $arr_regions_ucsmc = array(
101 'AN' => xl('Ankle + heel'),
102 'AR' => xl('Upper arm'),
103 'BL' => xl('Medical problem'),
104 'CV' => xl('Medical problem'),
105 'DE' => xl('Medical problem'),
106 'EL' => xl('Elbow'),
107 'EN' => xl('Medical problem'),
108 'EV' => xl('Environmental'),
109 'FA' => xl('Forearm'),
110 'FE' => xl('Fluid and electrolyte problem'),
111 'FO' => xl('Foot'),
112 'GI' => xl('Abdominal'),
113 'GU' => xl('Medical problem'),
114 'HA' => xl('Hand + fingers'),
115 'HE' => xl('Head'),
116 'HI' => xl('Hip + groin'),
117 'ID' => xl('Medical problem'),
118 'KN' => xl('Knee'),
119 'LE' => xl('Lower leg'),
120 'LP' => xl('Lumbar spine'),
121 'NE' => xl('Neck'),
122 'NS' => xl('Medical problem'),
123 'PS' => xl('Medical problem'),
124 'RE' => xl('Medical problem'),
125 'RM' => xl('Medical problem'),
126 'SH' => xl('Shoulder + clavicle'),
127 'TH' => xl('Thigh + hamstring'),
128 'TR' => xl('Thoracic spine'),
129 'WR' => xl('Wrist')
132 $arr_types_osi10 = array(
133 'A' => xl('Arthritis'),
134 'C' => xl('Cartilage injury'),
135 'D' => xl('Joint dislocations'),
136 'F' => xl('Fracture'),
137 'G' => xl('Synovitis, impingement, bursitis'),
138 'H' => xl('Bruising/haematoma'),
139 'J' => xl('Joint sprains'),
140 'K' => xl('Laceration/abrasion'),
141 'M' => xl('Muscle injury'),
142 'N' => xl('Nerve injury'),
143 'O' => xl('Organ injury'),
144 'S' => xl('Stress fracture'),
145 'T' => xl('Tendon injury'),
146 'V' => xl('Vascular injury'),
147 'W' => xl('Whiplash'),
148 'X' => xl('Non specific injury'),
149 'Y' => xl('Other stress/Over use injury'),
150 'Z' => xl('Other injury not elsewhere specified'),
153 $arr_types_osics = array(
154 'A' => xl('Arthritis / degen joint disease'),
155 'B' => xl('Developmental abnormality'),
156 'C' => xl('Cartilage / chondral / disc damage'),
157 'D' => xl('Dislocation'),
158 'E' => xl('Tumour'),
159 'F' => xl('Fracture'),
160 'G' => xl('Avulsion / avulsion fracture'),
161 'H' => xl('Haematoma / bruising'),
162 'I' => xl('Infection / Abscess'),
163 'J' => xl('Minor joint strain +/- synovitis'),
164 'K' => xl('Laceration / skin condition'),
165 'L' => xl('Ligament tear or sprain'),
166 'M' => xl('Strain of muscle'),
167 'N' => xl('Neural condition / nerve damage'),
168 'O' => xl('Visceral damage/trauma/surgery'),
169 'P' => xl('Chronic synovitis / effusion / joint pain / gout'),
170 'Q' => xl('Old fracture non / malunion'),
171 'R' => xl('Rupture'),
172 'S' => xl('Stress fracture'),
173 'T' => xl('Tendonitis / osis / bursitis'),
174 'U' => xl('Instability / subluxation'),
175 'V' => xl('Vascular condition'),
176 'X' => xl('Medical problem'),
177 'Y' => xl('Trigger point / compartment syndrome / DOMS / cramp'),
178 'Z' => xl('Undiagnosed')
181 $arr_types_ucsmc = array(
182 '01' => xl('Ligament tear or sprain'),
183 '02' => xl('Ligament tear or sprain'),
184 '03' => xl('Ligament tear or sprain'),
185 '07' => xl('Strain of muscle'),
186 '09' => xl('Rupture'),
187 '10' => xl('Dislocation'),
188 '11' => xl('Instability / subluxation'),
189 '12' => xl('Instability / subluxation'),
190 '13' => xl('Fracture'),
191 '14' => xl('Avulsion / avulsion fracture'),
192 '15' => xl('Old fracture non / malunion'),
193 '16' => xl('Fracture'),
194 '17' => xl('Cartilage / chondral / disc damage'),
195 '18' => xl('Stress fracture'),
196 '23' => xl('Haematoma / bruising'),
197 '24' => xl('Laceration / skin condition'),
198 '25' => xl('Haematoma / bruising'),
199 '26' => xl('Tendonitis / osis / bursitis'),
200 '27' => xl('Tendonitis / osis / bursitis'),
201 '28' => xl('Tendonitis / osis / bursitis'),
202 '29' => xl('Tendonitis / osis / bursitis'),
203 '33' => xl('Arthritis / degen joint diseas'),
204 '36' => xl('Trigger point / compartment syndrome / DOMS / cramp'),
205 '38' => xl('Infection / Abscess'),
206 '39' => xl('Medical problem'),
207 '40' => xl('Cartilage / chondral / disc damage'),
208 '42' => xl('Tumour'),
209 '44' => xl('Neural condition / nerve damage')
213 <html>
214 <head>
215 <?php html_header_show();?>
216 <title><?php xl('Football Injury Report','e'); ?></title>
217 <style type="text/css">@import url(../../library/dynarch_calendar.css);</style>
218 <style type="text/css">
219 body { font-family:sans-serif; font-size:10pt; font-weight:normal }
220 .dehead { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:bold }
221 .detail { color:#000000; font-family:sans-serif; font-size:10pt; font-weight:normal }
222 </style>
223 <script type="text/javascript" src="../../library/textformat.js"></script>
224 <script type="text/javascript" src="../../library/dynarch_calendar.js"></script>
225 <?php include_once("{$GLOBALS['srcdir']}/dynarch_calendar_en.inc.php"); ?>
226 <script type="text/javascript" src="../../library/dynarch_calendar_setup.js"></script>
227 <script language="JavaScript">
228 var mypcc = '<?php echo $GLOBALS['phone_country_code'] ?>';
229 </script>
230 </head>
232 <body leftmargin='0' topmargin='0' marginwidth='0' marginheight='0'>
234 <center>
236 <h2><?php xl('Football Injury Report','e'); ?></h2>
238 <form name='theform' method='post' action='football_injury_report.php'>
240 <table border='0' cellspacing='0' cellpadding='2'>
242 <tr>
243 <td valign='top' nowrap>
244 For each
245 </td>
246 <td valign='top'>
247 <select name='form_by' title='Left column of report'>
248 <?php
249 foreach ($arr_by as $key => $value) {
250 echo " <option value='$key'";
251 if ($key == $form_by) echo " selected";
252 echo ">" . $value . "</option>\n";
255 </select>
256 </td>
257 <td valign='top' rowspan='3' nowrap>
258 &nbsp;
259 <input type='submit' name='form_refresh' value='<?php xl('Show','e'); ?>' title='<?php xl('Click to generate the report','e'); ?>'> :
260 </td>
261 <td valign='top' rowspan='3'>
262 <select name='form_show[]' size='4' multiple
263 title='<?php xl('Hold down Ctrl to select multiple items','e'); ?>'>
264 <?php
265 foreach ($arr_show as $key => $value) {
266 echo " <option value='$key'";
267 if (is_array($form_show) && in_array($key, $form_show)) echo " selected";
268 echo ">" . $value[0] . "</option>\n";
271 </select>
272 </td>
273 <td valign='top' rowspan='3' nowrap>
274 &nbsp;
275 for:
276 </td>
277 <td valign='top' rowspan='3'>
278 <select name='form_squads[]' size='4' multiple
279 title='<?php xl('Hold down Ctrl to select multiple squads','e'); ?>'>
280 <?php
281 $squads = acl_get_squads();
282 if ($squads) {
283 foreach ($squads as $key => $value) {
284 echo " <option value='$key'";
285 if (!is_array($form_squads) || in_array($key, $form_squads)) echo " selected";
286 echo ">" . $value[3] . "</option>\n";
290 </select>
291 </td>
292 </tr>
293 <tr>
294 <td valign='top' nowrap>
295 from
296 </td>
297 <td valign='top' nowrap>
298 <input type='text' name='form_from_date' id='form_from_date' size='10' value='<?php echo $from_date ?>'
299 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='Start date yyyy-mm-dd'>
300 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
301 id='img_from_date' border='0' alt='[?]' style='cursor:pointer'
302 title='<?php xl('Click here to choose a date','e'); ?>'>
303 </td>
304 </tr>
305 <tr>
306 <td valign='top' nowrap>
308 </td>
309 <td valign='top' nowrap>
310 <input type='text' name='form_to_date' id='form_to_date' size='10' value='<?php echo $to_date ?>'
311 onkeyup='datekeyup(this,mypcc)' onblur='dateblur(this,mypcc)' title='End date yyyy-mm-dd'>
312 <img src='../pic/show_calendar.gif' align='absbottom' width='24' height='22'
313 id='img_to_date' border='0' alt='[?]' style='cursor:pointer'
314 title='<?php xl('Click here to choose a date','e'); ?>'>
315 </td>
316 </tr>
318 <tr>
319 <td height="1">
320 </td>
321 </tr>
323 </table>
325 <?php
326 if ($_POST['form_refresh']) {
328 // fetch all the issues that are medical problems and corresponding FIA
329 // data. We are reporting only values from issues (though often by FIA
330 // fields), so it seems we want to retain one array row per issue and
331 // discard extra FIA forms.
333 $squadmatches = '1 = 2'; // an always-false condition
334 if($form_squads!='') {
335 foreach ($form_squads as $squad)
336 $squadmatches .= " OR pd.squad = '$squad'";
339 /*****************************************************************
340 $query = "SELECT lists.id AS listid, lists.diagnosis, lists.pid, " .
341 "lists.extrainfo AS gmissed, lists.begdate, lists.enddate, " .
342 "lists.returndate, lists.title, fia.*, pd.lname, pd.fname, pd.mname " .
343 "FROM lists " .
344 "JOIN patient_data AS pd ON pd.pid = lists.pid AND ( $squadmatches ) " .
345 "JOIN issue_encounter AS ie ON ie.list_id = lists.id " .
346 "JOIN forms ON forms.pid = ie.pid AND forms.encounter = ie.encounter " .
347 "AND forms.formdir = 'football_injury_audit' " .
348 "JOIN form_football_injury_audit as fia ON fia.id = forms.form_id " .
349 "WHERE ( lists.enddate IS NULL OR lists.enddate >= '$from_date' ) AND " .
350 "lists.begdate <= '$to_date' AND " .
351 "lists.type = 'medical_problem' AND lists.title NOT LIKE '%Illness%'" .
352 "ORDER BY lists.pid, lists.begdate";
353 *****************************************************************/
354 $query = "SELECT lists.id AS listid, lists.diagnosis, lists.pid, " .
355 "lists.extrainfo AS gmissed, lists.begdate, lists.enddate, " .
356 "lists.returndate, lists.title, lfi.*, pd.lname, pd.fname, pd.mname " .
357 "FROM lists " .
358 "JOIN lists_football_injury AS lfi ON lfi.id = lists.id " .
359 "JOIN patient_data AS pd ON pd.pid = lists.pid AND ( $squadmatches ) " .
360 "WHERE ( lists.enddate IS NULL OR lists.enddate >= '$from_date' ) AND " .
361 "lists.begdate <= '$to_date' AND lists.type = 'football_injury' " .
362 "ORDER BY lists.pid, lists.begdate";
363 /****************************************************************/
365 $res = sqlStatement($query);
367 $areport = array();
368 $arr_my_body_regions = array();
369 $arr_my_injury_types = array();
370 $arr_my_issue_titles = array();
372 // $last_listid = 0;
373 $last_pid = 0;
374 $last_endsecs = 0;
376 while ($row = sqlFetchArray($res)) {
378 // // Throw away extra injury forms.
379 // if ($row['listid'] == $last_listid) continue;
380 // $last_listid = $rows['listid'];
382 // Determine the primary diagnosis.
383 $diagnosis = '';
384 if (!empty($row['diagnosis'])) {
385 $relcodes = explode(';', $row['diagnosis']);
386 foreach ($relcodes as $codestring) {
387 if ($codestring === '') continue;
388 list($codetype, $code) = explode(':', $codestring);
389 if (empty($code)) $code = $codetype;
390 $diagnosis = $code;
391 break;
395 $body_region = 'Undiagnosed';
396 if (preg_match('/^(.)...$/', $diagnosis, $matches)) {
397 $body_region = $arr_regions_osi10[$matches[1]];
399 else if (preg_match('/^(.)..$/', $diagnosis, $matches)) {
400 $body_region = $arr_regions_osics[$matches[1]];
402 else if (preg_match('/^(..)\...\...$/', $diagnosis, $matches)) {
403 $body_region = $arr_regions_ucsmc[$matches[1]];
406 $injury_type = 'Undiagnosed';
407 if (preg_match('/^.(.)..$/', $diagnosis, $matches)) {
408 $injury_type = $arr_types_osi10[$matches[1]];
410 else if (preg_match('/^.(.).$/', $diagnosis, $matches)) {
411 $injury_type = $arr_types_osics[$matches[1]];
413 else if (preg_match('/^..\...\.(..)$/', $diagnosis, $matches)) {
414 $injury_type = $arr_types_ucsmc[$matches[1]];
417 $issue_title = trim($row['title']);
419 $key = 'Unspecified';
421 if ($form_by == '1') { // Activity Type
422 if ($row['fimech_tackling'] || $row['fimech_tackled'] ||
423 $row['fimech_collision'] || $row['fimech_kicked'] ||
424 $row['fimech_elbow'] || $row['fimech_othercon'])
426 $key = 'Contact';
427 } else {
428 $key = 'Non-contact';
432 else if ($form_by == '2') { // Body Region
433 $key = $body_region;
436 else if ($form_by == '3') { // Footwear Type
437 if ($row['fifootwear']) $key = $arr_footwear[$row['fifootwear']];
440 else if ($form_by == '4') { // Game Period
441 if ($row['fiinjmin']) {
442 $key = 15 * (int)(($row['fiinjmin'] + 14) / 15);
446 else if ($form_by == '5') { // Injury Mechanism
447 foreach ($arr_activity as $imkey => $imvalue) {
448 if ($row["fimech_$imkey"]) {
449 $key = $imvalue;
450 break;
455 else if ($form_by == '6') { // Injury Type
456 $key = $injury_type;
459 else if ($form_by == '7') { // Player
460 $key = trim($row['lname'] . ', ' . $row['fname'] . ' ' . $row['mname']);
463 else if ($form_by == '8') { // Playing Position
464 if ($row['fiposition']) $key = $arr_position[$row['fiposition']];
467 else if ($form_by == '9') { // Referee Sanction Type
468 foreach ($arr_sanction as $imkey => $imvalue) {
469 if ($row["fimech_$imkey"]) {
470 $key = $imvalue;
471 break;
476 else if ($form_by == '10') { // Surface Type
477 if ($row['fisurface']) $key = $arr_surface[$row['fisurface']];
480 else if ($form_by == '11') { // Training Type
481 if ($row['fiinjtime']) $key = $arr_injtime[$row['fiinjtime']];
484 // OK we now have the reporting key for this issue.
486 // If first instance of this key, initialize its arrays.
487 if (! $areport[$key]) {
488 $areport[$key] = array();
489 $areport[$key]['inj'] = 0; // number of injuries
490 $areport[$key]['dmissed'] = 0; // days missed
491 $areport[$key]['gmissed'] = 0; // games missed
492 $areport[$key]['br'] = array(); // body region array
493 $areport[$key]['it'] = array(); // injury type array
494 $areport[$key]['ti'] = array(); // issue title array
497 // Compute days missed. Force non-overlap of multiple issues for the
498 // same player. This logic assumes sorting on begdate within pid.
500 $begsecs = strtotime($row['begdate']);
501 $endsecs = $row['returndate'] ? strtotime($row['returndate']) : time();
502 if ($row['pid'] == $last_pid) {
503 if ($begsecs < $last_endsecs) {
504 $begsecs = $last_endsecs;
507 else {
508 $last_pid = $row['pid'];
509 $last_endsecs = 0;
511 if ($begsecs > $endsecs) $begsecs = $endsecs;
512 if ($last_endsecs < $endsecs) $last_endsecs = $endsecs;
513 $daysmissed = round(($endsecs - $begsecs) / (60 * 60 * 24));
515 // Store values that we might want to report on.
516 $areport[$key]['inj'] += 1; // count number of injuries
517 $areport[$key]['dmissed'] += $daysmissed; // count days missed
518 $areport[$key]['gmissed'] += $row['gmissed']; // count games missed
519 $areport[$key]['br'][$body_region] += 1; // count injuries to this body part
520 $areport[$key]['it'][$injury_type] += 1; // count injuries of this type
521 $areport[$key]['ti'][$issue_title] += 1; // count injuries with this title
523 // These track all body regions and injury types encountered.
524 $arr_my_body_regions[$body_region] += 1;
525 $arr_my_injury_types[$injury_type] += 1;
526 $arr_my_issue_titles[$issue_title] += 1;
528 } // end while
530 // Sort everything by key for reporting.
531 ksort($areport);
532 ksort($arr_my_body_regions);
533 ksort($arr_my_injury_types);
534 ksort($arr_my_issue_titles);
537 <table border='0' cellpadding='1' cellspacing='2' width='98%'>
539 <tr bgcolor="#dddddd">
540 <td class="dehead">
541 <?php echo $arr_by[$form_by]; ?>
542 </td>
544 <?php
545 if($form_show!='') {
546 // Generate headings for values to be shown.
547 foreach ($form_show as $value) {
548 if ($value == '1') { // Number of injuries
549 echo " <td class='dehead' align='right'>Injuries</td>\n";
551 else if ($value == '2') { // days and games missed
552 echo " <td class='dehead' align='right'>Days Missed</td>\n";
553 echo " <td class='dehead' align='right'>Games Missed</td>\n";
555 else if ($value == '3') { // body region
556 foreach ($arr_my_body_regions as $br => $nothing) {
557 echo " <td class='dehead' align='right'>$br</td>\n";
560 else if ($value == '4') { // injury type
561 foreach ($arr_my_injury_types as $it => $nothing) {
562 echo " <td class='dehead' align='right'>$it</td>\n";
565 else if ($value == '5') { // issue titles
566 foreach ($arr_my_issue_titles as $ti => $nothing) {
567 echo " <td class='dehead' align='right'>$ti</td>\n";
573 echo " </tr>\n";
575 $encount = 0;
577 foreach ($areport as $key => $varr) {
578 $bgcolor = (++$encount & 1) ? "#ddddff" : "#ffdddd";
580 echo " <tr bgcolor='$bgcolor'>\n";
581 echo " <td class='detail'>$key</td>\n";
583 // Generate data for this row.
584 foreach ($form_show as $value) {
585 if ($value == '1') { // Number of injuries
586 echo " <td class='detail' align='right'>" . $areport[$key]['inj'] . "</td>\n";
588 else if ($value == '2') { // days and games missed
589 echo " <td class='detail' align='right'>" . $areport[$key]['dmissed'] . "</td>\n";
590 echo " <td class='detail' align='right'>" . $areport[$key]['gmissed'] . "</td>\n";
592 else if ($value == '3') { // body region
593 foreach ($arr_my_body_regions as $body_region => $nothing) {
594 echo " <td class='detail' align='right'>" . $areport[$key]['br'][$body_region] . "</td>\n";
597 else if ($value == '4') { // injury type
598 foreach ($arr_my_injury_types as $injury_type => $nothing) {
599 echo " <td class='detail' align='right'>" . $areport[$key]['it'][$injury_type] . "</td>\n";
602 else if ($value == '5') { // issue title
603 foreach ($arr_my_issue_titles as $issue_title => $nothing) {
604 echo " <td class='detail' align='right'>" . $areport[$key]['ti'][$issue_title] . "</td>\n";
609 echo " </tr>\n";
610 } // end foreach
613 </table>
615 <?php } // end of if ($_POST['form_refresh']) ?>
617 </form>
618 </center>
620 <script language='JavaScript'>
621 Calendar.setup({inputField:"form_from_date", ifFormat:"%Y-%m-%d", button:"img_from_date"});
622 Calendar.setup({inputField:"form_to_date", ifFormat:"%Y-%m-%d", button:"img_to_date"});
623 </script>
625 </body>
626 </html>