<?PHP
//
// Erzeugt einen HTML Stundenplan
//

/*

    This file was written by Thorsten Gunkel <tgunkel@gmx.de>
    for <url:http://www.tgunkel.de>.
    Copyright (C) 2003-2004 Thorsten Gunkel

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation version 2 of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

/* diese Funktion mit einer passenden csv Datei aufrufen.
   echo stundenplanausgabe('meinedate.csv');
   Aufbau der CSV:
   "ID","FACHNAME","BEGIN","ENDE","RAUM","URL","WOCHENTAG","DOZENT"
   "ID","FACHNAME",...
   Beispiel:
   "Mathe","01","09.50","11.30","123A","http://..",2,"Mueller"
*/
function stundenplanausgabe($filename)
{
  
$stundenplan=array();  // der Stundenplan
  
$zeiten=array();       // alle Zeitspannen die im Stundenplan vorkommen
  
$mehrbelegung=array(); // wieviel Veranstaltungen passieren an einem Tag maximal parallel
  
$doppelt=array();

  
// Daten einlesen
  
$handle fopen ($filename,"r");
  while (
$data fgetcsv ($handle1000","))
    {
      
$neuepos=count($stundenplan);
      
$stundenplan[$neuepos]['ID']=$data[0];
      if (isset(
$doppelt[$stundenplan[$neuepos]['ID']]))
        
$doppelt[$stundenplan[$neuepos]['ID']]++;
      else
        
$doppelt[$stundenplan[$neuepos]['ID']]=1;
      
$stundenplan[$neuepos]['Fach']=$data[1];
      
// Was das wohl mal sollte?: if ($bis<$von) $bis=$von;
      
$stundenplan[$neuepos]['Von']=$data[2];
      
$stundenplan[$neuepos]['Bis']=$data[3];
      
$stundenplan[$neuepos]['Raum']=$data[4];
      
$stundenplan[$neuepos]['Link']=$data[5];
      if ((
$data[6]<1) || ($data[6]>6)) $data[6]=7;
      
$stundenplan[$neuepos]['Wochentag']=$data[6];
      
$stundenplan[$neuepos]['Betreuer']=$data[7];
      
$zeiten=update_times($zeiten,$stundenplan[$neuepos]['Von'],$stundenplan[$neuepos]['Bis']);
    }
  
$zeiten=add_pausen($zeiten);
  
$mehrbelegung=mehrbelegung($stundenplan,$zeiten);

  
// Wie oft kommt jede Veranstaltung vor?
  
for ($i1=0$i1<count($stundenplan); $i1++)
    {
      
$stundenplan[$i1]['doppelt']=$doppelt[$stundenplan[$i1]['ID']];
    }
  unset(
$doppelt);

  
$tagesnamen=array("","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag");
 
  
// Tabelle ausgeben
  
$tmp_txt='';
  
$tmp_txt.='<table border="1" style="empty-cells:hide;">'."\n";
  
$tmp_txt.=' <tr>'."\n";
  if (
count($zeiten)>0)
    
$tmp_txt.='  <th>Zeiten</th>'."\n";
  else
    
$tmp_txt.='  <th>Leerer Stundenplan</th>'."\n";
  
// Nur belegte Tage ausgeben, Spalten breit genug machen
  
for ($i1=1$i1<=7$i1++)
    if (
$mehrbelegung[$i1]>0)
      
$tmp_txt.='  <th colspan="'.$mehrbelegung[$i1].'">'.$tagesnamen[$i1].'</th>'."\n";
  
$tmp_txt.=' </tr>'."\n";
  
// Jeder Zeitraum ist eine Zeile
  
for ($i1=0$i1<count($zeiten); $i1++)
    {
      
$tmp_txt.=' <tr>'."\n";;
      
$tmp_txt.='  <td>';
      
$tmp_txt.=$zeiten[$i1]['von']." - ".$zeiten[$i1]['bis'];
      
$tmp_txt.='  </td>'."\n";;
      
// Jeder Tag ist eine Spalte
      
for ($i3=1$i3<=7$i3++)
    {
      
// Alle Faecher durchsuchen
      
for ($i2=0$i2<count($stundenplan); $i2++)
        {
          if ((
$i3==$stundenplan[$i2]['Wochentag']) &&(start_times($zeiten,$i1,$stundenplan[$i2]['Von'])))
        {
          
$tmp_txt.='  <td rowspan="'.sizeof_times($zeiten,$stundenplan[$i2]['Von'],$stundenplan[$i2]['Bis']).'">'."\n";
          
$tmp_txt.=printentry($stundenplan,$i2);
          
$tmp_txt.="  </td>"."\n";
        }
        }
      
// gegebenenfalls Spalte mit leeren Zellen auffuellen
      
for ($i4=0$i4<($mehrbelegung[$i3]-mehrbelegung_prozeitraum($stundenplan,$zeiten,$i1,$i3)); $i4++)
        
$tmp_txt.='<td></td>';
    }
      
$tmp_txt.=' </tr>'."\n";
    }
  
$tmp_txt.='</table>'."\n";
  return 
$tmp_txt;
}

// gibt es die Zeitspanne schon?
function uniq_times($zeiten,$von,$bis)
{
  for (
$i1=0$i1<count($zeiten); $i1++)
    {
      if ((
$zeiten[$i1]['von']==$von) && ($zeiten[$i1]['bis']==$bis))
    return 
$i1;
    }
  return -
1;
}

// liegt der Zeitraum 'pos' zwischen 'von' und 'bis'
function within_times($zeiten,$pos,$von,$bis)
{
  if ((
$pos>=0) && ($pos<count($zeiten)))
    if ((
$zeiten[$pos]['von']>=$von) && ($zeiten[$pos]['bis']<=$bis))
      return 
true;
  return 
false;
}


// ist der Zeitraum pos derjenige, der mit 'von' startet?
function start_times($zeiten,$pos,$von)
{
  
// guelltiges pos?
  
if (($pos>=0) && ($pos<count($zeiten)))
    
// Startzeiten stimmen?
    
if ($zeiten[$pos]['von']==$von)
      
// und der Zeitraum davor wuerde nicht passen?
      
if (($pos==0) || ($zeiten[$pos-1]['von']!=$von)) return true;
  return 
false;
}

// wieviel Zeitspannen umfasst 'von' -> 'bis'?
function sizeof_times($zeiten,$von,$bis)
{
  
$ergb=0;
  for (
$i1=0$i1<count($zeiten); $i1++)
    {
      if (
within_times($zeiten,$i1,$von,$bis)) $ergb++;
    }
  return 
$ergb;
}

// zwischen nicht direkt anschliessenden Zeiten Pausen einfuegen
function add_pausen($zeiten)
{
  for (
$i1=0; ($i1+1)<count($zeiten); $i1++)
    {
      
// Luecke zwischen 2 Zeiten ist neue Pause
      
if ($zeiten[$i1]['bis']!=$zeiten[$i1+1]['von'])
    
$zeiten=add_times($zeiten,$zeiten[$i1]['bis'],$zeiten[$i1+1]['von']);
    }
  return 
$zeiten;
}

// Findet raus wieviel Veranstaltungen zu einem gegeben Zeitpunkt gleichzeitg stattfinden
function mehrbelegung_prozeitraum($stundenplan,$zeiten,$pos,$tag)
{
  
$anzahl=0;
  
// Gueltige pos?
  
if (($pos>=0) && ($pos<count($zeiten)))
    {
      
// alle Faecher ansehen
      
for ($i1=0$i1<count($stundenplan); $i1++)
    {
      
// wenn aktuelles Fach im Zeitraum liegt +1
      
if ( ($stundenplan[$i1]['Wochentag']==$tag) && (within_times($zeiten,$pos,$stundenplan[$i1]['Von'],$stundenplan[$i1]['Bis'])) )
        
$anzahl++;
    }
    }
  return 
$anzahl;
}

// stellt fuer jeden Tag fest wieviele Veranstaltungen maximal gleichzeitig stattfinden
function mehrbelegung($stundenplan,$zeiten)
{
  
$mehrbelegung=array("",0,0,0,0,0,0,0);
  
// alle Tage ansehen
  
for ($i2=1$i2<=7$i2++)
    {
      
$maxvalue=0;
      
// alle Zeitspannen ansehen
      
for ($i1=0$i1<count($zeiten); $i1++)
    {
      if (
$maxvalue<mehrbelegung_prozeitraum($stundenplan,$zeiten,$i1,$i2))
        
$maxvalue=mehrbelegung_prozeitraum($stundenplan,$zeiten,$i1,$i2);
    }
      
$mehrbelegung[$i2]=$maxvalue;
    }
  return 
$mehrbelegung;
}

// bekommt eine Zeitspanne, die in eine Liste einsortiert wird, falls sie dort nicht schon enthalten ist
function add_times($zeiten,$von,$bis)
{
  
// Eintrag schon vorhanden?
  
if (uniq_times($zeiten,$von,$bis)!=-1) return $zeiten;
  else
    {
      
// Eintrag hinten anfuegen
      
$pos=count($zeiten);
      
$zeiten[$pos]['von']=$von;
      
$zeiten[$pos]['bis']=$bis;

      
// Nach vorne sortieren
      
for ($pos=(count($zeiten)-1); $pos>0$pos--)
    {
      if ((
$zeiten[$pos-1]['von']>$zeiten[$pos]['von']) || (($zeiten[$pos-1]['von']==$zeiten[$pos]['von']) && ($zeiten[$pos-1]['bis']>$zeiten[$pos]['bis'])))
        {
          
$tmp=$zeiten[$pos-1];
          
$zeiten[$pos-1]=$zeiten[$pos];
          
$zeiten[$pos]=$tmp;
        }
    }
      return 
$zeiten;
    }
}

// Sorgt dafuer dass alle Zeitspannen so zerteilt werden dass sie sich nicht mehr ueberschneiden
function update_times($zeiten,$von,$bis)
{
  
$bonusfeld=false// muss ein zusaetzliches Feld erzeugt werden?
  
$modified=false;  // mussten Zeiten veraendert werden?
  
  // Neue Zeite mit allen anderen vergleichen und testen ob es irgendwo schneidet
  // Falls es schneidet Felder aufsplitten
  
for ($i1=0$i1<count($zeiten); $i1++)
    {

      
// Faengt davor an ...
      
if ($von<$zeiten[$i1]['von'])
    {
      
// ... und endet leider nicht auch davor sondern ...
      
if ($bis>$zeiten[$i1]['von'])
        {
          
// ... mittendrin, 3 Mengen bauen
          
if ($bis<$zeiten[$i1]['bis'])
        {
          
$bonus_von=$bis$bonus_bis=$zeiten[$i1]['bis'];
          
$zeiten[$i1]['bis']=$bis;
          
$bis=$zeiten[$i1]['von'];
          
$bonusfeld=true;
          
$modified=true;
        }
          
// ... gleichzeitig, kleine Menge davor
          
else if ($bis==$zeiten[$i1]['bis'])
        {
          
$bis=$zeiten[$i1]['von'];
        }
          
// ... endet hintendran, vorher und nacher neue Mengen
          
else if ($bis>$zeiten[$i1]['bis'])
        {
          
$bonus_von=$zeiten[$i1]['bis']; $bonus_bis=$bis;
          
$bis=$zeiten[$i1]['von'];
          
$bonusfeld=true;
          
$modified=true;
        }
        }
    }

      
// Faengt gleichzeitig an ...
      
else if ($von==$zeiten[$i1]['von'])
    {
      
// ... beide sind nicht leer ...
      
if (($von!=$bis) && ($zeiten[$i1]['von']!=$zeiten[$i1]['bis']))
        {
          
// ... und endet mittendrin, Menge halbieren
          
if ($bis<$zeiten[$i1]['bis'])
        {
          
$zeiten[$i1]['von']=$bis;
          
$modified=true;
        }
          
// ... und endet hintendran, hinten Menge anhaengen
          
else if ($bis>$zeiten[$i1]['bis'])
        {
          
$von=$zeiten[$i1]['bis'];
          
$modified=true;
        }
        }
    }

      
// Faengt dahinter an ...
      
else if ($von>$zeiten[$i1]['von'])
    {
      
// ... und endet mittendrin, andere Zeit halbieren und davor und danach plazieren
      
if ($bis<$zeiten[$i1]['bis'])
        {
          
$bonus_von=$bis$bonus_bis=$zeiten[$i1]['bis'];
          
$zeiten[$i1]['bis']=$von;
          
$bonusfeld=true;
          
$modified=true;
        }
      
// Hoeren gleichzeitig auf, Menge halbieren
      
else if ($bis==$zeiten[$i1]['bis'])
        {
          
$zeiten[$i1]['bis']=$von;
          
$modified=true;
        }
      
// ... und endet hintendran, 3 kleine Mengen
      
else if (($bis>$zeiten[$i1]['bis']) && ($von<$zeiten[$i1]['bis']))
        {
          
$bonus_von=$zeiten[$i1]['bis']; $bonus_bis=$bis;
          
$bis=$zeiten[$i1]['bis'];
          
$zeiten[$i1]['bis']=$von;
          
$bonusfeld=true;
          
$modified=true;
        }
    }
    }

  if (
$modified)
    
// die Zeitspanne wurde veraendert, lieber nochmal durchschicken ob sie jetzt OK ist
    
{
      
$zeiten=update_times($zeiten,$von,$bis);
      if (
$bonusfeld$zeiten=update_times($zeiten,$bonus_von,$bonus_bis);
    }
  else
    
// die Zeitpanne sind OK, abspeichern
    
{
      
$zeiten=add_times($zeiten,$von,$bis);
      if (
$bonusfeld$zeiten=add_times($zeiten,$bonus_von,$bonus_bis);
    }
  return 
$zeiten;
}

// Gibt Eintrag aus
function printentry($stundenplan,$nr)
{
  
$tmp_txt="";
  
$tmp_txt.='   ';
  if (
$stundenplan[$nr]['Link']!="")
    
$tmp_txt.='<a href="'.$stundenplan[$nr]['Link'].'">'.$stundenplan[$nr]['Fach'].'</a>';
  else 
$tmp_txt.=$stundenplan[$nr]['Fach'];
  
$tmp_txt.="<br />\n";
  
$tmp_txt.=$stundenplan[$nr]['Raum']."<br />\n";
  
$tmp_txt.=$stundenplan[$nr]['Betreuer']."<br />\n";
  if (
$stundenplan[$nr]['doppelt']>1)
    
$tmp_txt.='('.$stundenplan[$nr]['ID'].': 1/'.$stundenplan[$nr]['doppelt'].')'."<br />\n";
  return 
$tmp_txt;
}

// Erzeugt neuen Eintrag
function newentry($fach,$von,$bis,$raum,$link,$wochentag,$betreuer)
{
  global 
$stundenplan;
  global 
$zeiten;

  
$neuepos=count($stundenplan);
  
$stundenplan[$neuepos]['Fach']=$fach;
  if (
$bis<$von$bis=$von;
  
$stundenplan[$neuepos]['Von']=$von;
  
$stundenplan[$neuepos]['Bis']=$bis;
  
$stundenplan[$neuepos]['Raum']=$raum;
  
$stundenplan[$neuepos]['Link']=$link;
  if ((
$wochentag<1) || ($wochentag>6)) $wochentag=7;
  
$stundenplan[$neuepos]['Wochentag']=$wochentag;
  
$stundenplan[$neuepos]['Betreuer']=$betreuer;
  
$zeiten=update_times($zeiten,$stundenplan[$neuepos]['Von'],$stundenplan[$neuepos]['Bis']);
}


?>