سؤال

أحاول كتابة تقويم في PHP. في عرض الأسبوع، أريد أن يتم إدراج أحداثي مثل iCal، حيث تقلل الأحداث المتزامنة عرضها إلى نصف الحجم.

لدي وقت صعب للغاية في معرفة ذلك، لذلك آمل أن تتمكن من مساعدتي. ما أريده هو أنه إذا تداخل حدث واحد آخر، فيجب تعيين [split] => true في كل من صفيف الأحداث - أو شيء ما في هذا الاتجاه (اقرأ: أنا غير متأكد مما إذا كان هذا هو الحل الأكثر كفاءة). ثم يمكنني التحقق من split == true في حلقة foreach التي تطبع الأحداث.

هنا هو مجموعة مثال تحتوي على اثنين من الأحداث المتزامنة:

$events = array(
  array(
    "id" => 21,
    "start" => 1242219600,
    "end" => 1242237600,
    "title" => "foo",
    "split" => false
  ),
  array(
    "id" => 22,
    "start" => 1242223200,
    "end" => 1242234000,
    "title" => "foo",
    "split" => false
  )
);

$events = someFunctionToOffsetEvents($events);

كيف تحل هذا واحد؟

هل كانت مفيدة؟

المحلول

اضطررت إلى التعامل مع قضايا تصادم التاريخ كثيرا في الآونة الأخيرة، وأفضل ما تمكنت من التوصل إليه هو:

date1.start <date2.end و date1.end> date2.start = تصادم

ستحطط هذه الصيغة البسيطة لجميع المواقف التالية:

- اسمح لجميع المواقف: Date1.Start = 1/1/2009 Date1.end = 1/10/2009 - Nstart تاريخ في أول تواريخ المدى: Date2.Start = 1/9/2009 Date2.end = 2 / 10/2009 - تاريخ التنفيذ الأول قيد التنفيذ الأول: Date2.Start = 12/10/2008 Date2.end = 1/3/2009 - تاريخ الانتهاء من النطاق الأول للمجموعات الأولى: Date2.start = 1/2 / 2009 Date2.end = 1/3/2009 - تاريخ التوجيه في الداخل المدى: Date2.Start = 12/1/2008 Date2.end = 2/1/2009
$date1 = array('start' => '2009-01-05', 'end' => '2009-01-10');
$date2 = array('start' => '2009-01-01', 'end' => '2009-01-04'); // end inside one
$date3 = array('start' => '2009-01-04', 'end' => '2009-01-15'); // start inside one
$date4 = array('start' => '2009-01-01', 'end' => '2009-01-15'); // one inside me
$date5 = array('start' => '2009-01-04', 'end' => '2009-01-05'); // inside one

function datesCollide($date1, $date2)
{
    $start1TS = strtotime($date1['start']);
    $end1TS = strtotime($date1['end']);
    $start2TS = strtotime($date2['start']);
    $end2TS = strtotime($date2['end']);

    if ($start1TS <= $end2TS && $end1TS >= $start2)
    {
        return true;
    }

    return false;
}

بناء على تعليقك، ربما يكون هذا هو الحل الذي تبحث عنه: لاحظ أن هذا الحل غير محسن للغاية، ويجب استخدامه فقط للحصول على حل أفضل. لا تثق في رمز من الويب.

$events = array(
  array(
        "id" => 21,
        "start" => 1242219600,
        "end" => 1242237600,
        "title" => "foo",
        "split" => false
  ),
  array(
        "id" => 22,
        "start" => 1242223200,
        "end" => 1242234000,
        "title" => "foo",
        "split" => false
  )
);

foreach ($events as $key => $event)
{
    $events[$key]->split = dateCollisionCheck($event, $events);
}

function dateCollisionCheck(&$event, &$eventList)
{
    foreach ($eventList as $checkEvent)
    {
        if ($event->id != $checkEvent->id)
        {
            if ($event->start <= $checkEvent->end && $event->end >= $checkEvent->start)
            {
                return true; // return as soon as we know there is a collision
            }
        }
    }

    return false;
}

* لم يتم اختبار التعليمات البرمجية

نصائح أخرى

لقد قمت بنشرت سؤال حول ما إذا كانت ثلاث أحداث تتداخل، مما يؤدي إلى حل أفضل. لا تضع واجهة المستخدم الرسومية وبياناتك في نفس الهيكل. احفظ بياناتك، ثم اكتشف كيفية عرضه.

سأعود مشكلتك. قم بتعيين الأحداث على صفيف يمثل الأسبوع الذي تريد عرضه:

$weekdayEvents=array();
foreach ($events as $event) {
   $day=toThisWeek($event['start'], $firstweekday),
   $lastDay=toThisWeek($event['end'], $firstweekday); 
   while ($day<=$lastDay) {
     $weekdayEvents[$day++][]=$event['id'];
   }
}
// now you have an array of array filled with ids
$eventCollisions=array();
foreach($weekdaysEvents as $activeDay) {
  $eventsOnDay = count($activeDay);
  foreach($activeDay as $eventID) {
    if ($eventCollisions[$eventID]<$eventsOnDay) {
      $eventCollisions[$eventID]=$eventsOnDay;
    }
  }
}

}

حيث tothisweek () هي وظيفة مثل

function toThisWeek($dayTimestamp, $firstDayOfWeekTimestamp) {
  $dayOfWeek = unixtojd($firsDayOfWeekTimestamp) - unixtojd($dayTimestamp);
  if($dayOfWeek<0) return 0;
  if($dayOfWeek>6) return 6; 
  return $dayOfWeek;      
}

في هذه اللحظة appercolliss. لديك الحد الأقصى لعدد الاصطدام يحدث في حدث لكل أحداث تحدث خلال الأسبوع، عليك عرضها. الآن يمكنك استخدام القيم في هذه الصفيف لملء الانقسام في الحقل في Subarray $ Actions:

foreach ($events as $event) {
  $event['split']=$eventCollisions[$event['id']]-1;
}

أو مجرد استخدام القيم في EventCollisيات "على الطلب"

فيما يلي التعليمات البرمجية المعدلة بناء على إجابة ROB:

// this is in my getEvents function
if(is_array($events)) {
  foreach ($events as $key => $event) {
    $events[$key]['collides'] = $this->dateCollisionCheck($event, $events);
  }
}

//this is another function added to calendar.class.php
function dateCollisionCheck(&$event, &$eventList) {
  foreach ($eventList as $checkEvent) {
    if ($event['id'] != $checkEvent['id']) {
      if ($event['start'] <= $checkEvent['end'] && $event['end'] >= $checkEvent['start']) {
        return true;
      }
    }
  }

  return false;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top