Files
halloween-test/specs/001-mcdonald-s-it/data-model.md
snowprint 325eeaf063 feat(spec): complete implementation plan for Halloween event page
Created comprehensive planning documentation following Spec-Kit standards:

Phase 0 - Research:
- Analyzed 10 technical decisions (HTML5, ASCII art, countdown, responsive design)
- Resolved edge cases (post-countdown, post-event, JS disabled, small screens)
- Documented rationale and alternatives for each decision

Phase 1 - Design:
- Defined 4 data entities (Event, Countdown, VisualTheme, Content)
- Created JSON schema contract for page content validation
- Mapped 35 functional requirements to implementation approach
- Generated quickstart testing checklist with 10 test categories

Technical decisions:
- Single-file HTML architecture (no external dependencies)
- Pure CSS animations (blinking cursor)
- JavaScript countdown with GMT+8 timezone handling
- Responsive ASCII art (desktop/mobile versions)
- WCAG 2.1 AA compliance (21:1 contrast ratio)

Constitution compliance: PASS
- No violations detected
- Follows user-centric, professional excellence principles
- Minimal technical stack aligns with simplicity requirement

Artifacts created:
- spec.md: 35 functional requirements
- plan.md: Implementation strategy and phases
- research.md: 10 technical research decisions
- data-model.md: 4 entity definitions with validation
- contracts/page-content.schema.json: JSON Schema
- quickstart.md: Comprehensive testing checklist

Ready for: /tasks command to generate tasks.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 19:20:25 +08:00

10 KiB
Raw Blame History

Data Model: McDonald's IT Halloween Event Page

Feature: Halloween event announcement webpage Date: 2025-10-04 Status: Complete

Overview

This document defines the data entities and their relationships for the Halloween event page. While this is a static page with no backend storage, defining the data model helps structure the HTML content and JavaScript logic.

Entities

1. Event

Represents the Halloween event information.

Purpose: Store and display all event details

Fields:

Field Type Required Default Description
title String Yes - Event title: "2025 MITA Halloween"
date Date Yes - Event date: October 31, 2025
startTime Time Yes - Event start: 18:00 GMT+8
endTime Time Yes - Event end: 21:00 GMT+8
timezone String Yes "GMT+8" Timezone for event
location String Yes - "MITA Building 2F Pantry"
organizer Object Yes - Organizer details
organizer.name String Yes - "Jessi Pan"
organizer.email String Yes - "jessi.pan@cn.mcd.com"
activities Array Yes - List of activities
notes Array Yes - Additional information

Validation Rules:

  • date must be valid ISO date format
  • startTime must be before endTime
  • Times must be in 24-hour format (HH:MM)
  • organizer.email must be valid email format
  • activities must contain at least 1 item

Example:

{
  "title": "2025 MITA Halloween",
  "date": "2025-10-31",
  "startTime": "18:00",
  "endTime": "21:00",
  "timezone": "GMT+8",
  "location": "MITA Building 2F Pantry",
  "organizer": {
    "name": "Jessi Pan",
    "email": "jessi.pan@cn.mcd.com"
  },
  "activities": [
    "Cosplay (encouraged)",
    "Bug Debugging Games",
    "Lucky Draw"
  ],
  "notes": [
    "Costumes encouraged",
    "Food and drinks provided"
  ]
}

State Transitions: None (static data)


2. Countdown

Represents the countdown timer state and logic.

Purpose: Calculate and display time remaining until event

Fields:

Field Type Required Default Description
targetDateTime DateTime Yes - Oct 31 2025 18:00:00 GMT+8 (in UTC: 10:00:00 UTC)
currentDateTime DateTime Yes - User's current time (updated every second)
timeRemaining Object No null Calculated time remaining
timeRemaining.days Integer No 0 Days remaining
timeRemaining.hours Integer No 0 Hours remaining (0-23)
timeRemaining.minutes Integer No 0 Minutes remaining (0-59)
timeRemaining.seconds Integer No 0 Seconds remaining (0-59)
status Enum Yes "before" Current event status

Status Values:

  • before: Current time is before event start (show countdown)
  • active: Event has started, current time is between start and end (show "EVENT STARTING NOW!")
  • ended: Event has ended, current time is after event end (show "EVENT COMPLETED")

Validation Rules:

  • targetDateTime must be a valid Date object
  • All time values must be >= 0
  • status must be one of: "before", "active", "ended"
  • timeRemaining is null when status is not "before"

Calculation Logic:

// Convert GMT+8 to UTC for calculation
// Oct 31 2025 18:00 GMT+8 = Oct 31 2025 10:00 UTC
const targetDate = new Date('2025-10-31T10:00:00Z');
const eventEnd = new Date('2025-10-31T13:00:00Z'); // 21:00 GMT+8

function updateCountdown() {
  const now = new Date();

  if (now >= eventEnd) {
    return { status: 'ended', timeRemaining: null };
  }

  if (now >= targetDate) {
    return { status: 'active', timeRemaining: null };
  }

  const diff = targetDate - now;
  const days = Math.floor(diff / (1000 * 60 * 60 * 24));
  const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
  const seconds = Math.floor((diff % (1000 * 60)) / 1000);

  return {
    status: 'before',
    timeRemaining: { days, hours, minutes, seconds }
  };
}

State Transitions:

before → active (when current time >= targetDateTime)
active → ended (when current time >= eventEnd)

3. VisualTheme

Represents the visual design configuration.

Purpose: Define and apply consistent styling across the page

Fields:

Field Type Required Default Description
backgroundColor Color Yes "#000000" Pure black background
primaryColor Color Yes "#00FF00" Terminal green for main text
accentColor Color Yes "#FFBF00" Amber for key information
fontFamily String Yes See below Monospace font stack
fontSize Object Yes - Font sizes for different elements
fontSize.base String Yes "16px" Base font size
fontSize.heading String Yes "20px" Heading size
fontSize.small String Yes "14px" Small text size
asciiArt Object Yes - ASCII art content
asciiArt.logoDesktop String Yes - McDonald's logo for desktop
asciiArt.logoMobile String Yes - McDonald's logo for mobile
asciiArt.decorations Array Yes - Halloween ASCII decorations

Font Stack:

"Courier New", Monaco, Consolas, "Liberation Mono", Menlo, monospace

Validation Rules:

  • All color values must be valid hex format (#RRGGBB)
  • backgroundColor must be #000000 (black)
  • primaryColor and accentColor must meet WCAG AA contrast ratio with background
  • fontFamily must include at least one monospace fallback
  • ASCII art strings must contain only ASCII characters (0-127)

Example:

{
  "backgroundColor": "#000000",
  "primaryColor": "#00FF00",
  "accentColor": "#FFBF00",
  "fontFamily": "\"Courier New\", Monaco, Consolas, Menlo, monospace",
  "fontSize": {
    "base": "16px",
    "heading": "20px",
    "small": "14px"
  },
  "asciiArt": {
    "logoDesktop": "[Multi-line ASCII art]",
    "logoMobile": "[Simplified ASCII art]",
    "decorations": ["🎃", "👻", "🦇"]
  }
}

State Transitions: None (static configuration)


4. Content (Bilingual)

Represents bilingual text content structure.

Purpose: Store and display English/Chinese content pairs

Fields:

Field Type Required Default Description
section String Yes - Content section identifier
english String Yes - English text
chinese String Yes - Chinese text (Simplified)
order Integer Yes - Display order

Example Content Pairs:

[
  {
    "section": "date",
    "english": "Date: October 31, 2025",
    "chinese": "日期2025年10月31日",
    "order": 1
  },
  {
    "section": "time",
    "english": "Time: 18:00 - 21:00 (6:00 PM - 9:00 PM)",
    "chinese": "时间18:00 - 21:00",
    "order": 2
  },
  {
    "section": "location",
    "english": "Location: MITA Building 2F Pantry",
    "chinese": "地点MITA大厦2楼茶水间",
    "order": 3
  },
  {
    "section": "organizer",
    "english": "Organizer: Jessi Pan (jessi.pan@cn.mcd.com)",
    "chinese": "组织者Jessi Pan (jessi.pan@cn.mcd.com)",
    "order": 4
  }
]

Display Pattern:

<p lang="en">{english}</p>
<p lang="zh-CN">{chinese}</p>

Relationships

Event (1)
  ├── has timezone (1) → Countdown
  └── has theme (1) → VisualTheme

Countdown (1)
  └── uses targetDateTime from Event

VisualTheme (1)
  └── styles all Content

Content (many)
  └── derived from Event

HTML Representation

The data model maps to HTML structure as follows:

<main>
  <!-- VisualTheme.asciiArt.logoDesktop -->
  <header>
    <pre class="ascii-desktop">[McDonald's ASCII Logo]</pre>
    <pre class="ascii-mobile">[McDonald's ASCII Logo Simplified]</pre>
    <p class="tagline">i'm lovin' IT<span class="cursor">_</span></p>
  </header>

  <!-- Countdown -->
  <section class="countdown">
    <div id="countdown-display">
      <span id="days">0</span>d
      <span id="hours">0</span>h
      <span id="minutes">0</span>m
      <span id="seconds">0</span>s
    </div>
  </section>

  <!-- Event + Content (bilingual) -->
  <section class="event-info">
    <p lang="en">Date: {Event.date}</p>
    <p lang="zh-CN">日期:{Event.date}</p>
    <!-- ... more bilingual pairs -->
  </section>

  <!-- Event.activities -->
  <section class="activities">
    <p lang="en">Activities:</p>
    <p lang="zh-CN">活动:</p>
    <ul>
      <li lang="en">{activity}</li>
      <li lang="zh-CN">{activity_zh}</li>
    </ul>
  </section>

  <!-- VisualTheme.asciiArt.decorations -->
  <section class="decorations">
    <pre>{decoration}</pre>
  </section>
</main>

JavaScript Data Structure

const eventData = {
  event: {
    title: "2025 MITA Halloween",
    date: "2025-10-31",
    startTime: "18:00",
    endTime: "21:00",
    timezone: "GMT+8",
    location: "MITA Building 2F Pantry",
    organizer: {
      name: "Jessi Pan",
      email: "jessi.pan@cn.mcd.com"
    },
    activities: ["Cosplay", "Bug Debugging Games", "Lucky Draw"],
    notes: ["Costumes encouraged", "Food and drinks provided"]
  },

  countdown: {
    targetDateTime: new Date('2025-10-31T10:00:00Z'), // GMT+8 = UTC+8
    eventEnd: new Date('2025-10-31T13:00:00Z'),
    status: 'before',
    timeRemaining: null
  },

  theme: {
    backgroundColor: "#000000",
    primaryColor: "#00FF00",
    accentColor: "#FFBF00",
    fontFamily: '"Courier New", Monaco, Consolas, Menlo, monospace'
  }
};

Validation Contract

All data must conform to the schema defined in /contracts/page-content.schema.json.

See: page-content.schema.json

Notes

  • This is a static page, so data is hardcoded in HTML/JS
  • No database or API calls required
  • Data updates only via code changes
  • Countdown is the only dynamic data (calculated client-side)

Next Steps

  • Create contracts/page-content.schema.json (JSON Schema validation)
  • Create quickstart.md (testing checklist)
  • Update CLAUDE.md (agent context)