D:\host\scoreman.in\assisi2026\functions best working 14.php

<?php
 
require_once 'PHPMailer/PHPMailer.php';
require_once 'PHPMailer/SMTP.php';
require_once 'PHPMailer/Exception.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
function buildSpeedEventSummary(mysqli $con, $repdistrict = '')
{
    // ---- header info (championships) ----
    $eventtitle = $eventdate = '';
    if ($repdistrict !== '') {
        $sqlC = 'SELECT championshiptitle, dates FROM championships WHERE district = ? ORDER BY id DESC LIMIT 1';
        if ($st = mysqli_prepare($con, $sqlC)) {
            mysqli_stmt_bind_param($st, 's', $repdistrict);
            mysqli_stmt_execute($st);
            if (function_exists('mysqli_stmt_get_result')) {
                $rs = mysqli_stmt_get_result($st);
                if ($row = mysqli_fetch_assoc($rs)) {
                    $eventtitle = trim($row['championshiptitle']);
                    $eventdate  = trim($row['dates']);
                }
                if ($rs) mysqli_free_result($rs);
            }
            mysqli_stmt_close($st);
        }
    }

    // ---- speed events order (quad first, then inline) ----
    $events = array(
        'rink1' => 'rink1', 'rink2' => 'rink2', 'rink3' => 'rink3',
        'road1' => 'road1', 'road2' => 'road2',
        'rink4' => 'rink4', 'rink5' => 'rink5', 'rink6' => 'rink6', 'rink7' => 'rink7',
        'p2p'   => 'p2p',   'elim'  => 'elim',
        'road3' => 'road3', 'road4' => 'road4', 'road5' => 'road5',
        'p2prd' => 'p2prd', 'elimrd'=> 'elimrd',
        'relay' => 'relay', 'mixedrelay' => 'mixedrelay'
        // 'marathon' // omit if not required
    );

    // ---- fetch all needed data ----
    $cols = array_merge(array('agegroup','agorder','gender'), array_keys($events));
    $select = '`' . implode('`,`', $cols) . '`';

    $where = 'order_status="Success"';
    $types = '';
    $params = array();

    if ($repdistrict !== '') {
        $where .= ' AND repdistrict = ?';
        $types .= 's';
        $params[] = $repdistrict;
    }

    // optional: ignore blank chno entries if you prefer
    // $where .= ' AND chno <> ""';

    $sql = "SELECT $select FROM applications WHERE $where";
    $sql .= " ORDER BY agorder+0, gender DESC"; // Cadet.. Senior by agorder; Boys after Girls (DESC -> M,F depends on your data)

    $rows = array();
    if ($st = mysqli_prepare($con, $sql)) {
        if ($types !== '') {
            $bind = array($st, $types);
            foreach ($params as $k => $v) { $bind[] = &$params[$k]; }
            call_user_func_array('mysqli_stmt_bind_param', $bind);
        }
        mysqli_stmt_execute($st);

        if (function_exists('mysqli_stmt_get_result')) {
            $rs = mysqli_stmt_get_result($st);
            while ($r = mysqli_fetch_assoc($rs)) $rows[] = $r;
            if ($rs) mysqli_free_result($rs);
        } else {
            mysqli_stmt_store_result($st);
            $meta = mysqli_stmt_result_metadata($st);
            $fields = array(); $cur = array(); $bindRes = array();
            while ($f = mysqli_fetch_field($meta)) { $fields[] = $f->name; $bindRes[] = &$cur[$f->name]; }
            call_user_func_array('mysqli_stmt_bind_result', array_merge(array($st), $bindRes));
            while (mysqli_stmt_fetch($st)) {
                $rr = array();
                foreach ($fields as $f) $rr[$f] = $cur[$f];
                $rows[] = $rr;
            }
        }
        mysqli_stmt_close($st);
    }

    // ---- accumulate counts: summary[agorder]['label'] + ['Female'|'Male'][event] ----
    $summary = array();     // agorder => ['agegroup'=>..., 'Female'=>[], 'Male'=>[]]
    $grand   = array();     // event => total
    foreach ($events as $ev => $lbl) { $grand[$ev] = 0; }

    // helper to decide if a cell counts as an entry
    $countsAsEntry = function($v) {
        if ($v === null) return false;
        $v = strtoupper(trim((string)$v));
        // count entries that are participating or placed; ignore explicit Absent
        return ($v === 'P' || $v === '1' || $v === '2' || $v === '3' || $v === 'G' || $v === 'S' || $v === 'B' || $v === 'A');
    };

    foreach ($rows as $r) {
        $agorder = isset($r['agorder']) ? trim($r['agorder']) : '999';
        if (!isset($summary[$agorder])) {
            $summary[$agorder] = array(
                'agegroup' => trim($r['agegroup']),
                'Female'   => array(),
                'Male'     => array(),
            );
            foreach (array('Female','Male') as $g) {
                foreach ($events as $ev => $lbl) $summary[$agorder][$g][$ev] = 0;
            }
        }

        $gender = strtolower(trim($r['gender']));
        $gkey = (in_array($gender, array('f','female','girl','girls','women','woman'), true)) ? 'Female' : 'Male';

        foreach ($events as $ev => $lbl) {
            if ($countsAsEntry(isset($r[$ev]) ? $r[$ev] : null)) {
                $summary[$agorder][$gkey][$ev] += 1;
                $grand[$ev] += 1;
            }
        }
    }

    // ---- render HTML ----
    ob_start();
    ?>
    <style>
        .evt-sum { width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 12px; }
        .evt-sum th, .evt-sum td { border: 1px solid #333; padding: 4px 6px; text-align: right; }
        .evt-sum th:first-child, .evt-sum td:first-child { text-align: left; }
        .evt-sum thead th { background: #f2f2f2; font-weight: bold; }
        .evt-sum .ag { font-weight: bold; text-align: left; }
        .evt-sum .sex { text-align: left; width: 80px; }
        .evt-title { text-align:center; font-weight:bold; font-size:16px; margin:4px 0 10px; }
        .evt-sub { text-align:center; font-size:12px; margin-top:-6px; margin-bottom:10px; }
        .evt-sum tfoot td { font-weight: bold; background:#f7f7f7; }
        /* optional: rotate headers */
        .vhead { writing-mode: vertical-rl; transform: rotate(180deg); white-space:nowrap; padding:6px 2px; min-width:16px; }
        @media print {
            .evt-title { margin-top:0 }
        }
    </style>
    <div class="evt-title"><?php echo htmlspecialchars($eventtitle !== '' ? $eventtitle : 'EVENT SUMMARY', ENT_QUOTES, 'UTF-8'); ?></div>
    <div class="evt-sub">EVENT SUMMARY - SPEED<?php echo $eventdate ? ' &nbsp;|&nbsp; ' . htmlspecialchars($eventdate, ENT_QUOTES, 'UTF-8') : ''; ?></div>

    <table class="evt-sum">
        <thead>
            <tr>
                <th>Age Group</th>
                <th class="sex">Gender</th>
                <?php foreach ($events as $ev => $lbl): ?>
                    <th><span class="vhead"><?php echo htmlspecialchars($lbl, ENT_QUOTES, 'UTF-8'); ?></span></th>
                <?php endforeach; ?>
            </tr>
        </thead>
        <tbody>
        <?php
        ksort($summary, SORT_NATURAL);
        foreach ($summary as $agorder => $blk):
            $agegroup = $blk['agegroup'];
            ?>
            <tr>
                <td class="ag" rowspan="2"><?php echo htmlspecialchars($agegroup, ENT_QUOTES, 'UTF-8'); ?></td>
                <td class="sex">Female</td>
                <?php foreach ($events as $ev => $lbl): ?>
                    <td><?php echo (int)$blk['Female'][$ev]; ?></td>
                <?php endforeach; ?>
            </tr>
            <tr>
                <td class="sex">Male</td>
                <?php foreach ($events as $ev => $lbl): ?>
                    <td><?php echo (int)$blk['Male'][$ev]; ?></td>
                <?php endforeach; ?>
            </tr>
        <?php endforeach; ?>
        </tbody>
        <tfoot>
            <tr>
                <td colspan="2">Grand Total</td>
                <?php foreach ($events as $ev => $lbl): ?>
                    <td><?php echo (int)$grand[$ev]; ?></td>
                <?php endforeach; ?>
            </tr>
        </tfoot>
    </table>
    <?php
    return ob_get_clean();
}


function buildCertificatesHTML(
    mysqli $con,
    $repdistrict = '',
    array $onlyAppnos = null,
    $certPrefix = 'TNDT2025/',
    $bgPath = 'certbg.jpg'
) {
    $eventTitle=''; $eventDate=''; $eventVenue=''; $president=''; $secretary=''; $districtSafe=$repdistrict;

    // $fetchChamp = function(mysqli $con, $repdistrict){
    //     if ($st = mysqli_prepare($con, "SELECT * FROM championships WHERE district = ? ORDER BY id DESC LIMIT 1")) {
    //         mysqli_stmt_bind_param($st,"s",$repdistrict);
    //         mysqli_stmt_execute($st);
    //         if (function_exists('mysqli_stmt_get_result')) {
    //             $res = mysqli_stmt_get_result($st);
    //             if ($row = mysqli_fetch_assoc($res)) { mysqli_stmt_close($st); return $row; }
    //             if ($res) mysqli_free_result($res);
    //         }
    //         mysqli_stmt_close($st);
    //     }
    //     $row=null;
       
    //     return $row;
    // };

    // if ($champ = $fetchChamp($con,$repdistrict)) {
    //     $eventTitle   = (string)($champ['championshiptitle'] ?? '');
    //     $eventDate    = (string)($champ['dates'] ?? '');
    //     $eventVenue   = (string)($champ['venue'] ?? '');
    //     $president    = (string)($champ['president'] ?? '');
    //     $secretary    = (string)($champ['secretary'] ?? '');
    //     $districtSafe = (string)($champ['district'] ?? $repdistrict);
    // }

    $databaseQuery = 'SELECT * FROM `championships` WHERE `district`="'.$con->real_escape_string($repdistrict).'"';

    $result3 = mysqli_query($con,$databaseQuery) or die('Query failed: ' . mysqli_error());
        while($row = mysqli_fetch_array($result3))
  {
    
                   // $eventtitle=trim($row["championshiptitle"]);
                   //  $eventdate=trim($row["dates"]);

     $eventTitle   = (string)($row['championshiptitle'] ?? '');
        $eventDate    = (string)($row['dates'] ?? '');
        $eventVenue   = (string)($row['venue'] ?? '');
        $president    = (string)($row['president'] ?? '');
        $secretary    = (string)($row['secretary'] ?? '');
        $districtSafe = (string)($row['district'] ?? $repdistrict);


       }


    // Include ALL event columns now
    $cols = [
        'appno','sname','dob','agegroup','gender','club','clubname','photourl',
        // Speed-Quad
        'rink1','rink2','rink3','road1','road2',
        // Speed-Inline
        'rink4','rink5','rink6','rink7','p2p','elim','relay','mixedrelay','road3','road4','road5','p2prd','elimrd','marathon',
        // Artistic
        'figure','free','pair','solodance','pairdance','inlinefree','quartet','precisionskating','showgroup',
        // Hockey
        'quadhockey','mixedrollerhockey','inlinehockey',
        // Freestyle
        'speedslalom','classicslalom','pairslalom',
        // Other Games
        'alpine','downhill','rollerderby','rollerfreestyle','skateboarding','scooter'
    ];
    $select = '`'.implode('`,`',$cols).'`';
    $where  = "order_status='Success'";
    $types=''; $params=[];

    if ($repdistrict!==''){ $where.=" AND repdistrict=?"; $types.='s'; $params[]=$repdistrict; }
    if ($onlyAppnos && count($onlyAppnos)){
        $where.=" AND appno IN (".implode(',',array_fill(0,count($onlyAppnos),'?')).")";
        $types.=str_repeat('s',count($onlyAppnos));
        foreach($onlyAppnos as $a){ $params[]=(string)$a; }
    }

    $sql = "SELECT $select FROM applications WHERE $where
            ORDER BY agegroup, gender DESC, CAST(appno AS UNSIGNED)";

    $rows=[];
    if ($st = mysqli_prepare($con,$sql)) {
        if ($types!==''){
            $bind=[&$types]; foreach($params as $i=>$v){ $bind[]=&$params[$i]; }
            call_user_func_array('mysqli_stmt_bind_param',array_merge([$st],$bind));
        }
        mysqli_stmt_execute($st);
        if (function_exists('mysqli_stmt_get_result')) {
            $res = mysqli_stmt_get_result($st);
            while($r=mysqli_fetch_assoc($res)) $rows[]=$r;
            if ($res) mysqli_free_result($res);
        } else {
            mysqli_stmt_store_result($st);
            $meta = mysqli_stmt_result_metadata($st);
            $fields=[]; $row=[]; $bindRes=[];
            while($f=mysqli_fetch_field($meta)){ $fields[]=$f->name; $bindRes[]=&$row[$f->name]; }
            call_user_func_array('mysqli_stmt_bind_result',array_merge([$st],$bindRes));
            while(mysqli_stmt_fetch($st)){ $r=[]; foreach($fields as $f){ $r[$f]=$row[$f]; } $rows[]=$r; }
        }
        mysqli_stmt_close($st);
    }

  $resultLabel = function($v){
    $v = strtoupper(trim((string)$v));
    if ($v==='1' || $v==='G') return 'FIRST';
    if ($v==='2')             return 'SECOND';       // do NOT map 'S' to second anymore
    if ($v==='3' || $v==='B') return 'THIRD';
    if ($v==='S')             return 'SELECTED';     // NEW
    if ($v==='F')             return 'FORWARD';      // optional: only if you store F
    if ($v==='P')             return 'PARTICIPATED';
    // Hide Absent/empty by treating them as NIL (mkRows skips NIL)
    return 'NIL';
};
    $isMerit = function($lbl) { return in_array($lbl, array('FIRST','SECOND','THIRD'), true); };
    $genderWord = function($g){
        $g=strtolower(trim((string)$g));
        if (in_array($g,['f','female','girl','girls','women','woman'],true)) return 'Girls';
        if (in_array($g,['m','male','boy','boys','men','man'],true))         return 'Boys';
        return ucfirst($g);
    };

    // Maps for all disciplines (labels per your spec)
    $quadMap = [
        'rink1'=>'RINK - I','rink2'=>'RINK - II','rink3'=>'RINK - III','road1'=>'ROAD - I','road2'=>'ROAD - II'
    ];
    $inlineMap = [
        'p2p'=>'POINTS (TRACK)','elim'=>'ELIMINATION (RINK)',
        'rink4'=>'RINK - IV','rink5'=>'RINK - V','rink6'=>'RINK - VI','rink7'=>'RINK - VII (Dual TT)',
        'road3'=>'ROAD - III','road4'=>'ROAD - IV','road5'=>'ROAD - V',
        'p2prd'=>'POINT TO POINT (ROAD)','elimrd'=>'ELIMINATION (ROAD)','relay'=>'RELAY','mixedrelay'=>'MIXED RELAY','marathon'=>'MARATHON'
    ];
    $artisticMap = [
        'figure'=>'FIGURE','free'=>'FREE','pair'=>'PAIR','solodance'=>'SOLO DANCE','pairdance'=>'PAIR DANCE',
        'inlinefree'=>'INLINE FREE','quartet'=>'QUARTET','precisionskating'=>'PRECISION SKATING','showgroup'=>'SHOW GROUP'
    ];
    $rollerHockeyMap = [
        'quadhockey'=>'ROLLER HOCKEY','mixedrollerhockey'=>'MIXED ROLLER HOCKEY'
    ];
    $inlineHockeyMap = [
        'inlinehockey'=>'INLINE HOCKEY'
    ];
    $freestyleMap = [
        'speedslalom'=>'SPEED SLALOM','classicslalom'=>'CLASSIC SLALOM','pairslalom'=>'PAIR SLALOM'
    ];
    $otherGamesMap = [
        'alpine'=>'ALPINE','downhill'=>'DOWNHILL','rollerderby'=>'ROLLER DERBY','rollerfreestyle'=>'ROLLER FREESTYLE',
        'skateboarding'=>'SKATEBOARDING','scooter'=>'SCOOTER'
    ];

    $districtSlug = preg_replace('/[^A-Za-z0-9_-]/','_',$districtSafe);
    $bgAttr = htmlspecialchars($bgPath,ENT_QUOTES,'UTF-8');

    $css = '<style>
      :root{
        --ink:#0b2a6f; --title:#12306e; --accent:#274b9a;
        --line:#c3d2f2; --sig-bottom:68mm;
        --hdr-top:10mm; --hdr-bottom:4mm; --logo-max-h:28mm;
        --photo-size:34mm; --name-size:20pt; --title-size:19pt;
        --ring:1mm; --corner:4mm; --grad-a:#7a2cff; --grad-b:#ff3aa6; --grad-c:#3a8dff;
      }
      *{box-sizing:border-box}
      @page{ size:A4; margin:0 }
      html,body{ height:100% }
      body{ font-family:Arial,Helvetica,sans-serif; color:var(--ink); margin:0; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
      .certpage{ page-break-after:always } .certpage:last-child{ page-break-after:auto }
      .sheet{ position:relative; width:210mm; height:297mm; overflow:hidden; display:grid; grid-template-rows:auto 1fr auto; }
      .pagebg{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:-1; }
      .hdr{ text-align:center; padding:var(--hdr-top) 16mm var(--hdr-bottom) }
      .logoCenter{ display:block; margin:0 auto 4mm; width:85%; height:auto; max-height:var(--logo-max-h) }
      .titleCert{ font-size:var(--title-size); font-weight:800; letter-spacing:.4px; margin:0; color:var(--title); text-transform:uppercase }
      .certno{ font-size:10pt; margin:2px 0 5mm }
      .content{ display:flex; flex-direction:column; align-items:center; padding:0 16mm; padding-bottom: calc(var(--sig-bottom) + 6mm); }
      .content-inner{ max-width:138mm; text-align:center; width:100% }
      .idrow{ display:flex; justify-content:center; margin:4mm 0 }
      .photoFrame{ width:var(--photo-size); height:var(--photo-size); padding:var(--ring); border-radius:var(--corner);
        background:linear-gradient(135deg,var(--grad-a) 0%,var(--grad-b) 45%,var(--grad-c) 100%); box-shadow:0 .8mm 2mm rgba(0,0,0,.12);}
      .photo{ width:100%; height:100%; border-radius:var(--corner); object-fit:cover; background:#fff; display:block; }
      .photo.ph{ display:flex; align-items:center; justify-content:center; background:#eef3ff; color:var(--ink); font-weight:700; border-radius:var(--corner) }
      .name{ font-size:var(--name-size); font-weight:900; letter-spacing:.8px; margin:1.6mm 0 2.6mm; text-transform:uppercase }
      .line{ margin:1.6mm 0 }
      .events{ display:flex; gap:6mm; justify-content:center; margin-top:4mm; flex-wrap:wrap }
      .blk{ width:70mm }
      .blk h4{ margin:0 0 2mm; font-size:11.5pt; text-transform:uppercase; border-bottom:1px solid var(--accent); padding-bottom:2px; color:var(--accent) }
      table.ev{ width:100%; border-collapse:collapse; font-size:10.5pt }
      table.ev td{ border-bottom:0.8px dotted var(--line); padding:2.5px 2px }
      table.ev td:first-child{ text-align:left; width:62% }
      table.ev td:last-child{ text-align:right; width:38%; font-weight:800 }
      .footer{ position:absolute; left:16mm; right:16mm; bottom:var(--sig-bottom); z-index:1; }
      .signs{ display:flex; justify-content:space-between; gap:10mm }
      .sigbox{ width:46%; text-align:center }
      .signame{ font-weight:800; margin-top:0 }
      .sigrole{ margin-top:1.2mm }
    </style>';

    $pages=[];

    $mkRows = function($map,$row,&$hasMerit) use($resultLabel,$isMerit){
        $h='';
        foreach($map as $k=>$label){
            $val = isset($row[$k]) ? $row[$k] : '';
            $lbl = $resultLabel($val);
            if ($lbl==='NIL') continue;               // show only participating/non-NIL
            if ($isMerit($lbl)) $hasMerit=true;
            $h.='<tr><td>'.htmlspecialchars($label,ENT_QUOTES,'UTF-8').'</td><td>'.htmlspecialchars($lbl,ENT_QUOTES,'UTF-8').'</td></tr>';
        }
        return $h;
    };

    foreach($rows as $r){
        $clubDisplay = ($r['clubname']!=='') ? $r['clubname'] : $r['club'];
        $dobStr = ($ts=strtotime($r['dob'])) ? date('d-M-Y',$ts) : htmlspecialchars($r['dob'],ENT_QUOTES,'UTF-8');
        $name   = htmlspecialchars($r['sname'],ENT_QUOTES,'UTF-8');
        $team   = htmlspecialchars($clubDisplay,ENT_QUOTES,'UTF-8');
        $ag     = htmlspecialchars($r['agegroup'],ENT_QUOTES,'UTF-8');
        $gender = htmlspecialchars($genderWord($r['gender']),ENT_QUOTES,'UTF-8');
        $certNo = htmlspecialchars($certPrefix.$r['appno'],ENT_QUOTES,'UTF-8');

        $photo = trim((string)$r['photourl']);
        if ($photo!=='' && strpos($photo,'data:image/')!==0) $photo='data:image/png;base64,'.$photo;
        $photoTag = ($photo!=='')
          ? '<div class="photoFrame"><img class="photo" src="'.htmlspecialchars($photo,ENT_QUOTES,'UTF-8').'" alt=""></div>'
          : '<div class="photoFrame"><div class="photo ph">PHOTO</div></div>';

        $hasMerit=false;
        $quadRows       = $mkRows($quadMap,$r,$hasMerit);
        $inlineRows     = $mkRows($inlineMap,$r,$hasMerit);
        $artisticRows   = $mkRows($artisticMap,$r,$hasMerit);
        $rhRows         = $mkRows($rollerHockeyMap,$r,$hasMerit);
        $ihRows         = $mkRows($inlineHockeyMap,$r,$hasMerit);
        $freestyleRows  = $mkRows($freestyleMap,$r,$hasMerit);
        $otherRows      = $mkRows($otherGamesMap,$r,$hasMerit);

        $certTitle  = $hasMerit ? 'CERTIFICATE OF MERIT' : 'CERTIFICATE OF PARTICIPATION';

        $blocks = '';
        if ($quadRows!=='')       $blocks .= '<div class="blk"><h4>Speed-Quad</h4><table class="ev">'.$quadRows.'</table></div>';
        if ($inlineRows!=='')     $blocks .= '<div class="blk"><h4>Speed-Inline</h4><table class="ev">'.$inlineRows.'</table></div>';
        if ($artisticRows!=='')   $blocks .= '<div class="blk"><h4>Artistic</h4><table class="ev">'.$artisticRows.'</table></div>';
        if ($rhRows!=='')         $blocks .= '<div class="blk"><h4>Roller-Hockey</h4><table class="ev">'.$rhRows.'</table></div>';
        if ($ihRows!=='')         $blocks .= '<div class="blk"><h4>Inline-Hockey</h4><table class="ev">'.$ihRows.'</table></div>';
        if ($freestyleRows!=='')  $blocks .= '<div class="blk"><h4>Inline-Freestyle</h4><table class="ev">'.$freestyleRows.'</table></div>';
        if ($otherRows!=='')      $blocks .= '<div class="blk"><h4>Other-Games</h4><table class="ev">'.$otherRows.'</table></div>';
        if ($blocks==='')         $blocks = '<div class="blk"><h4>Events</h4><table class="ev"><tr><td>—</td><td>NIL</td></tr></table></div>';

        $logo = $districtSlug!=='' ? '<img src="districtlogos/'.$districtSlug.'.png" class="logoCenter" alt="" onerror="this.style.display=\'none\'">' : '';
        $titleLine = 'in the '.htmlspecialchars($eventTitle,ENT_QUOTES,'UTF-8');
        $heldLine  = ($eventVenue!=='')
            ? 'held at '.htmlspecialchars($eventVenue,ENT_QUOTES,'UTF-8').' on '.htmlspecialchars($eventDate,ENT_QUOTES,'UTF-8')
            : 'Held on '.htmlspecialchars($eventDate,ENT_QUOTES,'UTF-8');

        $pages[] =
        '<div class="certpage"><div class="sheet">'.
          '<img class="pagebg" src="'.$bgAttr.'" alt="" aria-hidden="true">'.
          '<div class="hdr">'.$logo.'<div class="titleCert">'.$certTitle.'</div><div class="certno">Cert. No.: '.$certNo.'</div></div>'.
          '<div class="content"><div class="content-inner">'.
            '<div class="idrow">'.$photoTag.'</div>'.
            '<div class="name">'.strtoupper($name).'</div>'.
            '<div class="line">( born on '.$dobStr.' )</div>'.
            '<div class="line">representing '.$team.'</div>'.
            '<div class="line">in '.$ag.' '.$gender.' Age Group</div>'.
            '<div class="line">'.$titleLine.'</div>'.
            '<div class="line">'.$heldLine.'</div>'.
            '<div class="line">has participated and attained the following ranking.</div>'.
            '<div class="events">'.$blocks.'</div>'.
          '</div></div>'.
          '<div class="footer"><div class="signs">'.
            '<div class="sigbox"><div class="signame">'.htmlspecialchars($president,ENT_QUOTES,'UTF-8').'</div><div class="sigrole">President</div></div>'.
            '<div class="sigbox"><div class="signame">'.htmlspecialchars($secretary,ENT_QUOTES,'UTF-8').'</div><div class="sigrole">Secretary</div></div>'.
          '</div></div>'.
        '</div></div>';
    }

    if (empty($pages)) return '<p>No eligible records found.</p>';
    return $css.implode("\n",$pages);
}


function buildCertificateData(mysqli $con, $appno, $repdistrict = null) {
    // Championships (title, dates, district, president, secretary)
    $sqlC = "SELECT championshiptitle, dates, district, venue, president, secretary
             FROM championships
             WHERE district = ?
             ORDER BY id DESC LIMIT 1";
    $stmtC = mysqli_prepare($con, $sqlC);
    $dist = ($repdistrict !== null) ? $repdistrict : '';
    mysqli_stmt_bind_param($stmtC, "s", $dist);
    mysqli_stmt_execute($stmtC);
    $evt = array('championshiptitle'=>'', 'dates'=>'', 'district'=>$dist, 'venue'=>'', 'president'=>'', 'secretary'=>'');
    if (function_exists('mysqli_stmt_get_result')) {
        $res = mysqli_stmt_get_result($stmtC);
        if ($row = mysqli_fetch_assoc($res)) $evt = $row;
        if ($res) mysqli_free_result($res);
    } else {
        mysqli_stmt_bind_result($stmtC, $evt['championshiptitle'], $evt['dates'], $evt['district'], $evt['venue'], $evt['president'], $evt['secretary']);
        mysqli_stmt_fetch($stmtC);
    }
    mysqli_stmt_close($stmtC);

    // Skater/application – include ALL event columns
    $cols = array(
        'appno','sname','dob','agegroup','gender','club','clubname','photourl',
        // Speed-Quad
        'rink1','rink2','rink3','road1','road2',
        // Speed-Inline
        'rink4','rink5','rink6','rink7','p2p','elim','relay','mixedrelay','road3','road4','road5','p2prd','elimrd','marathon',
        // Artistic
        'figure','free','pair','solodance','pairdance','inlinefree','quartet','precisionskating','showgroup',
        // Hockey
        'quadhockey','mixedrollerhockey','inlinehockey',
        // Freestyle
        'speedslalom','classicslalom','pairslalom',
        // Other Games
        'alpine','downhill','rollerderby','rollerfreestyle','skateboarding','scooter'
    );
    $select = '`'.implode('`,`',$cols).'`';
    $sqlA = "SELECT $select FROM applications
             WHERE appno = ? AND order_status='Success'".
             (($repdistrict!==null && $repdistrict!=='') ? " AND repdistrict=?" : "").
             " LIMIT 1";
    $stmtA = mysqli_prepare($con, $sqlA);
    if ($repdistrict!==null && $repdistrict!=='') {
        mysqli_stmt_bind_param($stmtA, "ss", $appno, $repdistrict);
    } else {
        mysqli_stmt_bind_param($stmtA, "s", $appno);
    }
    mysqli_stmt_execute($stmtA);

    $app = null;
    if (function_exists('mysqli_stmt_get_result')) {
        $res = mysqli_stmt_get_result($stmtA);
        $app = mysqli_fetch_assoc($res);
        if ($res) mysqli_free_result($res);
    } else {
        mysqli_stmt_store_result($stmtA);
        $meta = mysqli_stmt_result_metadata($stmtA);
        $fields = array(); $row = array(); $bindRes = array();
        while ($f = mysqli_fetch_field($meta)) { $fields[] = $f->name; $bindRes[] = &$row[$f->name]; }
        call_user_func_array('mysqli_stmt_bind_result', array_merge(array($stmtA), $bindRes));
        if (mysqli_stmt_fetch($stmtA)) { $app = array(); foreach ($fields as $f) $app[$f] = $row[$f]; }
    }
    mysqli_stmt_close($stmtA);
    if (!$app) { return null; }

    // Helpers
    // $gsb = function($v){
    //     $v = strtoupper(trim((string)$v));
    //     if ($v==='1') return 'G'; if ($v==='2') return 'S'; if ($v==='3') return 'B';
    //     if (in_array($v, array('G','S','B','P','A'), true)) return $v; // include P/A
    //     return 'NL';
    // };

    $gsb = function($v){
    $v = strtoupper(trim((string)$v));
    // Keep known raw codes as-is; avoid mapping 2 -> 'S'
    if (in_array($v, array('1','2','3','P','A','S','F','G','B'), true)) return $v;
    return 'NL';
};


    $genderWord = function($g){
        $g = strtolower(trim((string)$g));
        if (in_array($g, array('f','female','girl','girls','women','woman'), true)) return 'Girls';
        if (in_array($g, array('m','male','boy','boys','men','man'), true))       return 'Boys';
        return ucfirst($g);
    };
    $clubDisplay = ($app['clubname']!=='') ? $app['clubname'] : $app['club'];

    // Maps (matching HTML function)
    $quadMap = array(
        'rink1'=>'RINK - I', 'rink2'=>'RINK - II', 'rink3'=>'RINK - III',
        'road1'=>'ROAD - I', 'road2'=>'ROAD - II'
    );
    $inlineMap = array(
        'p2p'=>'POINTS (TRACK)',
        'elim'=>'ELIMINATION (RINK)',
        'rink4'=>'RINK - IV', 'rink5'=>'RINK - V', 'rink6'=>'RINK - VI', 'rink7'=>'RINK - VII (Dual TT)',
        'road3'=>'ROAD - III', 'road4'=>'ROAD - IV', 'road5'=>'ROAD - V',
        'p2prd'=>'POINT TO POINT (ROAD)', 'elimrd'=>'ELIMINATION (ROAD)',
        'relay'=>'RELAY', 'mixedrelay'=>'MIXED RELAY', 'marathon'=>'MARATHON'
    );
    $artisticMap = array(
        'figure'=>'FIGURE','free'=>'FREE','pair'=>'PAIR','solodance'=>'SOLO DANCE','pairdance'=>'PAIR DANCE',
        'inlinefree'=>'INLINE FREE','quartet'=>'QUARTET','precisionskating'=>'PRECISION SKATING','showgroup'=>'SHOW GROUP'
    );
    $rollerHockeyMap = array(
        'quadhockey'=>'ROLLER HOCKEY','mixedrollerhockey'=>'MIXED ROLLER HOCKEY'
    );
    $inlineHockeyMap = array(
        'inlinehockey'=>'INLINE HOCKEY'
    );
    $freestyleMap = array(
        'speedslalom'=>'SPEED SLALOM','classicslalom'=>'CLASSIC SLALOM','pairslalom'=>'PAIR SLALOM'
    );
    $otherGamesMap = array(
        'alpine'=>'ALPINE','downhill'=>'DOWNHILL','rollerderby'=>'ROLLER DERBY','rollerfreestyle'=>'ROLLER FREESTYLE',
        'skateboarding'=>'SKATEBOARDING','scooter'=>'SCOOTER'
    );

    // Build arrays (keep even P/A; drop only NL)
    $mkArr = function($map) use ($app,$gsb){
        $out = array();
        foreach ($map as $k=>$label) {
            $val = isset($app[$k]) ? $app[$k] : '';
            $code = $gsb($val);
            if ($code==='NL') continue;
            $out[] = array('label'=>$label,'val'=>$code);
        }
        return $out;
    };

    return array(
        'event'  => $evt,
        'skater' => array(
            'appno'=>$app['appno'],
            'name'=>$app['sname'],
            'dob'=>$app['dob'],
            'agegroup'=>$app['agegroup'],
            'gender'=>$genderWord($app['gender']),
            'team'=>$clubDisplay,
            'photo'=>$app['photourl']
        ),
        'quad'         => $mkArr($quadMap),
        'inline'       => $mkArr($inlineMap),
        'artistic'     => $mkArr($artisticMap),
        'rollerhockey' => $mkArr($rollerHockeyMap),
        'inlinehockey' => $mkArr($inlineHockeyMap),
        'freestyle'    => $mkArr($freestyleMap),
        'othergames'   => $mkArr($otherGamesMap)
    );
}


function renderPointsProbables(array $groups, $eventTitle, $discipline, $repdistrict = '') {
    $genderLabel = function($g){
        $gl = strtolower(trim((string)$g));
        if (in_array($gl, array('f','female','girl','girls','women','woman'), true)) return 'Girls';
        if (in_array($gl, array('m','male','boy','boys','men','man'), true))       return 'Boys';
        return $g ?: '';
    };
    $initials = function($name){
        $n = trim($name); if ($n==='') return '';
        $parts = preg_split('/\s+/', $n);
        $first = strtoupper(mb_substr($parts[0],0,1,'UTF-8'));
        $last  = isset($parts[count($parts)-1]) ? strtoupper(mb_substr($parts[count($parts)-1],0,1,'UTF-8')) : '';
        return $first.$last;
    };
    $photoSrc = function($raw){
        $raw = trim((string)$raw);
        if ($raw==='') return '';
        if (strpos($raw, 'data:image/') === 0) return $raw;
        return 'data:image/png;base64,'.$raw;
    };

    date_default_timezone_set('Asia/Kolkata');
    $printedOn = 'Printed On : ' . date('d-m-Y h:i:sa');
    $logoSafe  = preg_replace('/[^A-Za-z0-9_-]/', '_', (string)$repdistrict);
    $logoHtml  = $logoSafe!=='' ? "<div class='logo'><img src=\"districtlogos/".htmlspecialchars($logoSafe,ENT_QUOTES,'UTF-8').".png\" style=\"width:75%;height:auto;\" onerror=\"this.style.display='none'\" /></div>" : "";
    $subtitle  = strtoupper(str_replace('-', ' - ', $discipline)).' - POINTS & PROBABLES';

    $css = <<<CSS
<style>
  *{box-sizing:border-box}
  body{font-family:Arial,sans-serif;font-size:12pt;margin:0.6cm}
  table{border-collapse:collapse;width:100%;table-layout:fixed;margin:6px 0 12px}
  th,td{border:1px solid #444;vertical-align:middle;overflow:hidden}
  th{background:#e6e6e6}

  .header{text-align:center;margin-bottom:6px}
  .header .logo{display:none} @media print{.header .logo{display:block;margin:0 auto 6px}}
  .group{margin:8px 0 12px;break-inside:avoid;page-break-inside:avoid}
  .groupTitle{font-weight:bold;margin:4px 0 6px}

  .w-race{width:52px;text-align:center}
  .w-name{width:28%; padding:6px 8px; white-space:normal; word-break:break-word}
  .w-team{width:16%; padding:6px 8px; white-space:normal; word-break:break-word}

  .vcol{width:24px; text-align:center; font-size:11pt}
  .vcol th, .vcol td { padding:3px 2px !important }
  .vhead{writing-mode:vertical-rl; transform:rotate(180deg); white-space:nowrap; line-height:1}

  .w-pts{width:28px; text-align:center; font-size:11pt}
  .w-prob{width:28px; text-align:center; font-size:11pt}
  .w-pts th, .w-prob th, .w-pts td, .w-prob td { padding:3px 2px !important }

  .namewrap{display:inline-flex;align-items:center;gap:6px}
  .avatar{width:18px;height:18px;border-radius:50%;object-fit:cover;display:inline-block}
  .avatar.initials{background:#ddd;color:#555;font-weight:bold;font-size:9px;display:inline-flex;align-items:center;justify-content:center}

  tr.top3{background:#fff59d}        /* selected slots highlight */
  tr.tie{background:#ffe9cc}         /* tie rows (overlay-ish) */
  tr.top3.tie{background:#ffdca8}    /* tie + selected => deeper tone */

  .footer{display:flex;flex-direction:column;color:#000;font-size:11pt;margin-top:10px}
  .sigrow{display:flex;justify-content:space-between}
  .printed{margin-top:4px;font-size:9pt}
</style>
CSS;

    $out = $css;
    $out .= "<div class='header'>".$logoHtml
          . "<center><h3>".htmlspecialchars($eventTitle,ENT_QUOTES,'UTF-8')."</h3></center>"
          . "<center><h5>".htmlspecialchars($subtitle,ENT_QUOTES,'UTF-8')."</h5></center></div>";

    if (empty($groups)) {
        $out .= "<p>No data.</p>";
    } else {
        foreach ($groups as $G) {
            if (empty($G['items'])) continue;
            $ag = $G['agegroup']; $gLbl = $genderLabel($G['gender']);
            $events = $G['eventCols']; $labels = $G['labels'];

            $out .= "<div class='group'>";
            $out .= "<div class='groupTitle'>".htmlspecialchars($ag,ENT_QUOTES,'UTF-8')." - ".htmlspecialchars($gLbl,ENT_QUOTES,'UTF-8')."</div>";

            $out .= "<table><colgroup><col class='w-race'><col class='w-name'><col class='w-team'>";
            foreach ($events as $_) $out .= "<col class='vcol'>";
            $out .= "<col class='w-pts'><col class='w-prob'></colgroup>";

            // header row (vertical labels for event + points/prob)
            $out .= "<thead><tr>"
                  . "<th class='w-race'>Race&nbsp;No</th>"
                  . "<th class='w-name'>Skater Name</th>"
                  . "<th class='w-team'>Team</th>";
            foreach ($events as $ev) {
                $lab = isset($labels[$ev]) ? $labels[$ev] : strtoupper($ev);
                $out .= "<th class='vcol'><div class='vhead'>".htmlspecialchars($lab,ENT_QUOTES,'UTF-8')."</div></th>";
            }
            $out .= "<th class='w-pts'><div class='vhead'>Points</div></th>"
                  . "<th class='w-prob'><div class='vhead'>Probable</div></th>"
                  . "</tr></thead><tbody>";

            foreach ($G['items'] as $r) {
                $rowCls = array();
                if (!empty($r['prob'])) $rowCls[] = 'top3';
                if (!empty($r['is_tie'])) $rowCls[] = 'tie';
                $cls = empty($rowCls)?'':" class='".implode(' ', $rowCls)."'";

                $src = $photoSrc(isset($r['photo']) ? $r['photo'] : '');
                $avatar = $src!=='' 
                    ? '<img class="avatar" src="'.htmlspecialchars($src,ENT_QUOTES,'UTF-8').'" alt="" onerror="this.style.display=\'none\'">'
                    : '<span class="avatar initials">'.htmlspecialchars($initials($r['name']),ENT_QUOTES,'UTF-8').'</span>';

                $out .= "<tr{$cls}>"
                      .   "<td class='w-race'>".htmlspecialchars($r['chno'],ENT_QUOTES,'UTF-8')."</td>"
                      .   "<td class='w-name'><span class='namewrap'>{$avatar}<span>".htmlspecialchars($r['name'],ENT_QUOTES,'UTF-8')."</span></span></td>"
                      .   "<td class='w-team'>".htmlspecialchars($r['team'],ENT_QUOTES,'UTF-8')."</td>";
                foreach ($events as $ev) {
                    $cell = isset($r['per'][$ev]) && $r['per'][$ev] !== '' ? $r['per'][$ev] : '&nbsp;';
                    $out .= "<td class='vcol'>".$cell."</td>";
                }
                $probTxt = '';
                if (!empty($r['prob'])) {
                    $probTxt = $r['prob'];
                    if (!empty($r['is_tie'])) $probTxt .= ' – Tie';
                }
                $out .=   "<td class='w-pts'>".(int)$r['pts']."</td>"
                      .   "<td class='w-prob'>".htmlspecialchars($probTxt,ENT_QUOTES,'UTF-8')."</td>"
                      . "</tr>";
            }

            $out .= "</tbody></table></div>";
        }
    }

    $out .= "<div class='footer'><div class='sigrow'><span>Sign.</span><span>Chief.</span></div>"
          . "<div class='printed'>".htmlspecialchars($printedOn,ENT_QUOTES,'UTF-8')."</div></div>";

    return $out;
}


function buildPointsProbables(mysqli $db, $discipline, $repdistrict = null) {
    // Column labels
    $labels = array(
        'rink1'=>'RINK - I (1 LAP / 200M)','rink2'=>'RINK - II (500+D)','rink3'=>'RINK - III (1000M)',
        'road1'=>'ROAD - I (1 LAP)','road2'=>'ROAD - II (1500/3000M)',
        'rink4'=>'RINK - IV (1 LAP / 200M)','rink5'=>'RINK - V (500+D)','rink6'=>'RINK - VI (1000M)',
        'rink7'=>'RINK - VII Dual TT (200M)',
        'p2p'=>'POINT TO POINT (TRACK) (5000M)','elim'=>'ELIMINATION (RINK) (10000M)',
        'road3'=>'ROAD - III (100M)','road4'=>'ROAD - IV (1 LAP)','road5'=>'ROAD - V (3000M)',
        'p2prd'=>'POINT TO POINT (ROAD) (10000M)','elimrd'=>'ELIMINATION (ROAD) (15000M)',
        'relay'=>'RELAY (3000M)','mixedrelay'=>'MIXED RELAY (4000M)','marathon'=>'MARATHON'
    );

    // Display + scoring columns per discipline
    if ($discipline === 'Speed-Quad') {
        $displayCols = array('rink1','rink2','rink3','road1','road2');
        $pointsCols  = $displayCols;
    } elseif ($discipline === 'Speed-Inline') {
        // Track points/elim BEFORE road
        $displayCols = array('rink4','rink5','rink6','rink7','p2p','elim','road3','road4','road5','p2prd','elimrd','relay','mixedrelay','marathon');
        // No points for relay/mixedrelay/marathon
        $pointsCols  = array('rink4','rink5','rink6','rink7','p2p','elim','road3','road4','road5','p2prd','elimrd');
    } else {
        throw new InvalidArgumentException('Unknown discipline: '.$discipline);
    }

    // Build query
    $selectCols = implode('`,`', $displayCols);
    $sql = "SELECT appno, chno, sname, club, clubname, agegroup, gender,
                   IFNULL(agorder,999999) AS agorder, `$selectCols`, photourl
            FROM applications
            WHERE skatertype = ?
              AND COALESCE(chno,'') <> ''
              AND order_status='Success'";

    $types = 's';
    $vals  = array($discipline);
    if ($repdistrict !== null && $repdistrict !== '') {
        $sql   .= " AND repdistrict = ?";
        $types .= 's';
        $vals[] = $repdistrict;
    }
    $sql .= " ORDER BY IFNULL(agorder,999999), agegroup, gender, CAST(chno AS UNSIGNED), sname";

    $stmt = mysqli_prepare($db, $sql);
    if (!$stmt) { throw new RuntimeException('Prepare failed: '.mysqli_error($db)); }

    $bind = array(&$types); foreach ($vals as $i => $v) { $bind[] = &$vals[$i]; }
    call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt), $bind));

    if (!mysqli_stmt_execute($stmt)) {
        throw new RuntimeException('Execute failed: '.mysqli_stmt_error($stmt));
    }

    // Fetch
    $rows = array();
    if (function_exists('mysqli_stmt_get_result')) {
        $res = mysqli_stmt_get_result($stmt);
        if ($res) {
            while ($r = mysqli_fetch_assoc($res)) { $rows[] = $r; }
            mysqli_free_result($res);
        }
    } else {
        mysqli_stmt_store_result($stmt);
        $meta = mysqli_stmt_result_metadata($stmt);
        $fields = array(); $row = array(); $bindRes = array();
        if ($meta) {
            while ($f = mysqli_fetch_field($meta)) {
                $fields[] = $f->name;
                $bindRes[] = &$row[$f->name];
            }
            call_user_func_array('mysqli_stmt_bind_result', array_merge(array($stmt), $bindRes));
            while (mysqli_stmt_fetch($stmt)) {
                $r = array();
                foreach ($fields as $f) { $r[$f] = $row[$f]; }
                $rows[] = $r;
            }
        }
    }
    mysqli_stmt_close($stmt);

    // Helpers
    $toGSB = function($v) {
        $v = strtoupper(trim((string)$v));
        if ($v === '1') return 'G';
        if ($v === '2') return 'S';
        if ($v === '3') return 'B';
        if ($v === 'G' || $v === 'S' || $v === 'B') return $v;
        return ''; // ignore P/A/-
    };
    $pointsFor = function($gsb) {
        return ($gsb==='G') ? 5 : (($gsb==='S') ? 3 : (($gsb==='B') ? 1 : 0));
    };
    $probableSlots = function($discipline, $agegroup) {
        $ag = strtolower((string)$agegroup);
        if ($discipline === 'Speed-Inline' && strpos($ag, 'sub') !== false) return 4; // Sub-Junior Inline
        if (strpos($ag, 'cadet') !== false) return 3; // Cadet
        return 3; // default
    };

    // Group by AgeGroup|Gender
    $groups = array();
    foreach ($rows as $r) {
        $key = $r['agegroup'].'|'.$r['gender'];
        if (!isset($groups[$key])) {
            $groups[$key] = array(
                'agegroup' => $r['agegroup'],
                'gender'   => $r['gender'],
                'agorder'  => (int)$r['agorder'],
                'eventCols'=> $displayCols,
                'labels'   => $labels,
                'items'    => array()
            );
        }
        $team = ($r['clubname'] !== '' ? $r['clubname'] : $r['club']);

        $perEvent = array(); $tot=0; $g=0; $s=0; $b=0;
        foreach ($displayCols as $col) {
            $gsb = isset($r[$col]) ? $toGSB($r[$col]) : '';
            $perEvent[$col] = $gsb;
            if (in_array($col, $pointsCols, true)) {
                $pt = $pointsFor($gsb); $tot += $pt;
                if ($gsb==='G') $g++; elseif ($gsb==='S') $s++; elseif ($gsb==='B') $b++;
            }
        }

        $groups[$key]['items'][] = array(
            'appno' => $r['appno'],
            'chno'  => $r['chno'],
            'name'  => $r['sname'],
            'team'  => $team,
            'per'   => $perEvent,
            'pts'   => $tot,
            'g'     => $g,
            's'     => $s,
            'b'     => $b,
            'photo' => isset($r['photourl']) ? $r['photourl'] : ''
        );
    }

    // Filter pts>0, sort, and assign selection with SLOT CONSUMPTION + ties
    foreach ($groups as &$G) {
        // remove zero-point rows
        $G['items'] = array_values(array_filter($G['items'], function($it){ return (int)$it['pts'] > 0; }));
        if (empty($G['items'])) continue;

        // sort by pts desc, then G/S/B counts, then chno asc, then name
        usort($G['items'], function($a,$b){
            if ($a['pts'] !== $b['pts']) return $b['pts'] - $a['pts'];
            if ($a['g']   !== $b['g'])   return $b['g'] - $a['g'];
            if ($a['s']   !== $b['s'])   return $b['s'] - $a['s'];
            if ($a['b']   !== $b['b'])   return $b['b'] - $a['b'];
            $ac=(int)$a['chno']; $bc=(int)$b['chno']; if ($ac!==$bc) return $ac - $bc;
            return strcasecmp($a['name'],$b['name']);
        });

        // Group indices by DISTINCT points (tie blocks)
        $byPoints = array(); // pts => [rowIndex,...]
        foreach ($G['items'] as $idx => $it) {
            $p = (int)$it['pts'];
            if (!isset($byPoints[$p])) $byPoints[$p] = array();
            $byPoints[$p][] = $idx;
        }
        // Highest points first
        krsort($byPoints, SORT_NUMERIC);

        $slots = $probableSlots($discipline, $G['agegroup']); // e.g., 3 or 4
        $roman = array(1=>'I',2=>'II',3=>'III',4=>'IV',5=>'V');

        $consumed = 0;  // how many skaters taken so far
        $rank     = 0;  // I, II, III... by block
        foreach ($byPoints as $p => $idxs) {
            $rank++;
            $blockSize = count($idxs);
            $selected  = ($consumed < $slots); // if still room, take the whole block (tie at cutoff allowed)

            foreach ($idxs as $i) {
                $G['items'][$i]['rank']   = $rank;
                $G['items'][$i]['is_tie'] = ($blockSize > 1);
                $G['items'][$i]['prob']   = ($selected && isset($roman[$rank])) ? $roman[$rank] : '';
            }
            // ties consume all their spots
            $consumed += $blockSize;
        }
    }
    unset($G);

    // Drop empty groups and order groups
    foreach ($groups as $k=>$G) if (empty($G['items'])) unset($groups[$k]);
    uasort($groups, function($A,$B){
        if ($A['agorder'] !== $B['agorder']) return $A['agorder'] - $B['agorder'];
        if ($A['agegroup'] !== $B['agegroup']) return strcmp($A['agegroup'], $B['agegroup']);
        return strcmp($A['gender'], $B['gender']);
    });

    return array_values($groups);
}


// PHP 5.6+ compatible: no scalar type hints
function consolidateResults($db, $racename, $repdistrict = null) {
    // Whitelist event columns you actually store results in
    $allowed = array(
        'rink1','rink2','rink3','road1','road2','rink4','rink5','rink6','rink7',
        'p2p','elim','relay','mixedrelay','road3','road4','road5','p2prd','elimrd',
        'marathon','figure','free','pair','solodance','pairdance','inlinefree',
        'quartet','precisionskating','showgroup','quadhockey','inlinehockey',
        'mixedrollerhockey','speedslalom','pairslalom','classicslalom','alpine',
        'downhill','rollerderby','rollerfreestyle','skateboarding','scooter'
    );
    if (!in_array($racename, $allowed, true)) {
        throw new InvalidArgumentException("Invalid event column: ".$racename);
    }

    // WHERE: medal winners only; chest number NOT required
    $where = "COALESCE(`$racename`, '') IN ('1','2','3')
              AND order_status='Success'";
    $types = '';
    $vals  = array();
    if ($repdistrict !== null && $repdistrict !== '') {
        $where .= " AND repdistrict = ?";
        $types .= 's';
        $vals[] = $repdistrict;
    }

    // Pull medal winners + photourl
    $sql = "
      SELECT
        appno, chno, sname, club, clubname, agegroup, gender,
        IFNULL(agorder, 999999) AS agorder,
        `$racename` AS pos_code,
        photourl
      FROM applications
      WHERE $where
      ORDER BY
        IFNULL(agorder,999999),
        agegroup, gender,
        CAST(`$racename` AS UNSIGNED),
        CAST(NULLIF(chno,'') AS UNSIGNED), chno
    ";

    $stmt = mysqli_prepare($db, $sql);
    if (!$stmt) { throw new RuntimeException('Prepare failed: '.mysqli_error($db)); }
    if ($types !== '') {
        $refs = array(&$types);
        foreach ($vals as $i => $v) { $refs[] = &$vals[$i]; }
        call_user_func_array('mysqli_stmt_bind_param', array_merge(array($stmt), $refs));
    }
    if (!mysqli_stmt_execute($stmt)) {
        throw new RuntimeException('Execute failed: '.mysqli_stmt_error($stmt));
    }

    $rows = array();
    if (function_exists('mysqli_stmt_get_result')) {
        $res = mysqli_stmt_get_result($stmt);
        while ($r = mysqli_fetch_assoc($res)) { $rows[] = $r; }
        if ($res) mysqli_free_result($res);
    } else {
        mysqli_stmt_store_result($stmt);
        mysqli_stmt_bind_result($stmt, $appno, $chno, $sname, $club, $clubname, $agegroup, $gender, $agorder, $pos_code, $photourl);
        while (mysqli_stmt_fetch($stmt)) {
            $rows[] = compact('appno','chno','sname','club','clubname','agegroup','gender','agorder','pos_code','photourl');
        }
    }
    mysqli_stmt_close($stmt);

    // Group + team points
    $groups = array();
    foreach ($rows as $r) {
        $key = $r['agegroup'].'|'.$r['gender'];
        if (!isset($groups[$key])) {
            $groups[$key] = array(
                'agegroup'   => $r['agegroup'],
                'gender'     => $r['gender'],
                'agorder'    => (int)$r['agorder'],
                'items'      => array(),
                'scoreboard' => array()
            );
        }
        $pos   = (string)$r['pos_code']; // 1/2/3
        $team  = ($r['clubname'] !== '' ? $r['clubname'] : $r['club']);
        $pts   = ($pos==='1') ? 5 : (($pos==='2') ? 3 : 1);

        $groups[$key]['items'][] = array(
            'appno' => $r['appno'],
            'chno'  => $r['chno'],       // may be empty now
            'name'  => $r['sname'],
            'team'  => $team,
            'pos'   => $pos,
            'photo' => $r['photourl'],
        );
        if (!isset($groups[$key]['scoreboard'][$team])) { $groups[$key]['scoreboard'][$team] = 0; }
        $groups[$key]['scoreboard'][$team] += $pts;
    }

    foreach ($groups as &$G) {
        usort($G['items'], function($a,$b){
            $pa = (int)$a['pos']; $pb = (int)$b['pos'];
            if ($pa !== $pb) return $pa - $pb;
            // safe compare on chno even if empty/non-numeric
            $ca = (int)$a['chno']; $cb = (int)$b['chno'];
            if ($ca !== $cb) return $ca - $cb;
            return strcasecmp($a['name'], $b['name']);
        });
        $sb = array();
        foreach ($G['scoreboard'] as $team => $p) { $sb[] = array('team'=>$team,'points'=>$p); }
        usort($sb, function($a,$b){
            if ($a['points'] !== $b['points']) return $b['points'] - $a['points'];
            return strcasecmp($a['team'], $b['team']);
        });
        $G['scoreboard'] = $sb;
    } unset($G);

    uasort($groups, function($A,$B){
        if ($A['agorder'] !== $B['agorder']) return $A['agorder'] - $B['agorder'];
        if ($A['agegroup'] !== $B['agegroup']) return strcmp($A['agegroup'], $B['agegroup']);
        return strcmp($A['gender'], $B['gender']);
    });

    return array_values($groups);
}


function renderConsolidatedResults($groups, $eventTitle, $racename, $repdistrict = '') {
    // Helpers
    $mapGender = function($g) {
        $gl = strtolower(trim((string)$g));
        if (in_array($gl, array('f','female','girl','girls','women','woman'), true)) return 'Girls';
        if (in_array($gl, array('m','male','boy','boys','men','man'), true))       return 'Boys';
        return $g ?: '';
    };
    $rowClass = function($pos) {
        if ($pos==='1') return 'res-first';
        if ($pos==='2') return 'res-second';
        if ($pos==='3') return 'res-third';
        return 'res-none';
    };
    $medalIcon = function($pos) {
        if ($pos==='1') return '🥇';
        if ($pos==='2') return '🥈';
        if ($pos==='3') return '🥉';
        return '';
    };
    $initials = function($name){
        $n = trim($name);
        if ($n==='') return '';
        $parts = preg_split('/\s+/', $n);
        $first = strtoupper(mb_substr($parts[0],0,1,'UTF-8'));
        $last  = isset($parts[count($parts)-1]) ? strtoupper(mb_substr($parts[count($parts)-1],0,1,'UTF-8')) : '';
        return $first . $last;
    };
    $photoSrc = function($raw){
        $raw = trim((string)$raw);
        if ($raw==='') return '';
        if (strpos($raw, 'data:image/') === 0) return $raw; // already a data URL
        return 'data:image/png;base64,'. $raw;              // assume base64 PNG blob
    };

    // Build ONE overall team-points table by summing all group scoreboards
    $overallMap = array();
    foreach ($groups as $G) {
        if (empty($G['scoreboard'])) continue;
        foreach ($G['scoreboard'] as $row) {
            $t = (string)$row['team'];
            $p = (int)$row['points'];
            if (!isset($overallMap[$t])) $overallMap[$t] = 0;
            $overallMap[$t] += $p;
        }
    }
    $overall = array();
    foreach ($overallMap as $team=>$pts) $overall[] = array('team'=>$team,'points'=>$pts);
    usort($overall, function($a,$b){
        if ($a['points'] !== $b['points']) return $b['points'] - $a['points'];
        return strcasecmp($a['team'], $b['team']);
    });

    // Header/footer bits
    date_default_timezone_set('Asia/Kolkata');
    $printedOn = 'Printed On : ' . date('d-m-Y h:i:sa');
    $logoSafe = preg_replace('/[^A-Za-z0-9_-]/', '_', (string)$repdistrict);
    $logoHtml = $logoSafe !== ''
        ? "<div class='logo'><img src=\"districtlogos/".htmlspecialchars($logoSafe, ENT_QUOTES, 'UTF-8').".png\" alt=\"\" style=\"width:75%;height:auto;\" onerror=\"this.style.display='none'\" /></div>"
        : "";

    // CSS
    $css = <<<CSS
<style>
  body { font-family: Arial, sans-serif; font-size: 12pt; margin: 0.6cm; }
  h3, h4, h5 { margin: 4px 0; }
  table { border-collapse: collapse; width: 100%; margin: 6px 0 10px; table-layout: fixed; }
  th, td { border: 1px solid #444; padding: 6px 8px; text-align: left; vertical-align: middle; overflow: hidden; }
  th, td { white-space: nowrap; }

  .cell-name { white-space: normal; word-break: break-word; }
  .namewrap { display: inline-flex; align-items: center; gap: 8px; }
  .avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; display: inline-block; vertical-align: middle; }
  .avatar.initials {
    background: #ddd; color: #555; font-weight: bold; font-size: 11px;
    display: inline-flex; align-items: center; justify-content: center;
  }
  .cell-team { text-overflow: ellipsis; }

  /* Results table column widths (no Timing) */
  .r-col-app{width:14%}.r-col-chno{width:12%}.r-col-name{width:42%}.r-col-team{width:22%}.r-col-pos{width:10%;text-align:center}

  .header  { text-align: center; margin-bottom: 6px; }
  .header .logo { display: none; }  /* hide logo on screen */
  @media print { .header .logo { display: block; margin: 0 auto 6px; } }

  .group { margin: 10px 0 12px; break-inside: avoid; page-break-inside: avoid; }
  .group h4 { margin: 2px 0 6px; }

  .footer { display: flex; flex-direction: column; color: #000; font-size: 11pt; margin-top: 10px; }
  .sigrow { display: flex; justify-content: space-between; }
  .printed { margin-top: 4px; font-size: 9pt; }

  /* Row colors for positions */
  tr.res-first{background:#fff3c4}
  tr.res-second{background:#eceff4}
  tr.res-third{background:#f6e0d5}
  tr.res-none{background:#fff}
  tr.res-first td:first-child{border-left:4px solid #ffd700}
  tr.res-second td:first-child{border-left:4px solid #c0c0c0}
  tr.res-third td:first-child{border-left:4px solid #cd7f32}

  .medal{font-size:12pt}

  /* Overall scoreboard */
  .scoreboard { width: 60%; margin: 12px auto 6px; }
  .scoreboard th, .scoreboard td { text-align: left; }
  .scoreboard th.rank, .scoreboard td.rank { width: 12%; text-align: center; }
  .scoreboard th.points, .scoreboard td.points { width: 20%; text-align: right; }

  @media print {
    table, .group { break-inside: avoid; page-break-inside: avoid; }
  }
</style>
CSS;

    $out = $css;

    // One header
    $out .= "<div class='header'>"
          .   $logoHtml
          .   "<center><h3>".htmlspecialchars($eventTitle, ENT_QUOTES, 'UTF-8')."</h3></center>"
          .   "<center><h5>".htmlspecialchars(strtoupper($racename), ENT_QUOTES, 'UTF-8')." RESULTS</h5></center>"
          . "</div>";

    // All age-group results
    if (empty($groups)) {
        $out .= "<p>No medal results found.</p>";
    } else {
        foreach ($groups as $G) {
            $ag   = $G['agegroup'];
            $gLbl = $mapGender($G['gender']);

            $out .= "<div class='group'>\n";
            $out .= "  <h4>Age Group : ".htmlspecialchars($ag, ENT_QUOTES, 'UTF-8')
                  .  " - ".htmlspecialchars($gLbl, ENT_QUOTES, 'UTF-8')."</h4>\n";
            $out .= "  <table>\n";
            $out .= "    <colgroup><col class='r-col-app'><col class='r-col-chno'><col class='r-col-name'><col class='r-col-team'><col class='r-col-pos'></colgroup>\n";
            $out .= "    <thead><tr><th>Appno</th><th>Race No</th><th>Name</th><th>Team</th><th>Position</th></tr></thead>\n";
            $out .= "    <tbody>\n";

            foreach ($G['items'] as $r) {
                $cls   = $rowClass($r['pos']);
                $icon  = $medalIcon($r['pos']);
                $src   = $photoSrc($r['photo']);
                if ($src !== '') {
                    $avatar = '<img class="avatar" src="'.htmlspecialchars($src, ENT_QUOTES, 'UTF-8').'" alt="Photo of '.htmlspecialchars($r['name'], ENT_QUOTES, 'UTF-8').'" onerror="this.style.display=\'none\'">';
                } else {
                    $avatar = '<span class="avatar initials">'.htmlspecialchars($initials($r['name']), ENT_QUOTES, 'UTF-8').'</span>';
                }

                $out .= "      <tr class='{$cls}'>"
                      . "        <td>".htmlspecialchars($r['appno'], ENT_QUOTES, 'UTF-8')."</td>"
                      . "        <td>".htmlspecialchars($r['chno'], ENT_QUOTES, 'UTF-8')."</td>"
                      . "        <td class='cell-name'><span class='namewrap'>{$avatar}<span class='medal'>{$icon}</span><span>".htmlspecialchars($r['name'], ENT_QUOTES, 'UTF-8')."</span></span></td>"
                      . "        <td class='cell-team' title=\"".htmlspecialchars($r['team'], ENT_QUOTES, 'UTF-8')."\">".htmlspecialchars($r['team'], ENT_QUOTES, 'UTF-8')."</td>"
                      . "        <td class='r-col-pos'>".htmlspecialchars($r['pos'], ENT_QUOTES, 'UTF-8')."</td>"
                      . "      </tr>\n";
            }

            $out .= "    </tbody>\n";
            $out .= "  </table>\n";
            $out .= "</div>\n";
        }
    }

    // Overall Team Points (moved BELOW results)
    if (!empty($overall)) {
        $out .= "<h4 style='text-align:center;margin-top:8px;'>Team Points (Overall) &nbsp; <small>(5/3/1)</small></h4>";
        $out .= "<table class='scoreboard'>"
              .   "<thead><tr><th class='rank'>Rank</th><th>Team</th><th class='points'>Points</th></tr></thead><tbody>";
        $rank = 1;
        foreach ($overall as $row) {
            $out .= "<tr>"
                  .   "<td class='rank'>".$rank++."</td>"
                  .   "<td>".htmlspecialchars($row['team'], ENT_QUOTES, 'UTF-8')."</td>"
                  .   "<td class='points'>".(int)$row['points']."</td>"
                  . "</tr>";
        }
        $out .= "</tbody></table>";
    } else {
        $out .= "<p style='text-align:center;margin:8px 0;'>No medal results found for team points.</p>";
    }

    // Footer
    $out .= "<div class='footer'>"
          .   "<div class='sigrow'><span>Sign.</span><span>Chief.</span></div>"
          .   "<div class='printed'>".htmlspecialchars($printedOn, ENT_QUOTES, 'UTF-8')."</div>"
          . "</div>";

    return $out;
}
function scoresheet($db, $event, $maxPerHeat, $repdistrict = null) {
    // allowed event columns
    $allowed = [
         'rink1', 'rink2', 'rink3', 'road1', 'road2', 'rink4', 'rink5', 'rink6', 'rink7', 'p2p', 'elim', 'relay', 'mixedrelay', 'road3', 'road4', 'road5', 'p2prd', 'elimrd', 'marathon', 'figure', 'free', 'pair','solodance', 'pairdance', 'inlinefree', 'quartet', 'precisionskating', 'showgroup', 'quadhockey', 'inlinehockey', 'mixedrollerhockey',  'speedslalom', 'pairslalom', 'classicslalom', 'alpine', 'downhill', 'rollerderby', 'rollerfreestyle', 'skateboarding', 'scooter'
    ];
    if (!in_array($event, $allowed, true)) {
        throw new InvalidArgumentException("Invalid event column: ".$event);
    }
    $W = (int)$maxPerHeat;
    if ($W <= 0) throw new InvalidArgumentException("maxPerHeat must be > 0");

    // events that REQUIRE chest number
    $requiresChnoSet = [
        'rink1','rink2','rink3','rink4','rink5','rink6','rink7',
        'road1','road2','road3','road4','road5',
        'p2p','elim','relay','mixedrelay','p2prd','elimrd','marathon'
    ];
    $requiresChno = in_array($event, $requiresChnoSet, true);

    // WHERE
    $where = "COALESCE($event, '') <> '' AND $event NOT IN ('0','No')";
    if ($requiresChno) {
        $where .= " AND COALESCE(chno, '') <> ''";      // only for speed/track events
    }
    $where .= " AND order_status = 'Success'";

    $bindTypes = '';
    $bindVals  = [];
    if ($repdistrict !== null && $repdistrict !== '') {
        $where     .= " AND repdistrict = ?";
        $bindTypes .= 's';
        $bindVals[] = $repdistrict;
    }

    // Fetch rows (include event column as result_code)
    $sql = "
        SELECT
            appno, chno, sname, club, clubname, repdistrict,
            skaterid, dob, age, agegroup, gender,
            IFNULL(agorder, 999999) AS agorder,
            `$event` AS result_code
        FROM applications
        WHERE $where
        ORDER BY
            IFNULL(agorder, 999999),
            agegroup, gender,
            CAST(chno AS UNSIGNED), chno
    ";
    $stmt = mysqli_prepare($db, $sql);
    if (!$stmt) throw new RuntimeException('Prepare failed: '.mysqli_error($db));
    if ($bindTypes !== '') {
        $refs = [ &$bindTypes ];
        foreach ($bindVals as $i => $v) { $refs[] = &$bindVals[$i]; }
        call_user_func_array('mysqli_stmt_bind_param', array_merge([$stmt], $refs));
    }
    if (!mysqli_stmt_execute($stmt)) {
        throw new RuntimeException('Execute failed: '.mysqli_stmt_error($stmt));
    }

    $base = [];
    if (function_exists('mysqli_stmt_get_result')) {
        $res = mysqli_stmt_get_result($stmt);
        while ($row = mysqli_fetch_assoc($res)) $base[] = $row;
        if ($res) mysqli_free_result($res);
    } else {
        mysqli_stmt_store_result($stmt);
        mysqli_stmt_bind_result(
            $stmt, $appno, $chno, $sname, $club, $clubname, $repdistrictOut,
            $skaterid, $dob, $age, $agegroup, $gender, $agorder, $result_code
        );
        while (mysqli_stmt_fetch($stmt)) {
            $base[] = compact(
                'appno','chno','sname','club','clubname','repdistrictOut',
                'skaterid','dob','age','agegroup','gender','agorder','result_code'
            );
        }
    }
    mysqli_stmt_close($stmt);

    // Group and serpentine assign
    $out = [];
    $currKey = null; $group = [];

    $flushGroup = function() use (&$out, &$group, $W) {
        $n = count($group); if ($n === 0) return;
        $H = (int)ceil($n / $W);
        $assigned = [];
        for ($i = 0; $i < $n; $i++) {
            $col  = intdiv($i, $H);
            $row  = $i % $H;
            $heat = ($col % 2 === 0) ? ($row + 1) : ($H - $row);
            $lane = $col + 1;
            $r = $group[$i];
            $assigned[] = [
                'agegroup'     => $r['agegroup'],
                'gender'       => $r['gender'],
                'heat_no'      => $heat,
                'lane_no'      => $lane,
                'appno'        => $r['appno'],
                'chno'         => $r['chno'],
                'sname'        => $r['sname'],
                'club'         => $r['club'],
                'clubname'     => $r['clubname'],
                'repdistrict'  => isset($r['repdistrictOut']) ? $r['repdistrictOut'] : $r['repdistrict'],
                'skaterid'     => $r['skaterid'],
                'dob'          => $r['dob'],
                'age'          => $r['age'],
                'result_code'  => isset($r['result_code']) ? $r['result_code'] : '',
            ];
        }
        usort($assigned, function($a, $b){
            if ($a['heat_no'] === $b['heat_no']) return $a['lane_no'] <=> $b['lane_no'];
            return $a['heat_no'] <=> $b['heat_no'];
        });
        foreach ($assigned as $row) $out[] = $row;
        $group = [];
    };

    foreach ($base as $row) {
        $key = $row['agegroup'].'|'.$row['gender'].'|'.$row['agorder'];
        if ($currKey !== null && $key !== $currKey) { $flushGroup(); }
        $group[] = $row; $currKey = $key;
    }
    $flushGroup();

    return $out;
}

function renderScoresheet( array $rows, mysqli $con, $raceTitle = 'Start List', $racename = '', $repdistrict = '', $eventTitle='' ) {

    if (!$rows) return "<p>No entries.</p>";

    $eventCol     = (string)$racename;
    $safeEventCol = htmlspecialchars($eventCol, ENT_QUOTES, 'UTF-8');

    // events that REQUIRE chest number (used to decide whether to show the column)
    $requiresChnoSet = array_flip([
        'rink1','rink2','rink3','rink4','rink5','rink6','rink7',
        'road1','road2','road3','road4','road5',
        'p2p','elim','relay','mixedrelay','p2prd','elimrd','marathon'
    ]);
    $requiresChno = isset($requiresChnoSet[$eventCol]);

    // Gender label
    $mapGender = function($g) {
        $gl = strtolower(trim((string)$g));
        if (in_array($gl, ['f','female','girl','girls','women','woman'], true)) return 'Girls';
        if (in_array($gl, ['m','male','boy','boys','men','man'], true))       return 'Boys';
        return $g ?: '';
    };

    // Position text (now includes S & F)
    $mapPos = function($code) {
        $c = strtoupper(trim((string)$code));
        if ($c === '1') return 'First';
        if ($c === '2') return 'Second';
        if ($c === '3') return 'Third';
        if ($c === 'S') return 'Selected';
        if ($c === 'F') return 'Forward';
        if ($c === 'P') return 'Participated';
        if ($c === 'A') return 'Absent';
        return 'Not Reported';
    };

    // Row CSS class
    $mapRowClass = function($code) {
        $c = strtoupper(trim((string)$code));
        if ($c === '1') return 'res-first';
        if ($c === '2') return 'res-second';
        if ($c === '3') return 'res-third';
        if ($c === 'S') return 'res-selected';
        if ($c === 'F') return 'res-forward';
        if ($c === 'P') return 'res-participated';
        if ($c === 'A') return 'res-absent';
        return 'res-none';
    };

    // IST timestamp
    date_default_timezone_set('Asia/Kolkata');
    $printedOn = 'Printed On : ' . date('d-m-Y h:i:sa');

    // Print-only header logo
    $logoSafe = preg_replace('/[^A-Za-z0-9_-]/', '_', (string)$repdistrict);
    $logoHtml = $logoSafe !== ''
        ? "<div class='logo'><img src=\"districtlogos/".htmlspecialchars($logoSafe, ENT_QUOTES, 'UTF-8').".png\" alt=\"\" style=\"width:75%;height:auto;\" onerror=\"this.style.display='none'\" /></div>"
        : "";

    $css = <<<CSS
<style>
  body { font-family: Arial, sans-serif; font-size: 12pt; }
  h2, h3, h4, h5 { margin: 6px 0; }
  table { border-collapse: collapse; width: 100%; margin: 8px 0 14px; table-layout: fixed; }
  th, td { border: 1px solid #444; padding: 6px 8px; text-align: left; vertical-align: top; overflow: hidden; }
  th, td { white-space: nowrap; }
  .cell-name, .cell-remarks { white-space: normal; word-break: break-word; }
  .cell-club { text-overflow: ellipsis; }
  .cell-chno { font-weight: bold; }
  th.th-chno { font-weight: bold; }

  /* Column widths when Ch.No. is present */
  .col-lane    { width: 8%;  }
  .col-chno    { width: 12%; }
  .col-name    { width: 30%; }
  .col-club    { width: 22%; }
  .col-remarks { width: 12%; }
  .col-pos     { width: 10%; }
  .col-result  { width: 16%; } /* screen only */

  /* Alternate widths when Ch.No. is hidden */
  .no-chno .col-lane   { width: 9%; }
  .no-chno .col-name   { width: 36%; }
  .no-chno .col-club   { width: 27%; }
  .no-chno .col-remarks{ width: 13%; }
  .no-chno .col-pos    { width: 15%; }
  .no-chno .col-result { width: 18%; }

  .page { page-break-after: always; min-height: 96vh; display: flex; flex-direction: column; margin-bottom: 16px; }
  @media print { .page { page-break-after: always; } }

  .header  { text-align: center; margin-bottom: 6px; }
  .header .logo { display: none; }
  @media print { .header .logo { display: block; margin: 0 auto 6px; } }

  .content { flex: 1 1 auto; }
  .heatTitle { margin: 4px 0; font-size: 11.5pt; }

  .footer { display: flex; flex-direction: column; color: #000; font-size: 11pt; margin-top: 12px; }
  .sigrow { display: flex; justify-content: space-between; }
  .printed { margin-top: 4px; font-size: 9pt; }

  .btns { display: flex; gap: 4px; flex-wrap: wrap; }
  .res-btn { font-size: 10pt; padding: 2px 6px; cursor: pointer; border: 1px solid #666; background: #f6f6f6; }
  .res-btn.gold   { background: #ffd700; }
  .res-btn.silver { background: #c0c0c0; }
  .res-btn.bronze { background: #cd7f32; color: #fff; border-color: #a15b23; }
  .res-btn.sel    { background: #e3f2fd; }     /* Selected */
  .res-btn.fwd    { background: #ede7f6; }     /* Forward  */
  .res-btn.chosen { box-shadow: inset 0 0 0 2px #000; }

  @media print {
    /* Hide live controls; keep Position column structure */
    .td-pos { color: transparent; }
    .col-result, td.col-result, th.col-result, .btns, .res-btn { display: none !important; }
  }

  /* Row colors */
  tr.res-first         { background-color: #fff3c4; }
  tr.res-second        { background-color: #eceff4; }
  tr.res-third         { background-color: #f6e0d5; }
  tr.res-selected      { background-color: #e8f3ff; } /* light blue */
  tr.res-forward       { background-color: #f0eaff; } /* light purple */
  tr.res-participated  { background-color: #eaf7ea; }
  tr.res-absent        { background-color: #fdecea; }
  tr.res-none          { background-color: #ffffff; }

  tr.res-first td:first-child        { border-left: 4px solid #ffd700; }
  tr.res-second td:first-child       { border-left: 4px solid #c0c0c0; }
  tr.res-third td:first-child        { border-left: 4px solid #cd7f32; }
  tr.res-selected td:first-child     { border-left: 4px solid #1976d2; }
  tr.res-forward td:first-child      { border-left: 4px solid #7e57c2; }
  tr.res-participated td:first-child { border-left: 4px solid #2e7d32; }
  tr.res-absent td:first-child       { border-left: 4px solid #c62828; }
</style>
CSS;

    $out = $css;

    $currKey  = null;
    $currHeat = null;
    $openTable = false;
    $openPage  = false;

    foreach ($rows as $r) {
        $ag   = $r['agegroup'];
        $gRaw = $r['gender'];
        $gLbl = $mapGender($gRaw);
        $heat = (int)$r['heat_no'];
        $key  = $ag . '|' . $gRaw;

        $codeRaw = isset($r['result_code']) ? $r['result_code'] : (isset($r[$eventCol]) ? $r[$eventCol] : '');
        $ucCode  = strtoupper(trim((string)$codeRaw));
        $posText = $mapPos($ucCode);
        $rowCls  = $mapRowClass($ucCode);

        // New page (agegroup, gender)
        if ($currKey !== $key) {
            if ($openTable) { $out .= "</tbody></table>\n"; $openTable = false; }
            if ($openPage)  {
                $out .= "</div><!-- .content -->\n";
                $out .= "<div class='footer'>"
                      .   "<div class='sigrow'><span>Sign.</span><span>Chief.</span></div>"
                      .   "<div class='printed'>".htmlspecialchars($printedOn, ENT_QUOTES, 'UTF-8')."</div>"
                      . "</div>\n";
                $out .= "</div><!-- .page -->\n";
                $openPage = false;
            }

            $currKey  = $key;
            $currHeat = null;

            $pageCls = $requiresChno ? '' : ' no-chno';
            $out .= "<div class='page{$pageCls}' data-event=\"{$safeEventCol}\">\n";
            $out .= "<div class='header'>"
                  . $logoHtml
                  . "<center><h3>".htmlspecialchars($eventTitle, ENT_QUOTES, 'UTF-8')."</h3></center>"
                  . "<center><h5>".htmlspecialchars($raceTitle, ENT_QUOTES, 'UTF-8')." - RACE CHART</h5></center>"
                  . "</div>\n";
            $out .= "<div class='content'>\n";
            $out .= "<h3>".htmlspecialchars($ag, ENT_QUOTES, 'UTF-8')." - ".htmlspecialchars($gLbl, ENT_QUOTES, 'UTF-8')."</h3>\n";
            $openPage = true;
        }

        // Heat table
        if ($currHeat !== $heat) {
            if ($openTable) { $out .= "</tbody></table>\n"; }
            $currHeat = $heat;

            // Build header with/without Ch.No.
            if ($requiresChno) {
                $out .= "<div class='heatTitle'>Heat {$heat}</div>\n";
                $out .= "<table>"
                      . "<colgroup>"
                      . "<col class='col-lane'><col class='col-chno'><col class='col-name'>"
                      . "<col class='col-club'><col class='col-remarks'><col class='col-pos'><col class='col-result'>"
                      . "</colgroup>"
                      . "<thead><tr>"
                      . "<th>Lane</th><th class='th-chno'>Ch.No.</th><th>Name</th>"
                      . "<th>Team</th><th>Timing/Remarks</th><th class='th-pos'>Position</th><th class='col-result'>Result</th>"
                      . "</tr></thead><tbody>\n";
            } else {
                $out .= "<div class='heatTitle'>Heat {$heat}</div>\n";
                $out .= "<table>"
                      . "<colgroup>"
                      . "<col class='col-lane'><col class='col-name'><col class='col-club'>"
                      . "<col class='col-remarks'><col class='col-pos'><col class='col-result'>"
                      . "</colgroup>"
                      . "<thead><tr>"
                      . "<th>Lane</th><th>Name</th><th>Team</th>"
                      . "<th>Timing/Remarks</th><th class='th-pos'>Position</th><th class='col-result'>Result</th>"
                      . "</tr></thead><tbody>\n";
            }
            $openTable = true;
        }

        $team = ($r['clubname'] !== '' ? $r['clubname'] : $r['club']);
        $appnoAttr = (int)$r['appno'];

        // Preselect buttons
        $sel1 = ($ucCode === '1') ? ' chosen' : '';
        $sel2 = ($ucCode === '2') ? ' chosen' : '';
        $sel3 = ($ucCode === '3') ? ' chosen' : '';
        $selS = ($ucCode === 'S') ? ' chosen' : '';
        $selF = ($ucCode === 'F') ? ' chosen' : '';
        $selP = ($ucCode === 'P') ? ' chosen' : '';
        $selA = ($ucCode === 'A') ? ' chosen' : '';

        $out .= "<tr class=\"{$rowCls}\" data-appno=\"{$appnoAttr}\">"
              . "<td>".(int)$r['lane_no']."</td>";
        if ($requiresChno) {
            $out .= "<td class='cell-chno'>".htmlspecialchars($r['chno'], ENT_QUOTES, 'UTF-8')."</td>";
        }
        $out .= "<td class='cell-name'>".htmlspecialchars($r['sname'], ENT_QUOTES, 'UTF-8')."</td>"
              . "<td class='cell-club' title=\"".htmlspecialchars($team, ENT_QUOTES, 'UTF-8')."\">".htmlspecialchars($team, ENT_QUOTES, 'UTF-8')."</td>"
              . "<td class='cell-remarks'></td>"
              . "<td class='td-pos'>".htmlspecialchars($posText, ENT_QUOTES, 'UTF-8')."</td>"
              . "<td class='col-result'>"
              .   "<div class='btns'>"
              .     "<button type='button' class='res-btn gold{$sel1}'   data-code='1' data-event='{$safeEventCol}'>Gold</button>"
              .     "<button type='button' class='res-btn silver{$sel2}' data-code='2' data-event='{$safeEventCol}'>Silver</button>"
              .     "<button type='button' class='res-btn bronze{$sel3}' data-code='3' data-event='{$safeEventCol}'>Bronze</button>"
              .     "<button type='button' class='res-btn sel{$selS}'    data-code='S' data-event='{$safeEventCol}'>Selected</button>"
              .     "<button type='button' class='res-btn fwd{$selF}'    data-code='F' data-event='{$safeEventCol}'>Forward</button>"
              .     "<button type='button' class='res-btn{$selP}'        data-code='P' data-event='{$safeEventCol}'>Participated</button>"
              .     "<button type='button' class='res-btn{$selA}'        data-code='A' data-event='{$safeEventCol}'>Absent</button>"
              .   "</div>"
              . "</td>"
              . "</tr>\n";
    }

    if ($openTable) { $out .= "</tbody></table>\n"; }
    if ($openPage)  {
        $out .= "</div><!-- .content -->\n";
        $out .= "<div class='footer'>"
              .   "<div class='sigrow'><span>Sign.</span><span>Chief.</span></div>"
              .   "<div class='printed'>".htmlspecialchars($printedOn, ENT_QUOTES, 'UTF-8')."</div>"
              . "</div>\n";
        $out .= "</div><!-- .page -->\n";
    }

    // JS: update Position + row color + selection state
    $out .= <<<JS
<script>
(function(){
  function labelFor(code){
    switch(String(code).toUpperCase()){
      case '1': return 'First';
      case '2': return 'Second';
      case '3': return 'Third';
      case 'S': return 'Selected';
      case 'F': return 'Forward';
      case 'P': return 'Participated';
      case 'A': return 'Absent';
      default:  return 'Not Reported';
    }
  }
  function classFor(code){
    switch(String(code).toUpperCase()){
      case '1': return 'res-first';
      case '2': return 'res-second';
      case '3': return 'res-third';
      case 'S': return 'res-selected';
      case 'F': return 'res-forward';
      case 'P': return 'res-participated';
      case 'A': return 'res-absent';
      default:  return 'res-none';
    }
  }
  function clearResClasses(tr){
    ['res-first','res-second','res-third','res-selected','res-forward','res-participated','res-absent','res-none']
      .forEach(function(c){ tr.classList.remove(c); });
  }

  document.addEventListener('click', function(e){
    var t = e.target;
    if(!t.classList.contains('res-btn')) return;
    var tr = t.closest('tr');
    if(!tr) return;
    var appno = tr.getAttribute('data-appno');
    var code  = t.getAttribute('data-code');
    var page = t.closest('.page');
    var eventCol = (t.getAttribute('data-event') || (page && page.getAttribute('data-event')) || '');
    if(!eventCol){ alert('Missing event column.'); return; }

    var cell = t.closest('td');
    cell.querySelectorAll('button').forEach(function(b){ b.disabled = true; });

    var body = 'appno=' + encodeURIComponent(appno) +
               '&event=' + encodeURIComponent(eventCol) +
               '&code='  + encodeURIComponent(code);

    fetch('update_result.php', {
      method: 'POST',
      headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},
      body: body,
      cache: 'no-store'
    }).then(function(r){ return r.json(); })
      .then(function(j){
        cell.querySelectorAll('button').forEach(function(b){ b.disabled = false; b.classList.remove('chosen'); });
        if(j && j.ok){
          t.classList.add('chosen');
          var posCell = tr.querySelector('.td-pos');
          if (posCell) posCell.textContent = labelFor(code);
          clearResClasses(tr);
          tr.classList.add(classFor(code));
        }else{
          alert('Update failed' + (j && j.error ? ': ' + j.error : '.'));
        }
      }).catch(function(){
        cell.querySelectorAll('button').forEach(function(b){ b.disabled = false; });
        alert('Network error. Please retry.');
      });
  });
})();
</script>
JS;

    return $out;
}

function assignchestno()
{
include('dbconnect.php');
set_time_limit (1200);
	/*$databaseQuery = 'UPDATE applications AS t
JOIN
(
    SELECT @rownum:=@rownum+1 rownum,appno,club,skatertype,CONVERT(agorder,UNSIGNED INTEGER),gender,CONVERT(appno,UNSIGNED INTEGER) 
    FROM applications
    CROSS JOIN (select @rownum := 0) rn
  where status != "delete" AND skatertype LIKE "Speed%%" order by club,skatertype,CONVERT(agorder,UNSIGNED INTEGER),gender desc,CONVERT(appno,UNSIGNED INTEGER) 
) AS r ON t.appno = r.appno
SET t.skaterid =r.rownum';*/
$dt=$_SESSION['teamf'];

$dbqs='SELECT @rownum:=@rownum+1 rownum,appno,club,skatertype,CONVERT(agorder,UNSIGNED INTEGER),gender,CONVERT(appno,UNSIGNED INTEGER) 
    FROM applications
    CROSS JOIN (select @rownum := 100) rn
  where repdistrict="'.$dt.'" AND status != "Delete" AND status != "Rejected" AND (order_status="Success") AND ((skatertype LIKE "Speed%%") OR (skatertype LIKE "Tenacity")) order by club,skatertype desc,CONVERT(agorder,UNSIGNED INTEGER),gender desc,CONVERT(appno,UNSIGNED INTEGER) ';
  
  $selectresult = mysqli_query($con,$dbqs) or die('Query failed: ' . mysqli_error());
 // echo $dbqs;
  while($row = mysqli_fetch_array($selectresult))
  {
	  $chno=$row['rownum'];
	  $appno=$row['appno'];
	  
	  $updateq ='update applications set chno='.$chno.' where appno='.$appno.' and (chno="" or chno is NULL)';

	$updateresult = mysqli_query($con,$updateq) or die('Query failed: ' . mysqli_error());
	echo $chno." ".$appno." ".$con -> affected_rows."<br/>";
	  
  }


echo mysqli_num_rows($selectresult);

	

}

function sendform($appno)
{


    include('dbconnect.php');

    $databaseQuery = 'SELECT appno, sname, email, hashcode FROM applications WHERE appno = "' . mysqli_real_escape_string($con, $appno) . '"';
    $result = mysqli_query($con, $databaseQuery) or die('Query failed - Send Form: ' . mysqli_error($con));

    if ($result && $row = mysqli_fetch_array($result)) {
        $appno = $row["appno"];
        $sname = $row["sname"];
        $email = $row["email"];
        $key   = $row["hashcode"];

        $content = '<html><body><b>Dear Skater '.$sname.',<br/><br/></b><br/>
Your registration is complete.<br/><br/>

You can download your <b>TAMILNADU DISTRICT CHAMPIONSHIPS – 2025 - Entry Form </b> in the following link.<br/>

<a href="https://tamilnaduskate.com/tndistricts2025/application.php?appno='.$appno.'&k='.$key.'">Click Here to Print / Download Application Form</a>
<br/></b><br/>
Please contact your District / State Unit for further details and approval.
Thanks & Regards<br/><br/>
TNRSA<br/>
tamilnaduskate.com
</body></html>';

        $mail = new PHPMailer(true);
        try {
            // SMTP settings
            $mail->isSMTP();
            $mail->Host       = 'mail.tamilnaduskate.com';
            $mail->SMTPAuth   = true;
            $mail->Username   = 'office@tamilnaduskate.com';
            $mail->Password   = 'priority1@1';
            $mail->SMTPSecure = ''; // no encryption
            $mail->Port       = 25;

            // $mail->SMTPDebug = 2; // optional debug
            // $mail->Debugoutput = 'html';

            // Recipients
            $mail->setFrom('office@tamilnaduskate.com', 'TNRSA');
            $mail->addAddress($email, $sname);
         //   $mail->addBCC('jeganonly@gmail.com');

            // Content
            $mail->isHTML(true);
            $mail->Subject = $sname." |Entry Form ".$appno." | TAMILNADU DISTRICT CHAMPIONSHIPS - 2025";
            $mail->Body    = $content;

            $mail->send();
            $mailres = "Success";
        } catch (Exception $e) {
            $mailres = "Mailer Error: " . $mail->ErrorInfo;
        }

        $qtext = 'UPDATE applications SET emailstatus="' . mysqli_real_escape_string($con, $mailres) . '" WHERE appno = "' . $appno . '"';
        mysqli_query($con, $qtext);
    }
}

function sendformold($appno)
{
include('dbconnect.php');
$databaseQuery = 'SELECT appno,sname,email,hashcode FROM applications where (appno= "'.$appno.'")';
$result = mysqli_query($con,$databaseQuery) or die('Query failed: ' . mysqli_error());
if($result)
{

	$row = mysqli_fetch_array($result);

$appno=$row["appno"];
$sname=$row["sname"];
$email=$row["email"];
$key=$row["hashcode"];

$content='<html><body><b>Dear Skater '.$sname.',<br/><br/></b><br/>
Your registration is complete.<br/><br/>

You can download your <b>TAMILNADU DISTRICT CHAMPIONSHIPS – 2025 - Entry Form </b> in the following link.<br/>

<a href="https://tamilnaduskate.com/tndistricts2025/application.php?appno='.$appno.'&k='.$key.'">Click Here to Print / Download Application Form</a>
<br/></b><br/>
Please contact your District / State Unit for further details and approval.
Thanks & Regards<br/><br/>
TNRSA<br/>
tamilnaduskate.com
</body></html>';


//$to = "jeganonly@gmail.com,krishnamani_k@yahoo.com,vishnuamalraj@yahoo.com";
$to =$email;
//$to =$email.",jeganonly@gmail.com";
//$to ="jeganonly@gmail.com";
$subject = $sname." |Entry Form ".$appno." | TAMILNADU DISTRICT CHAMPIONSHIPS – 2025";

$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";
$headers .= "From: office@tamilnaduskate.com" . "\r\n" ;
//$headers .= "Bcc: jeganonly@gmail.com"; //disable later

$mailres=mail($to,$subject,$content,$headers);


$qtext='UPDATE applications SET emailstatus="'.$mailres.'" WHERE appno = "'.$appno.'"';
	//	echo $qtext;
		 mysqli_query($con,$qtext) or mysqli_error();
			

			

}



}


function listskaterbase()
{

	include('dbconnect.php');
	
	$dt=$_SESSION['username'];
	if($dt=="secretary")
	{
		$dt=$_SESSION['teamf'];
	//	$dt="Chennai";
	}
	//$qtext='SELECT appno, sname, dob, agegroup, gender, club from skaterbase_'.strtolower($_SESSION['username']).' where status != "delete"';

	$qtext='SELECT appno, sname, dob, agegroup, gender, clubname as club from tdrsc2021 where status != "delete"';

	//where clubname="'.strtolower($_SESSION['username']).'" AND

//	echo $qtext;
$result3 = mysqli_query($con,$qtext) or die('Query failed: ' . mysqli_error());
				while($row = mysqli_fetch_array($result3))
  {
	  
	    $appno=trim($row["appno"]);
 $sname=trim($row["sname"]);
$dob=trim($row["dob"]);
$ag=trim($row["agegroup"])." ".trim($row["gender"]);
$club=trim($row["club"]);
//$photo="http://".$_SERVER[HTTP_HOST]."/oldpics/".trim($row["Photo"]);
$gender=trim($row["gender"]);
echo '<li><a href="#" onclick="loadprof(\''.$appno.'\');">'.$sname." | ".$dob." | ".$club.' </a></li>';

  }
}

function listentries($stypesel,$teamfilter=NULL,$del=NULL)
{   
    include('dbconnect.php');


    
    $delstatus = "";
    if ($del=="hidedelete") {
        $delstatus='AND status != "delete" ';
    }

    $stype = $stypesel;
    $dt = "";
    $club = $_SESSION["username"];

    if ($club=="secretary") {
        $team = "%";
        $dt = $teamfilter;
    } else {
        if ($club=="") { loginbox(); return; }
        $team = $club;
    }

    $usertype = $_SESSION["usertype"];
    if ($usertype=="District") {
   $team=$teamfilter;
        if($team=="All Entries")
        {
           $team = "%"; 
        }
        $dt   = $_SESSION["currentdistrict"];

        if($dt=="")
        {
            $_SESSION["currentdistrict"]=$dt;
            $dt=$_SESSION["username"];;

        }


    } else if ($usertype=="Club") {
        $team = $_SESSION["username"];
        $dt   = $_SESSION["currentdistrict"];
    }

        if($team=="All Entries")
        {
           $team = "%"; 
        }

    if ($stype!="Other") {
        $databaseQuery = 'SELECT * FROM applications WHERE (skatertype like "%'.$stype.'%") and (club like "%'.$con->real_escape_string($team).'%")and (repdistrict like "%'.$con->real_escape_string($dt).'%") '.$delstatus.' AND (order_status="Success")  order by agorder+0,gender desc,skatertype,club,CONVERT(appno,UNSIGNED INTEGER)';
    } else {
        $databaseQuery = 'SELECT * FROM applications WHERE (otherdiscipline <> "") and (club like "%'.$con->real_escape_string($team).'%") and (repdistrict like "%'.$con->real_escape_string($dt).'%")'.$delstatus.' AND (order_status="Success")   order by skatertype,agorder+0,gender desc,club,CONVERT(appno,UNSIGNED INTEGER)';
    }

    $result3 = mysqli_query($con,$databaseQuery) or die('Query failed: ' . mysqli_error());
    date_default_timezone_set('Asia/Kolkata');

    echo '<p class="font2"> ' .mysqli_num_rows($result3) . ' Results found for "'.$dt."-".$team.'-'.$stype.'" as on '.date("d-m-Y h:i:sa").' </p>';
    echo '<title>'.$team.'-'.$stype.'</title>';

    if ($_SESSION['usertype']=="Club") {
        echo '<a href="print.php?stype='.$stype.'" target="_blank" class="noprint ui-btn ui-btn-raised  ui-btn ui-btn-inline waves-effect waves-button waves-effect waves-button" ><i class="zmdi zmdi-print zmd-2x"></i> Print Entry Form</a>';
    } else if($_SESSION['username']=="secretary" || $_SESSION['usertype']=="District") {
        echo '<a href="print-list.php?stype='.$stype.'" target="_blank" class="noprint ui-btn ui-btn-raised  ui-btn ui-btn-inline waves-effect waves-button waves-effect waves-button" ><i class="zmdi zmdi-print zmd-2x"></i> Print List</a>';
    }

    echo '<table id="listtable" data-role="table" data-mode="columntoggle" style="overflow-x: auto; width:90%;"    class="ui-responsive table-stroke">';
    echo '<thead>';

    if ($stype=="all") {
        echo '<tr class="th-groups" >
            <th colspan="4" data-priority="1" style="height:auto !important; text-align:center;">Skater Details</th>
            <th colspan="2" data-priority="5" style="height:auto !important; text-align:center;" >DOB & Age</th>
            <th colspan="2" data-priority="2" style="height:auto !important; text-align:center;">Age Group</th>
            <th colspan="1" data-priority="6" style="height:auto !important; text-align:center;">Representing Team</th>
            <th colspan="2" data-priority="1" style="height:auto !important; text-align:center;">Tenacity</th>
            <th colspan="2" data-priority="1" style="height:auto !important; text-align:center;">Under 5 Quad</th>
            <th colspan="2" data-priority="1" style="height:auto !important; text-align:center;">Under 5 Inline</th>
            <th colspan="4" data-priority="1" style="height:auto !important; text-align:center;">Quad Events</th>
            <th colspan="10" data-priority="1" style="height:auto !important; text-align:center;">Inline Events</th>
            <th colspan="1" data-priority="4" style="height:auto !important; text-align:center;">Comments</th>
        </tr>';
    }

    echo '<tr>
        <th><div class="verticalText">Sl.No.</div></th>';

    if ($stype=="Speed-Quad"|| $stype=="Speed-Inline" || $stype=="Tenacity" || $stype=="Under5-Quad" || $stype=="Under5-Inline") {
        echo '<th><div>Race No.</div></th>';
    }

    echo '<th><div class="verticalText">AppNo</div></th>
        <th><div>Status</div></th>
        <th><div>RSFI App.no.</div></th>
        <th ><div style=" width:120px;">Skater Name</div></th>
        <th><div>Date_of_Birth</div></th>
        <th><div>Age</div></th>
        <th><div>AgeGroup</div></th>
        <th><div>Gender</div></th>
        <th><div>Representing Team</div></th>';

    if ($_SESSION['username']=="secretary" || $_SESSION['usertype']=="District" || $_SESSION['usertype']=="Club") {
        echo '<th class="noprint"><div class="noprint">Edit</div></th>';
    }

    echo '<th class="noprint"><div class="noprint">Delete</div></th>';

    if ($stype=="Tenacity" || $stype=="all") {
        echo '<th><div class="verticalText">Race 1</div></th>
              <th><div class="verticalText">Race 2</div></th>';
    }
    if ($stype=="Under5-Quad" || $stype=="all") {
        echo '<th><div class="verticalText">Under 5- Quad Race 1</div></th>
              <th><div class="verticalText">Under 5-Quad Race 2</div></th>';
    }
    if ($stype=="Under5-Inline" || $stype=="all") {
        echo '<th><div class="verticalText">Under 5- Inline Race 1</div></th>
              <th><div class="verticalText">Under 5- Inline Race 2</div></th>';
    }
    if ($stype=="Speed-Quad"|| $stype=="all") {
        echo '<th><div class="verticalText">Rink - I<br/>(1 Lap  [200M])</div></th>
              <th><div class="verticalText">Rink - II<br/>(2 Lap / 500+D)</div></th>
              <th><div class="verticalText">Rink - III<br/>(3 Lap / 4 Lap / 1000 M)</div></th>
              <th><div class="verticalText">Road - I<br/>(1 Lap)</div></th>
              <th><div class="verticalText">Road - II<br/>(1500 / 3000 M)</div></th>';
    }
    if ($stype=="Speed-Inline"|| $stype=="all") {
        echo '<th><div class="verticalText">Rink - IV<br/>(1 Lap [200M])</div></th>
              <th><div class="verticalText">Rink - V<br/>(500+D)</div></th>
              <th><div class="verticalText">Rink - VI<br/>(1000 M)</div></th>
              <th><div class="verticalText">Rink - VII<br/>DUAL TT(200 M)</div></th>
              <th><div class="verticalText">Points Track (5000 M)</div></th>
              <th><div class="verticalText">Elimination - Rink (10000 M)</div></th>
              <th><div class="verticalText">Road - III (100 M)</div></th>
              <th><div class="verticalText">Road - IV (1 Lap)</div></th>
              <th><div class="verticalText">Road - V (3000 M)</div></th>
              <th><div class="verticalText">Point to Point - Road (10000 M)</div></th>
              <th><div class="verticalText">Elimination - Road (15000 M)</div></th>
              <th><div class="verticalText">Relay (3000M)</div></th>
              <th><div class="verticalText">Mixed Relay (4000M)</div></th>';
    }
    if ($stype=="Artistic") {
        echo '<th><div class="verticalText">Figure</div></th>
              <th><div class="verticalText">Free</div></th>
              <th><div class="verticalText">Pair</div></th>
              <th><div class="verticalText">Partner Name</div></th>
              <th><div class="verticalText">Solodance</div></th>
              <th><div class="verticalText">Coupledance</div></th>
              <th><div class="verticalText">Partner Name</div></th>
              <th><div class="verticalText">Inlinefree</div></th>
              <th><div class="verticalText">Quartet</div></th>
              <th><div class="verticalText">ShowGroup</div></th>
              <th><div class="verticalText">Precision</div></th>';
    }
    if ($stype=="Roller-Hockey") {
        echo '<th><div class="verticalText">Roller Hockey</div></th>
        <th><div class="verticalText">Roller Hockey - Mixed</div></th>
              <th><div class="verticalText">Position</div></th>
              <th><div class="verticalText">Jersey No.</div></th>';
    }
    if ($stype=="Roller-Hockey" || $stype=="Inline-Hockey") {
        echo '<th><div class="verticalText">Inline Hockey</div></th>
              <th><div class="verticalText">Position</div></th>
              <th><div class="verticalText">Jersey No.</div></th>';
    }
    if ($stype=="Inline-Freestyle") {
        echo '<th><div class="verticalText">Classic Slalom</div></th>
              <th><div class="verticalText">Speed Slalom</div></th>
              <th><div class="verticalText">Pair Slalom</div></th>';
    }
    if ($stype=="Other") {
        echo '<th><div class="verticalText">Main Discipline</div></th>
              <th><div class="verticalText">Other Discipline</div></th>
              <th><div class="verticalText">Alpine</div></th>
              <th><div class="verticalText">Downhill</div></th>
              <th><div class="verticalText">Roller Derby</div></th>
              <th><div class="verticalText">Roller Freestyle</div></th>
              <th><div class="verticalText">Skateboarding</div></th>
              <th><div class="verticalText">Scooter</div></th>';
    }

    echo '<th><div class="verticalText">Comments</div></th>';
    echo '</tr></thead>';

    $twocol=0;  
    $itcount=0;
    $curag=""; $curgender=""; $curteam="";

    $rink1cnt=0; $rink2cnt=0; $road1cnt=0; $road2cnt=0; $quadskaterscnt=0;
    $rink3cnt=0; $rink4cnt=0; $rink5cnt=0; $rink6cnt=0; $rink7cnt=0;
    $road3cnt=0; $road4cnt=0; $road5cnt=0; $p2pcnt=0; $rinkelimcnt=0; $p2prdcnt=0;
    $roadelimcnt=0; $relaycnt=0; $mixedrelaycnt=0; $inlineskaterscnt=0;
    $rollerhockeycnt=0; $inlinehockeycnt=0;

    echo '<tbody>';
    $slno=0;

    // helper: normalize event result to 1/2/3/P/A/-
    $normalize = function($v){
        $c = strtoupper(trim((string)$v));
        return in_array($c, ['1','2','3','P','A','S','F']) ? $c : '-';
    };

    while($row = mysqli_fetch_array($result3)) {
        $status = trim($row["status"]);
        $slno++;

        $appno   = trim($row["appno"]);
        $sname   = trim($row["sname"]);
        $hashcode= trim($row["hashcode"]);
        $discipline = trim($row["skatertype"]);
        $otherdiscipline = trim($row["otherdiscipline"]);
        if ($otherdiscipline=='on') { $otherdiscipline="Yes"; }

        if ($discipline=="Speed-Quad")  { $quadskaterscnt++; }
        if ($discipline=="Speed-Inline"){ $inlineskaterscnt++; }

        $skaterid= trim($row["skaterid"]);
        $chno    = trim($row["chno"]);
        $dob     = trim($row["dob"]);
        $age     = trim($row["age"]);
        $ag      = trim($row["agegroup"]);

        if ($discipline=="Roller-Hockey") {
            if ($age<9) { $ag="6 to 9 - Cadet Tiny Tots"; }
             if ($age>=9 && $age<12) { $ag="9 to 12 - Cadet"; }
            $rollerhockeycnt++;
        }
        if ($discipline=="Inline-Hockey") {
             if ($age<9) { $ag="6 to 9 - Cadet Tiny Tots"; }
             if ($age>=9 && $age<12) { $ag="9 to 12 - Cadet"; }
            $inlinehockeycnt++;
        }

        $gender   = trim($row["gender"]);
        $club     = trim($row["club"]);
        $clubname = trim($row["clubname"]);
        $school   = trim($row["school"]);

        $residingstate   = trim($row["residingstate"]);
        $residingdistrict= trim($row["residingdistrict"]);
        $repstate        = trim($row["repstate"]);
        $repdistrict     = trim($row["repdistrict"]);
        $fathername      = trim($row["fathername"]);
        $address         = trim($row["address"]);
        $address2        = trim($row["address2"]);
        $city            = trim($row["city"]);
        $pin             = trim($row["pin"]);
        $phone           = trim($row["phone"]);
        $email           = trim($row["email"]);
        $blood           = trim($row["bloodgroup"]);
        $comments        = trim($row["comments"]);
        $payref          = trim($row["payref"]);
        $paystatus       = trim($row["paystatus"]);

        $nodob = "";
        $doburl= trim($row["doburl"]);
        if ($doburl=='NA') { $nodob="true"; }
        $pwd = trim($row["aadhaarpass"]);

        $position = trim($row["hockeyplayertype"]);
        $jerseyno = trim($row["jerseyno"]);

        // ---- RESULT-CODE aware mapping + counters (1/2/3/P/A/-)
        // helper that also increments counters for 1/2/3/P (not for A/-)
        $setAndCount = function($raw, &$cnt) use ($normalize, $status){
            $code = $normalize($raw);
            if ($status!="Delete" && in_array($code, ['1','2','3','P','S','F'])) { $cnt++; }
            return $code;
        };

        $adjrink1 = $normalize($row["adjrink1"]);
        $adjrink2 = $normalize($row["adjrink2"]);
        $adjrink3 = $normalize($row["adjrink3"]);

        $u8race1q = $normalize($row["u8race1q"]);
        $u8race2q = $normalize($row["u8race2q"]);
        $u8race1i = $normalize($row["u8race1i"]);
        $u8race2i = $normalize($row["u8race2i"]);

        $rink1 = $setAndCount($row["rink1"], $rink1cnt);
        $rink2 = $setAndCount($row["rink2"], $rink2cnt);
        $rink3 = $setAndCount($row["rink3"], $rink3cnt);
        $road1 = $setAndCount($row["road1"], $road1cnt);

        $rink4 = $setAndCount($row["rink4"], $rink4cnt);
        $rink5 = $setAndCount($row["rink5"], $rink5cnt);
        $rink6 = $setAndCount($row["rink6"], $rink6cnt);
        $rink7 = $normalize($row["rink7"]); // no counter needed here by your previous logic

        $road2 = $setAndCount($row["road2"], $road2cnt);
        $road3 = $setAndCount($row["road3"], $road3cnt);
        $road4 = $setAndCount($row["road4"], $road4cnt);
        $road5 = $setAndCount($row["road5"], $road5cnt);

        $p2p   = $setAndCount($row["p2p"], $p2pcnt);

        // use rinkelimcnt (not undefined $elimcnt)
        $elim  = $setAndCount($row["elim"], $rinkelimcnt);

        $p2prd = $setAndCount($row["p2prd"], $p2prdcnt);
        $elimrd= $setAndCount($row["elimrd"], $roadelimcnt);

        $relay      = $setAndCount($row["relay"], $relaycnt);
        $mixedrelay = $setAndCount($row["mixedrelay"], $mixedrelaycnt);

        $figure     = $normalize($row["figure"]);
        $free       = $normalize($row["free"]);
        $combined   = $normalize($row["combined"]);
        $pair       = $normalize($row["pair"]);
        $pairpartnername = trim($row["pairpartnername"]);
        $pairpartnerag   = trim($row["pairpartnerag"]);
        $inlinefree = $normalize($row["inlinefree"]);
        $solodance  = $normalize($row["solodance"]);
        $pairdance  = $normalize($row["pairdance"]);
        $quartet    = $normalize($row["quartet"]);
        $coupledancepartnername = trim($row["coupledancepartnername"]);
        $coupledancepartnerag   = trim($row["coupledancepartnerag"]);
        $quadhockey = $normalize($row["quadhockey"]);
        $mixedhockey = $normalize($row["mixedrollerhockey"]);
        $inlinehockey = $normalize($row["inlinehockey"]);

        $classicslalom = $normalize($row["classicslalom"]);
        $speedslalom   = $normalize($row["speedslalom"]);
        $pairslalom    = $normalize($row["pairslalom"]);

        $alpine        = $normalize($row["alpine"]);
        $downhill      = $normalize($row["downhill"]);
        $rollerderby   = $normalize($row["rollerderby"]);
        $rollerfreestyle = $normalize($row["rollerfreestyle"]);
        $skateboarding = $normalize($row["skateboarding"]);
        $precision     = $normalize($row["precisionskating"]);
        $showgroup     = $normalize($row["showgroup"]);
        $scooter       = $normalize($row["scooter"]);

        // row background by status (unchanged)
        $bgc="";
        if ($status=="Approved by state") { $bgc="Lime"; }
        if ($status=="Rejected")          { $bgc="grey"; }
        if ($status=="Verified By Dt")    { $bgc="LightGreen"; }
        if ($status=="Pending")           { $bgc="Red"; }
        if ($status=="Held")              { $bgc="Yellow"; }
        if ($status=="Delete")            { $bgc="LightGrey"; }

        if ($curag!=$ag || $curgender!=$gender) {
            if ($rollerhockeycnt>10) {
                echo '<tr style="background-color:red; color:white;"><td colspan=8>Error! More than 10 skaters in a '.$curag.' '.$curgender.' Team. </td></tr>';
            }
            if ($inlinehockeycnt>12) {
                echo '<tr style="background-color:red; color:white;"><td colspan=8>Error! More than 12 skaters in a '.$curag.' '.$curgender.' Team. </td></tr>';
            }
            $rollerhockeycnt=0;
            $inlinehockeycnt=0;

            echo '<tr style="background-color:#e6ffe6;"><td colspan=8><h5 style="-webkit-margin-after:0.5em !important; -webkit-margin-before:0.67em !important;"><b>'.$ag.' '.$gender.'</b></h5></td></tr>';   
            $curag=trim($ag);
            $curgender=trim($gender);
            $curteam=trim($club);
        }

        echo '<tr style="background-color:'.$bgc.'"><td>'.$slno.'</td>';
        if ($stype=="Speed-Quad"|| $stype=="Speed-Inline" || $stype=="Tenacity" || $stype=="Under5-Quad" || $stype=="Under5-Inline") {
            echo '<td><b>'.$chno.'</b></td>';
        }

        echo '<td>'.$appno.'</td>
              <td id="status'.$appno.'">'.$status.'</td>
              <td>'.$skaterid.'</td>
              <td style=" text-align:left;">'.$sname.'<br/>'.$phone.'</td>
              <td>'.$dob.'</td>
              <td>'.$age.'</td>
              <td>'.$ag.'</td>
              <td>'.$gender.'</td>
              <td style="white-space: nowrap; text-overflow:ellipsis; overflow: hidden; max-width:100px; width:80%;">'.$club.'</td>';

        if ($_SESSION['username']=="secretary" || $_SESSION['usertype']=="District" || $_SESSION['usertype']=="Club") {
            echo '<td class="noprint"><a href="#" onclick="editapp('.$appno.');"  data-rel="popup" data-position-to="window" data-role="button" class="ui-btn ui-btn-inline ui-mini ui-btn-raised">Edit</a></td>';
        }

        echo '<td class="noprint"><a href="#" onclick="deleteapp('.$appno.');"  data-rel="popup" data-position-to="window" data-role="button" class="ui-btn ui-btn-inline ui-mini ui-btn-raised color-red">Delete</a></td>';

        if ($stype=="Tenacity" || $stype=="all") {
            echo '<td>'.$adjrink1.'</td><td>'.$adjrink2.'</td>';
        }
        if ($stype=="Under5-Quad" || $stype=="all") {
            echo '<td>'.$u8race1q.'</td><td>'.$u8race2q.'</td>';
        }
        if ($stype=="Under5-Inline" || $stype=="all") {
            echo '<td>'.$u8race1i.'</td><td>'.$u8race2i.'</td>';
        }
        if ($stype=="Speed-Quad" || $stype=="all") {
            echo '<td>'.$rink1.'</td><td>'.$rink2.'</td><td>'.$rink3.'</td><td>'.$road1.'</td><td>'.$road2.'</td>';
        }
        if ($stype=="Speed-Inline" || $stype=="all") {
            echo '<td style="border-left:1px solid black !important;">'.$rink4.'</td><td>'.$rink5.'</td><td>'.$rink6.'</td><td>'.$rink7.'</td><td>'.$p2p.'</td><td>'.$elim.'</td><td>'.$road3.'</td><td>'.$road4.'</td><td>'.$road5.'</td><td>'.$p2prd.'</td><td>'.$elimrd.'</td><td>'.$relay.'</td><td>'.$mixedrelay.'</td>';
        }
        if ($stype=="Artistic") {
            echo '<td>'.$figure.'</td><td>'.$free.'</td><td>'.$pair.'</td><td>'.$pairpartnername.'<br/>'.$pairpartnerag.'</td><td>'.$solodance.'</td><td>'.$pairdance.'</td><td>'.$coupledancepartnername.'<br/>'.$coupledancepartnerag.'</td><td>'.$inlinefree.'</td><td>'.$quartet.'</td><td>'.$showgroup.'</td><td>'.$precision.'</td>';
        }
        if ($stype=="Roller-Hockey") {
            echo '<td>'.$quadhockey.'</td><td>'.$mixedrollerhockey.'</td>';
            echo '<td>'.$position.'</td><td>'.$jerseyno.'</td>';
        }
        if ($stype=="Inline-Hockey") {
            echo '<td>'.$inlinehockey.'</td>';
            echo '<td>'.$position.'</td><td>'.$jerseyno.'</td>';
        }
        if ($stype=="Inline-Freestyle") {
            echo '<td>'.$classicslalom.'</td><td>'.$speedslalom.'</td><td>'.$pairslalom.'</td>';
        }
        if ($stype=="Other") {
            echo '<td>'.$discipline.'</td>';
            echo '<td>'.$otherdiscipline.'</td>';
            echo '<td>'.$alpine.'</td>';
            echo '<td>'.$downhill.'</td>';
            echo '<td>'.$rollerderby.'</td>';
            echo '<td>'.$rollerfreestyle.'</td>';
            echo '<td>'.$skateboarding.'</td>';
            echo '<td>'.$scooter.'</td>';
        }

        echo '<td> '.$comments.' </td></tr>';
    }

    // reset counters
    $rink1cnt=0; $rink2cnt=0; $road1cnt=0; $road2cnt=0; $quadskaterscnt=0;
    $rink3cnt=0; $rink4cnt=0; $road3cnt=0; $road4cnt=0; $road5cnt=0; $p2pcnt=0; $rinkelimcnt=0; $p2prdcnt=0;
    $roadelimcnt=0; $relaycnt=0; $mixedrelaycnt=0; $inlineskaterscnt=0; $rollerhockeycnt=0; $inlinehockeycnt=0;

    echo '</tbody>';  
    echo "</table>";
}

 ?>