2012-06-06 6 views
3

여러 장소 그룹에 예약 가용성 시스템을 사용하고 있으며 주어진 달에 일 단위 시간 블록을 생성하는 데 어려움을 겪고 있습니다. . 이것은 PHP에서 서버 측에서 발생하지만 개념 자체는 언어에 구애받지 않습니다. JS 나 다른 어떤 것으로 이것을 할 수 있습니다. venue_id 년, 월, 일 (2,012분의 6 예를 들어)을 감안할 때 한 달에 매일 열려있는 연속 된 시간 블록 찾기

, 나는 유닉스 startend 타임 스탬프로 표현하는 장소에서 그 범위에서 발생하는 모든 이벤트의 목록을 가지고있다. 이 데이터는 데이터베이스에서 가져옵니다. 매일 최소 길이 (장소마다 다름)의 연속 블록이 존재하는지 확인해야합니다.

예를 들어, 6/1에는 오후 2시에서 7시 사이에 이벤트가 있습니다. 최소 시간은 5 시간이므로 오전 9 시부 터 오후 2 시까 지, 오후 7 시부 터 12시 사이에 블록이 열립니다. 이것은 6 월의 2 일, 3 일 등 ... 매일 계속 될 것입니다. 일부 (대부분)에는 아무 일도 일어나지 않으며, 일부는 1-3 이벤트가 있습니다.

해결책을 찾았지만 데이터를 생성하는 데 너무 오래 걸립니다. 기본적으로 나는 매월 매일 루프를 만들고 그 날 15 분마다 타임 스탬프 배열을 만듭니다. 그런 다음 해당 날짜의 이벤트 시간을 15 분 동안 반복하여 "촬영 된"타임 슬롯을 false로 표시합니다. 남은, 내가 걸리는 시간 대 자유 시간의 타임 스탬프를 포함하는 배열이 있습니다

//one day's array after processing through loops (not real timestamps) 
array(
    12345678=>12345678, // <--- avail 
    12345878=>12345878, 
    12346078=>12346078, 
    12346278=>false,  // <--- not avail 
    12346478=>false, 
    12346678=>false, 
    12346878=>false, 
    12347078=>12347078, // <--- avail 
    12347278=>12347278 
) 

가 지금은 연속 시간 블록을 찾기 위해 루프이 배열을 필요를, 다음 (그들은 충분히 긴 있는지 확인하기 위해 각 장소를 확인 최소값), 그렇다면 시작과 끝 (즉, 오전 9시 - 오후 2시)에 대한 설명 텍스트를 작성하십시오. 아휴! 이 모든 루핑이 완료 될 때까지 사용자는 지루해졌고 강아지의 비디오를보기 위해 Youtube로 돌아 왔습니다. 30 일 정도면 검사하는 데 시간이 걸립니다.

이 문제를 해결하는 더 빠른 방법이 있습니까? 문제를 요약하면, 주어진 시간 I는 최소 시간 블록 m보다 긴 D에 남은 시간을 결정할 수있는 방법, T1 날T2D 범위.

이 데이터는 사용자가 달력 달 사이를 이동할 때 AJAX를 통해 필요에 따라 조합됩니다. 결과는 페이지로드 당 캐시되므로 사용자가 7 월에 두 번째로 이동하면 처음 생성 된 데이터가 다시 사용됩니다.

도움이 될만한 다른 세부 정보를 알려주세요.


편집

의 요청에 따라, 데이터베이스 구조 (또는 여기에 관련된 부분은)

*events* 
id  (bigint) 
title  (varchar) 

*event_times* 
id  (bigint) 
event_id (bigint) 
venue_id (bigint) 
start  (bigint) 
end  (bigint) 

*venues* 
id  (bigint) 
name  (varchar) 
min_block (int) 
min_start (varchar) 
max_start (varchar) 

이벤트는 항상 15에서 시작 - : 00 : 15 : 30, : 45

실제 시간 소인의 일부 데이터 덤프 : http://pastebin.com/k1PRkj44

+0

Hey Chris, 정리해보기 : 예약 시스템 작업 중이라서 모든 예약 정보가 데이터베이스에 저장되었다고 가정합니다. 아니면 한 번 큰 데이터 세트로 한 번 실행하고 일회 기준으로 시간표를 생성해야하는 일입니까? –

+0

모든 데이터가 데이터베이스에서 제공됩니다. venue_id, month, year가 주어지면 해당 데이터를 먼저 쿼리합니다. 그것을 명확히하기 위해 편집 된 질문. –

+0

좋아요, 데이터베이스를 제어 할 수 있습니까? 어떤 필드를 사용할 수 없으면 가장 중요한 것은 현재 예약이 어떻게 저장되어 있습니까? –

답변

1

올바른 방향으로 가야합니다 (희망 사항). 이 데이터베이스 레코드는 일정 기간 (예 : 1 개월) 내에있는 데이터베이스 레코드를 반복합니다.

그 세트에서 예약 사이에 "간격"을 찾아 배열을 채 웁니다 (날짜는 키). 끝에

$days = array(); 

$stmt = $db->prepare('SELECT 
    DATE(FROM_UNIXTIME(start)) AS sdate, 
    GROUP_CONCAT(HOUR(FROM_UNIXTIME(start)),",", MINUTE(FROM_UNIXTIME(start)) ORDER BY start ASC SEPARATOR ",") AS from_hours, 
    GROUP_CONCAT(HOUR(FROM_UNIXTIME(end)), ",", MINUTE(FROM_UNIXTIME(end)) ORDER BY start ASC SEPARATOR ",") AS to_hours 
    FROM event_time 
    WHERE start >= ? AND end < ? AND start < end 
    GROUP BY sdate 
    ORDER BY sdate'); 

$stmt->execute(array($from, $to)); 
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { 
    // from and to are formatted as: [hh,mm,hh,mm,hh,mm,...] 
    $from = explode(',', $row['from_hours']); 
    $to = explode(',', $row['to_hours']); 

    // skew the two arrays: 
    // - add 00:00 in the front of $to 
    // - add 23:59 at the back of $from 
    array_unshift($to, 0, 0); 
    array_push($from, 23, 59); 

    for ($i = 0, $n = count($from); $i != $n; $i += 2) { 
     // create time values 
     $start = new DateTime("{$to[$i]}:{$to[$i+1]}"); 
     $end = new DateTime("{$from[$i]}:{$from[$i+1]}"); 

     // calculate difference 
     $diff = $start->diff($end); 
     // difference must be positive and at least 5 hours apart (depending on venue) 
     if (!$diff->invert && $diff->h >= 5) { 
      $days[$row['sdate']][] = array($start->format('H:i'), $end->format('H:i')); 
     } 
    } 
} 

은 $ 일이 포함됩니다

[2012-06-30] => Array 
    (
     [0] => Array 
      (
       [0] => 00:00 
       [1] => 05:30 
      ) 

     [1] => Array 
      (
       [0] => 11:30 
       [1] => 23:59 
      ) 

    ) 

당신이 당신의 계산하게 변경해야 할 몇 가지 변수가있다 : 예를 들어

  1. 최소 시간 (얼마나 일찍부터 아침에)
  2. 최대 시간 (예 : 밤 늦게까지)
  3. 최소 booki 당신이 프라임 $days 배열이 기간 내의 모든 일에 루프를 시작해야하기 전에, 그래서 NG 시간 (장소에 따라) 또한

는 결과 배열에 누락 된 키는, 하루 종일 사용할 수 있습니다 당신 다시 묻습니다.

내가 도움이되었는지 알려주세요. :)

+0

약간의 수정을 가하면 작동하고있다. 그러나 다음날 끝나는 이벤트 시간은 잘 처리되지 않습니다 (이벤트는 오전 1시에 끝납니다). 나는이 코드를 극복 할 수 있는지 확인하기 위해 노력하고 있습니다. 감사합니다! –

+0

이것은 함께 나오고 있습니다, 나는 당신의 코드와 비슷한 것을 최종 해결책으로 사용할 것입니다. 아이디어를 가져 주셔서 감사합니다! –

0

사용 가능한 시간 목록을 만드십시오. 각 항목에는 시작 시간과 종료 시간이 있습니다. 처음부터 끝까지 한 항목으로 시작하십시오. 데이터베이스에서 사용 된 시간을 읽습니다. 기존 항목의 시작 또는 끝 부분에있는 경우 적절히 줄이십시오. 중간에 떨어지는 경우, 하나를 줄이고 새 것을 추가해야합니다 (같은 시간을 처리하기 위해 중간에 간격이 있음). 이것은 당신을 몇 시간의 긴 이벤트에서 15 분 슬롯을 보지 않아도되게합니다. 슬롯이 15 대신 5 분이되면 여전히 작동합니다.

DB를 읽으면 모든 무료 기간이 하나의 시간순으로 나열됩니다. 크기별로 정렬 된 별도의 목록에 넣을 수도 있습니다.

링크 된 목록은 대부분 순차적으로 액세스하므로 가장 논리적 인 선택 일 수 있습니다. 신속하게 추가하고 제거 할 수 있습니다. 일종의 배열은 느려야하지만 요즘에는 배열이 매우 빠르며 바이너리 검색도 가능합니다. 정말 사용량이 많은 경우, 일종의 트리 기반 (정렬 된 순차 액세스 용) 사전이나 맵을 사용하면 두 가지 영역 모두에서 최상의 결과를 얻을 수 있습니다 (빠른 추가 및 제거 임의 액세스). 이 경우 일종의 배열로 생각합니다.

이것은 약간의 작업이지만 약간의 속도를 줄 수 있습니다.