Source Code

;; time-utils-health - Clarity 4
;; Time and scheduling utility functions for healthcare operations

(define-constant ERR-INVALID-TIME (err u100))
(define-constant ERR-PAST-TIME (err u101))

(define-constant SECONDS-PER-DAY u86400)
(define-constant SECONDS-PER-HOUR u3600)
(define-constant SECONDS-PER-MINUTE u60)

(define-map scheduled-events uint
  {
    event-name: (string-utf8 100),
    event-type: (string-ascii 50),
    scheduled-time: uint,
    duration: uint,
    organizer: principal,
    is-recurring: bool,
    recurrence-interval: uint
  }
)

(define-map time-windows uint
  {
    window-name: (string-utf8 100),
    start-time: uint,
    end-time: uint,
    time-zone: (string-ascii 50),
    is-active: bool
  }
)

(define-map appointment-slots { date: uint, slot-id: uint }
  {
    start-time: uint,
    end-time: uint,
    is-available: bool,
    booked-by: (optional principal)
  }
)

(define-map recurring-schedules uint
  {
    schedule-name: (string-utf8 100),
    base-time: uint,
    interval-type: (string-ascii 20),
    interval-value: uint,
    end-date: (optional uint)
  }
)

(define-data-var event-counter uint u0)
(define-data-var window-counter uint u0)
(define-data-var schedule-counter uint u0)

(define-public (schedule-event
    (event-name (string-utf8 100))
    (event-type (string-ascii 50))
    (scheduled-time uint)
    (duration uint)
    (is-recurring bool)
    (recurrence-interval uint))
  (let ((event-id (+ (var-get event-counter) u1)))
    (asserts! (> scheduled-time stacks-block-time) ERR-PAST-TIME)
    (map-set scheduled-events event-id
      {
        event-name: event-name,
        event-type: event-type,
        scheduled-time: scheduled-time,
        duration: duration,
        organizer: tx-sender,
        is-recurring: is-recurring,
        recurrence-interval: recurrence-interval
      })
    (var-set event-counter event-id)
    (ok event-id)))

(define-public (create-time-window
    (window-name (string-utf8 100))
    (start-time uint)
    (end-time uint)
    (time-zone (string-ascii 50)))
  (let ((window-id (+ (var-get window-counter) u1)))
    (asserts! (< start-time end-time) ERR-INVALID-TIME)
    (map-set time-windows window-id
      {
        window-name: window-name,
        start-time: start-time,
        end-time: end-time,
        time-zone: time-zone,
        is-active: true
      })
    (var-set window-counter window-id)
    (ok window-id)))

(define-public (book-appointment-slot
    (date uint)
    (slot-id uint))
  (let ((slot (unwrap! (map-get? appointment-slots { date: date, slot-id: slot-id }) ERR-INVALID-TIME)))
    (asserts! (get is-available slot) ERR-INVALID-TIME)
    (ok (map-set appointment-slots { date: date, slot-id: slot-id }
      (merge slot {
        is-available: false,
        booked-by: (some tx-sender)
      })))))

(define-public (create-recurring-schedule
    (schedule-name (string-utf8 100))
    (base-time uint)
    (interval-type (string-ascii 20))
    (interval-value uint)
    (end-date (optional uint)))
  (let ((schedule-id (+ (var-get schedule-counter) u1)))
    (map-set recurring-schedules schedule-id
      {
        schedule-name: schedule-name,
        base-time: base-time,
        interval-type: interval-type,
        interval-value: interval-value,
        end-date: end-date
      })
    (var-set schedule-counter schedule-id)
    (ok schedule-id)))

(define-read-only (get-scheduled-event (event-id uint))
  (ok (map-get? scheduled-events event-id)))

(define-read-only (get-time-window (window-id uint))
  (ok (map-get? time-windows window-id)))

(define-read-only (get-appointment-slot (date uint) (slot-id uint))
  (ok (map-get? appointment-slots { date: date, slot-id: slot-id })))

(define-read-only (get-recurring-schedule (schedule-id uint))
  (ok (map-get? recurring-schedules schedule-id)))

(define-read-only (calculate-time-difference (start-time uint) (end-time uint))
  (ok (if (> end-time start-time)
      (- end-time start-time)
      u0)))

(define-read-only (add-days (base-time uint) (days uint))
  (ok (+ base-time (* days SECONDS-PER-DAY))))

(define-read-only (is-time-in-window (check-time uint) (window-start uint) (window-end uint))
  (ok (and (>= check-time window-start) (<= check-time window-end))))

(define-read-only (validate-principal (p principal))
  (principal-destruct? p))

(define-read-only (format-event-id (event-id uint))
  (ok (int-to-ascii event-id)))

(define-read-only (parse-event-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (15)

FunctionAccessArgs
schedule-eventpublicevent-name: (string-utf8 100
create-time-windowpublicwindow-name: (string-utf8 100
book-appointment-slotpublicdate: uint, slot-id: uint
create-recurring-schedulepublicschedule-name: (string-utf8 100
get-scheduled-eventread-onlyevent-id: uint
get-time-windowread-onlywindow-id: uint
get-appointment-slotread-onlydate: uint, slot-id: uint
get-recurring-scheduleread-onlyschedule-id: uint
calculate-time-differenceread-onlystart-time: uint, end-time: uint
add-daysread-onlybase-time: uint, days: uint
is-time-in-windowread-onlycheck-time: uint, window-start: uint, window-end: uint
validate-principalread-onlyp: principal
format-event-idread-onlyevent-id: uint
parse-event-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only