Ergebnis 1 bis 13 von 13

Thema: PHP Daten in einem Tag auf Überschneidung prüfien und dementsprechend anzeigen

  1. #1

    PHP Daten in einem Tag auf Überschneidung prüfien und dementsprechend anzeigen

    Hi Leute.
    Ich bin gerade dabei, einen Planer zu erstellen.
    Er sieht im Moment so aus:

    Man kann Aufträge anlegen und sie werden ihrer Länge entsprechend angezeigt.
    Ich möchte es jetzt allerdings so machen, dass man auch Aufträge anlegen kann, die sich überschneiden. Also bspw. Montag 2 um 8 Uhr gleichzeitig starten und somit nebeneinander angezeigt werden.

    Kann man eine Tabellenzelle noch weiter unterteilen, ohne eine weitere Tabelle einzufügen?

    Geändert von Raildex (21.06.2014 um 13:08 Uhr)

  2. #2
    Nimm Divisions (<div>...</div>), die du per CSS float:left nebeneinanderreihst.

  3. #3
    Ich nehm aber schon Tabellenzellen zum Anzeigen...
    mithilfe von Row-Span werden sie entsprechend lang angezeigt.

  4. #4
    Du sollst ja auch in den Zellen die Divisions verwenden.
    (Allerdings weiß ich gar nicht, ob das überhaupt in Tabellen funktioniert)

  5. #5
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Du sollst ja auch in den Zellen die Divisions verwenden.
    (Allerdings weiß ich gar nicht, ob das überhaupt in Tabellen funktioniert)
    Aber was ist, wenn 2 Aufträge gleichzeitig starten, aber unterschiedlich lang sind? Dann würde diese Methode ja nicht funktionieren :/
    Ich hab hier mal mein PHP Ding.
    Code:
    <table style="border-collapse: collapse;width: 100%;border-width:1px ;table-layout:fixed;">
        <thead>
            <tr>
                <td>
                    Uhrzeit <?php ?>
                </td>
                <?php foreach ($weekPeriod as $date): ?>
                    <td>
                        <b><?php echo $weekNames[$date->format('w')];?></b><br/>
                        <?php echo $date->format('d.m.Y'); ?>
                    </td>
                <?php endforeach; ?>
            </tr>
        </thead>
        <tbody>
            <?php foreach ($hoursPeriod as $time): ?>
                <tr >
                    <td><?php echo $time->format($dayformat); ?></td>
                    <?php
                    foreach ($weekPeriod as $date):
                        $hours = $time->format('H');
                        $minutes = $time->format('i');
                        $date->setTime($hours, $minutes);
                        $task = getTask($date, $tasks);
                        ?>
                        <?php
                        if ($task):
                            if (!isset($displayedInvervals[$task->id])):
                                $displayedInvervals[$task->id] = true;
                                ?>
                                <td class="task" rowspan="<?= $task->intervals ?>">
                                <div class="task<?php if($task->deleted ==1)echo 'deleted';?>"
                                    <b><u> <?php echo $task->id . ':' . $task->name; ?></u></b> 
                                    <br><b><?php echo $task->billnumb; ?></b>
                                    <br><?php echo $task->customnumb;echo ': '; echo $task->customname; ?>
                                    <br><?php echo $task->description; ?>
                                    <br><?php echo $task->workernumb;echo ': '; echo $task->workername; ?>
                                    <br><?php echo $task->comment; ?><br>
                                    <?php if($task->deleted == 0): ?>
                                    <a href="Planung/auftragbearbeit.php?action=edit&id=<?php echo $task->id; ?>"target="_blank">Bearbeiten</a>
                                    <a href="Planung/auftragloeschen.php?id=<?php echo $task->id; ?>"target="_blank">L��en</a>
                                    <?php else:?>
                                    <a href="Planung/auftragloeschen.php?id=<?php echo $task->id; ?>"target="_blank">Freigeben</a>
                                    <?php endif;?>
                                    </div>
                                </td>
                            <?php endif; ?>
                        <?php else: ?>
                            <td class="empty"><a target="_blank" href="Planung/auftragbearbeit.php?action=new&time=<?php echo $date->getTimestamp(); ?>" style="display:block;width:100%;height:100%;"></a></td>
                        <?php endif; ?>
    
    
                    <?php endforeach; ?>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>

  6. #6
    Ohne den Code anzuschauen, fallen mir hier schon einige Probleme auf:
    • Ich würde dir vorschlagen, erst mal einen Prototypen mittels statischem HTML zu entwickeln, um zu schauen, wie man so etwas darstellen kann. Gleich mit php anzufangen, obwohl man gar nicht weißt, wie was auszusehen hat, ist schon mal der falsche Schritt.
    • Mache dich mit MVC vertraut, und wie man so was kapseln kann. Kein Mensch tut sich so ein Code freiwillig an.
    • Du unterschätzt diese Problemstellung gewaltig. Nur mit Tabellen kommt du hier nicht weit. Was ist, wenn du ein Termin um 08:05 Uhr hast? Dies würde sich mit deiner Tabelle nicht darstellbar sein. Du brauchst also etwas, womit du die Termine beliebig verschieben kannst.


    Um vielleicht mal ein Denkanstoß zu geben, wie so was aussehen könnte:
    Code:
    <table style="width:600px;" border = "1" frame="void" rules="rows">
    	<tr>
    		<td style="width:300px;height:50px;">08:00</td>
    		<td style="width:300px;;min-width:300px;vertical-align:top;">
    			<div style="position:relative;">
    				<div style="position:absolute;width:150px;height:100px;border:1px solid blue;top:0px;left:0px;">Termin1</div>
    				<div style="position:absolute;width:150px;height:150px;border:1px solid blue;top:0px;left:150px;">Termin2</div>
    				<div style="position:absolute;width:150px;height:100px;border:1px solid blue;top:125px;left:0px;">Termin3</div>
    				<div style="position:absolute;width:150px;height:75px;border:1px solid blue;top:175px;left:150px;">Termin4</div>
    				<div style="position:absolute;width:100px;height:100px;border:1px solid blue;top:275px;left:0px;">Termin5</div>
    				<div style="position:absolute;width:100px;height:150px;border:1px solid blue;top:300px;left:100px;">Termin6</div>
    				<div style="position:absolute;width:100px;height:50px;border:1px solid blue;top:325px;left:200px;">Termin7</div>
    			</div>
    		</td>
    	</tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">08:30</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">09:00</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">09:30</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">10:00</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">10:30</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">11:00</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">11:30</td><td></td></tr>
    	<tr><td style="width:300px;height:50px;1px solid black;">12:00</td><td></td></tr>
    </table>
    (Der Code ist nicht optimal!)

    Um die Breite und Position jeder Division herauszufinden, würde ich vielleicht so vorgehen (ausgehend von meinem Beispiel):
    1. Alle Termine aufsteigend sortieren.
    2. Alle Termine, die sich nicht überschneiden in ein neues Array speichern, und sie aus dem Haupt-Array löschen.
    3. Schritt 2 so lange wiederholen, bis das Haupt-Array leer ist. Dann hätten wir folgende Arrays:
    Array[0] = Termin1, Termin3, Termin5
    Array[1] = Termin2, Termin4, Termin6
    Array[2] = Termin7

    4. Die Positionen für Termin1, Termin3 und Termin5 wissen wir dann schon mal. Nur die Breite wissen wir noch nicht, weil wir nicht wissen, wie viele Überschneidungen diese Termine haben. Wir wissen nur, dass es maximal 2 Überschneidungen geben kann. Also nehmen wir uns nun Termin1 und überprüfen nun diesen Termin mit allen anderen Termin aus Array[1] und Array[2] nach Überschneidungen.
    Es gibt eine Überschneidung: Termin2 überschneidet sich mit Termin1. Also hat Termin1 die Breite von Gesamtbreite / (Anzahl Überschneidungen + 1). Also können wir nun Termin1 in die Tabelle zeichnen.
    5. Dasselbe machen wir mit Termin3 und Termin5.
    6. Nun wird es etwas Tricky. Jetzt schauen wir uns Array[1] an. Wir wissen weder den linken Versatz, noch die Breite.
    Um den linken Versatz zu ermitteln, müssen wir wissen, wieviele Überschneidungen es vorher gab. Also nehmen wir uns Termin2 und überprüfen es mit allen Terminen aus Array[0].
    Zusätzlich schauen wir uns die Breite an. Also überprüfen wir Termin2 mit allen Terminen aus Array[2]. Wir wissen also, dass es ein Termin gibt, welches schon vorher eingetragen wurde, und ob welche noch eingetragen werden müssen. Also ist die Breite Gesamtbreite / (Anzahl Überschneidungen + 1)) und der linke Versatz Anzahl vorherige Termine * Breite.
    7. Dasselbe machen wir mit Termin4 und Termin6.
    8. Schritt 6 mit Array[2] wiederholen.

    Schritt 4 ließe sich auch mit Schritt 5 verallgemeinern.
    Ob jetzt mein Ansatz richtig ist, oder ob es einfachere Wege gibt, weiß ich jetzt auch nicht. Das habe ich mir von ein paar Minuten zusammengesponnen ^^

    Geändert von Whiz-zarD (16.06.2014 um 14:10 Uhr)

  7. #7
    Vielen Danke schonmal.
    Ich habe mir überlegt, dass ich die Spalte für den Tag je nach Anzahl der Überschneidungen einfach breiter mache.
    Also zuerst überprüfe, wieviele maximale Überschneidungen es an diesem Tag gibt dann einfach mehr <td> anzeige.
    Wenn bei einem anderen Termin keine Überschneidungen sind, mach ich einfach eine Colspan mit der Anzahl der Überschneidungen.
    Das sollte meinen Aufbau nicht ganz so sehr über den Haufen werfen.
    Zitat Zitat
    • Du unterschätzt diese Problemstellung gewaltig. Nur mit Tabellen kommt du hier nicht weit. Was ist, wenn du ein Termin um 08:05 Uhr hast? Dies würde sich mit deiner Tabelle nicht darstellbar sein. Du brauchst also etwas, womit du die Termine beliebig verschieben kannst.
    Man kann den "Zoom"-Faktor einstellen. Möchte man einen Auftrag anlegen, Wir die Zeit aus der Tabelle übernommen und man gibt einen Zeitraum in 10-Minuten Intervallen an.

    Geändert von Raildex (17.06.2014 um 10:22 Uhr)

  8. #8
    Zitat Zitat von Raildex Beitrag anzeigen
    Vielen Danke schonmal.
    Ich habe mir überlegt, dass ich die Spalte für den Tag je nach Anzahl der Überschneidungen einfach breiter mache.
    Also zuerst überprüfe, wieviele maximale Überschneidungen es an diesem Tag gibt dann einfach mehr <td> anzeige.
    Wenn bei einem anderen Termin keine Überschneidungen sind, mach ich einfach eine Colspan mit der Anzahl der Überschneidungen.
    Das sollte meinen Aufbau nicht ganz so sehr über den Haufen werfen.
    Musst du wissen. Finde ich aber sehr suboptimal.
    Ich finde, das macht das Ganze sehr unübersichtlich, wenn die Tage eine unterschiedliche Breite haben. Man muss also schon genau hinschauen, welcher Termin zu welchem Tag gehört, wenn z.B. der Montag plötzlich die selbe Breite hat, wie der Dienstag und Mittwoch zusammen. Oder wenn ich mir schon einige Terminpläne meiner Arbeitskollegen anschaue, dann gäbe es oft der Fall, dass ein Tag mal den Platz einer gesamten Woche benötigt.


    Zitat Zitat von Raildex Beitrag anzeigen
    Man kann den "Zoom"-Faktor einstellen. Möchte man einen Auftrag anlegen, Wir die Zeit aus der Tabelle übernommen und man gibt einen Zeitraum in 10-Minuten Intervallen an.
    Bringt dir ja trotzdem nichts.
    Wie willst du ein Termin korrekt anzeigen lassen, der z.B. um 08:25 Uhr anfängt?
    Auch wenn man rein- oder rauszoomen kann, muss ja dennoch der Termin korrekt in der Spalte angezeigt werden.
    Es kann ja nicht sein, dass der Termin um 08:00 oder 8:30 Uhr anfängt, wenn die Einteilung halb-stündlich ist, und dann plötzlich um 08:00 oder 09:00 Uhr anfängt, wenn die Einteilung stündlich ist.
    Darum sage ich ja, dass du mit einer festen Einteilung (auch mit Zoom-Funktion ist die Einteilung fest) nicht weit kommen wirst, du musst schon was haben, um die Termine in deiner Zeitleiste variabel verschieben zu können.

  9. #9
    Hey, vielen Dank für die Hilfe!
    Ich hab allerdings Probleme mit der Umsetzung
    Ich hab hier mal meine Funktion:

    Code:
    function getNumberOfMaxOverlaps(DateTime $date,array $tasks){
    	$tasksOfThisDay = array();
    	foreach($tasks as $task)
    	{
    		if($task->start->format('Y-m-d') == $date->format('Y-m-d'))
    		{
    			$tasksOfThisDay[] = $task;
    		}
    	}
    	$overlap = array();
    	foreach ($tasksOfThisDay as $task1) 
    	{
    		foreach ($tasksOfThisDay as $task2) 
    		{
    
    
    			if (strtotime($task1->start->format("Y-m-d HH:ii:ss")) <  strtotime($task2->end->format("Y-m-d HH:ii:ss")) &&
    				strtotime($task1->start->format("Y-m-d HH:ii:ss")) >= strtotime($task2->start))
    			{
    				$array = array($task1->id, $task2->id);
    				sort($array);
    				if (!in_array($array, $overlap)) $overlap[] = $array;
    			}
    		}
    	}
    }
    $overlap zeigt am Ende allerdings immer 0 an. Gearbeitet habe ich mit folgenden Daten

    Code:
    $rows               = array();$class              = new stdClass();
    $class->id          = 1;
    $class->name        = 'Test';
    $class->description = 'Test Description';
    $class->start       = '2014-06-17 06:05:00';
    $class->end         = '2014-06-17 07:00:00';
    $rows[]             = $class;
    $class              = new stdClass();
    $class->id          = 2;
    $class->name        = 'Test 2';
    $class->description = 'Test Description 2';
    $class->start       = '2014-06-17 07:00:00';
    $class->end         = '2014-06-17 07:40:00';
    $rows[]             = $class;
    $class              = new stdClass();
    $class->id          = 3;
    $class->name        = 'Test 2';
    $class->description = 'Test Description 2';
    $class->start       = '2014-06-17 09:00:00';
    $class->end         = '2014-06-17 09:40:00';
    $rows[]             = $class;
    $class              = new stdClass();
    $class->id          = 4;
    $class->name        = 'Test 2';
    $class->description = 'Test Description 2';
    $class->start       = '2014-06-17 10:00:00';
    $class->end         = '2014-06-17 11:40:00';
    $rows[]             = $class;

  10. #10
    Kapsel deinen Code weiter in Funktionen. Hab keine Scheu kleine Funktionen zu schreiben.
    Für start und end kannst auch gleich DateTime Objekte erstellen. Dann sparst du dir das ganze rumkonvertiere.

    Außerdem ist das Ergebnis von 0 doch richtig mit deinen Testdaten und es fehlt ein return in deiner Funktion.

  11. #11
    Wenn ich
    Code:
    count($overlap);
    anwende, zeigt er 0 0 0 0 0 0
    an.
    Die IDs haben aber einen Wert, der nicht 0 ist.
    Zitat Zitat
    Für start und end kannst auch gleich DateTime Objekte erstellen. Dann sparst du dir das ganze rumkonvertiere.
    Alles Klar

    €dit:
    Ok, die ganze Sache mit assoziativen Arrays verwirrt mich.
    Code:
    foreach($overlap as $key => $value)
    			{
    				echo $key;
    				echo $value;
    			}
    gibt aber auch nichts aus...

    Geändert von Raildex (18.06.2014 um 18:07 Uhr)

  12. #12
    Drei Fehler:
    1. Erst mal hast du bei deiner if-Abfrage bei $task2->start vergessen den Formatstring mitzugeben.
    2. Der Formatstring für die Uhrzeit muss H:i:s lauten.

    Korrigierst du diese beiden Fehler, dann wirst du auch ein Ergebnis bekommen, welches aber noch falsch ist, denn:

    3. Du testest die IDs nicht auf Gleichheit. Das sorgt dafür, dass er eine Task mit sich selbst überprüft.

    Edit:
    Ich würde den Code aber auch so in etwas aufteilen:

    Code:
    function getOverlaps(DateTime $date,array $tasks)
    {
    	$result = array();
    	$tasksOfThisDay = getTasksOfDate($date, $tasks);
    	
    	foreach ($tasksOfThisDay as $task1) 
    	{
    		foreach ($tasksOfThisDay as $task2) 
    		{
    			if (isOverlay($task1, $task2)) 
    			{
    				$array = array($task1->id, $task2->id);
    				sort($array);
    				if (!in_array($array, $result)) $result[] = $array;
    			}
    		}
    	}
    	
    	return $result;
    }
    
    function getTasksOfDate(DateTime $date, array $tasks)
    {
    	$result = array();
    	foreach($tasks as $task)
    	{
    		if($task->start->format('Y-m-d') == $date->format('Y-m-d'))
    		{
    			$result[] = $task;
    		}
    	}
    	
    	return $result;
    }
    
    function isOverlay(stdClass $task1, stdClass $task2)
    {
    	return  ($task1->id != $task2->id)
    			&& ($task1->start->format('H:i:s') < $task2->end->format('H:i:s')) 
    			&& ($task1->start->format('H:i:s') >= $task2->start->format('H:i:s'));
    }
    Meine php Kenntnisse sind aber auch sehr eingerostet. Vermutlich geht der Code noch hübscher. Ich hab schon seit etlichen Jahren nichts mit mit php am Hut gehabt.

    Geändert von Whiz-zarD (18.06.2014 um 20:54 Uhr)

  13. #13
    Puh, vielen Dank!

    Ich habe mich im Übrigen für deine Variante entschieden, allein weil es wirklich schöner ist, wenn die Daten genauer angezeigt werden.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •