feat: core domain models (habits, village, quests)
This commit is contained in:
commit
0f85059e92
9
prisma/migrations/20260102113639_init/migration.sql
Normal file
9
prisma/migrations/20260102113639_init/migration.sql
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "User" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"email" TEXT NOT NULL,
|
||||||
|
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||||
3
prisma/migrations/migration_lock.toml
Normal file
3
prisma/migrations/migration_lock.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Please do not edit this file manually
|
||||||
|
# It should be added in your version-control system (e.g., Git)
|
||||||
|
provider = "sqlite"
|
||||||
116
prisma/schema.prisma
Normal file
116
prisma/schema.prisma
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
// prisma/schema.prisma
|
||||||
|
|
||||||
|
// Enums
|
||||||
|
// VillageObjectType: Defines the possible types of objects that can be placed in the village grid.
|
||||||
|
enum VillageObjectType {
|
||||||
|
HOUSE
|
||||||
|
FIELD
|
||||||
|
ROAD
|
||||||
|
FENCE
|
||||||
|
OBSTACLE
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 @db.Date // 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 @db.Date // 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[]
|
||||||
|
}
|
||||||
|
|
||||||
|
// VillageObject: An object (e.g., house, field, obstacle) placed on the
|
||||||
|
// village grid. It stores the object's type, its coordinates, and optionally
|
||||||
|
// details if it's an obstacle or a planted crop.
|
||||||
|
model VillageObject {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
type VillageObjectType
|
||||||
|
x Int
|
||||||
|
y Int
|
||||||
|
obstacleMetadata String? // Stores metadata for obstacles (e.g., "rock", "bush").
|
||||||
|
|
||||||
|
// Crop details (only if type is FIELD)
|
||||||
|
cropType CropType?
|
||||||
|
plantedAt DateTime?
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
village Village @relation(fields: [villageId], references: [id], onDelete: Cascade)
|
||||||
|
villageId Int
|
||||||
|
|
||||||
|
@@unique([villageId, x, y]) // Ensure only one object per grid cell per village
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user