generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } // prisma/schema.prisma // Enums // VillageObjectType: Defines the possible types of objects that can be placed in the village grid. enum VillageObjectType { HOUSE FIELD LUMBERJACK QUARRY WELL } enum TerrainType { EMPTY BLOCKED_TREE BLOCKED_STONE } enum TerrainState { IDLE CLEARING } // CropType: Defines the types of crops that can be planted. enum CropType { BLUEBERRIES CORN } // User: Represents a registered user and stores their core profile, // settings, and in-game resources like coins and experience points. model User { id Int @id @default(autoincrement()) email String @unique password String nickname String? avatar String? @default("/avatars/default.png") coins Int @default(0) exp Int @default(0) // User settings soundOn Boolean @default(true) confettiOn Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations habits Habit[] dailyVisits DailyVisit[] village Village? } // Habit: A recurring task a user wants to build. Each habit belongs to a // single user. The `daysOfWeek` field stores which days the habit is active. model Habit { id Int @id @default(autoincrement()) name String // `daysOfWeek` is a JSON array of numbers [0, 1, ..., 6], where 0 is Sunday. daysOfWeek Json createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int completions HabitCompletion[] } // HabitCompletion: Records a single completion of a habit on a specific date. // This creates a history of the user's progress for each habit. model HabitCompletion { id Int @id @default(autoincrement()) date DateTime // Store only the date part // Relations habit Habit @relation(fields: [habitId], references: [id], onDelete: Cascade) habitId Int @@unique([habitId, date]) // A habit can only be completed once per day } // DailyVisit: Tracks the user's daily visit for the "I visited the site today" // quest and for calculating 5-day streaks. model DailyVisit { id Int @id @default(autoincrement()) date DateTime // Store only the date part // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int @@unique([userId, date]) // A user can only have one recorded visit per day } // Village: The user's personal village, which acts as a container for all // village objects. Each user has exactly one village. model Village { id Int @id @default(autoincrement()) // Relations user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId Int @unique // Each user has only one village objects VillageObject[] tiles VillageTile[] } // VillageObject: An object (e.g., house, field) placed on a village tile. model VillageObject { id Int @id @default(autoincrement()) type VillageObjectType createdAt DateTime @default(now()) lastExpAt DateTime? // Crop details (only if type is FIELD) cropType CropType? plantedAt DateTime? // Relations village Village @relation(fields: [villageId], references: [id], onDelete: Cascade) villageId Int tile VillageTile @relation(fields: [tileId], references: [id]) tileId Int @unique } model VillageTile { id Int @id @default(autoincrement()) x Int y Int terrainType TerrainType terrainState TerrainState @default(IDLE) clearingStartedAt DateTime? // Relations village Village @relation(fields: [villageId], references: [id], onDelete: Cascade) villageId Int object VillageObject? @@unique([villageId, x, y]) }