Class Diagram - bounswe/bounswe2026group4 GitHub Wiki

Note: Diagram rendered using PlantUML via the PlantUML Integration plugin in IntelliJ IDEA.
code
@startuml
skinparam style strictuml
skinparam classAttributeIconSize 0
skinparam class {
BackgroundColor #FFF9E6
BorderColor #CC8800
ArrowColor #555555
HeaderBackgroundColor #FFE599
}
title Local History Story Map - Class Diagram
' ─────────────────────────────────────────
' USER HIERARCHY
' ─────────────────────────────────────────
class User {
-userId: String {id}
-email: String
-passwordHash: String
-username: String
-isUsernamePublic: Boolean
-createdAt: Date
-totalPoints: int
+login(email: String, password: String): boolean
+logout(): void
+register(email: String, username: String, password: String): void
+changePassword(oldPassword: String, newPassword: String): void
+resetPassword(email: String): void
+addPoints(points: int): void
+deductPoints(points: int): void
+getContributionCount(): int
+deleteAccount(): void
}
class UserProfile {
-profilePhoto: String
-location: String
-birthDate: Date
-bio: String
-isLocationPublic: Boolean
-isBirthDatePublic: Boolean
-isPhotoPublic: Boolean
+updateProfile(): void
+getPublicProfile(): UserProfile
+validatePhoto(): boolean
}
class Admin {
+reviewReport(reportId: String): void
+removeContent(contentId: String, reason: String): void
+banUser(userId: String): void
+resolveReport(reportId: String, outcome: String): void
+removeTag(tagId: String): void
+reviewTags(): Tag[]
+updateModerationPolicy(policy: String): void
}
' ─────────────────────────────────────────
' STORY
' ─────────────────────────────────────────
class Story {
-storyId: String {id}
-title: String
-narrativeText: String
-submissionDate: Date
-status: StoryStatus
-likeCount: int
-saveCount: int
-removalReason: String
+publish(): void
+remove(reason: String): void
+delete(): void
+edit(title: String, narrativeText: String): void
+getLikeCount(): int
}
enum "<<enumeration>>\nStoryStatus" as StoryStatus {
DRAFT
PUBLISHED
REMOVED
}
class StoryLocation {
-locationId: String {id}
-latitude: float
-longitude: float
-placeName: String
-region: String
+getCoordinates(): String
}
class TimePeriod {
-timePeriodId: String {id}
-startYear: int
-endYear: int
-approximatePeriod: String
+getDisplayLabel(): String
}
class Tag {
-tagId: String {id}
-name: String
-isPredefined: Boolean
+validate(): boolean
}
' ─────────────────────────────────────────
' MAP / FEED / TIMELINE
' ─────────────────────────────────────────
interface MapHandler {
+displayStoryPins(criteria: FilterCriteria): void
+selectLocation(): StoryLocation
+searchLocation(query: String): StoryLocation[]
+getPreview(storyId: String): Story
+zoomToRegion(region: String): void
+geocodeAddress(address: String): StoryLocation
}
interface FeedHandler {
+loadFeed(criteria: FilterCriteria): Story[]
+loadNextPage(): Story[]
+getDefaultFeed(userLocation: String): Story[]
+sortByRecent(): Story[]
+sortByPopular(): Story[]
}
interface TimelineHandler {
+loadTimeline(region: String): TimePeriod[]
+getStoriesForPeriod(timePeriodId: String): Story[]
+filterByLocation(location: String): void
}
class EmailService {
+sendVerificationCode(email: String): void
+sendPasswordResetLink(email: String): void
}
' ─────────────────────────────────────────
' FILTER
' ─────────────────────────────────────────
class FilterCriteria {
-keyword: String
-locationFilter: String
-startYear: int
-endYear: int
+addTagFilter(tag: Tag): void
+clearFilters(): void
+hasActiveFilters(): boolean
}
' ─────────────────────────────────────────
' MEDIA
' ─────────────────────────────────────────
class MediaFile {
-mediaId: String {id}
-fileType: MediaType
-fileSize: long
-filePath: String
-uploadedAt: Date
+validate(): boolean
+getMetadata(): String
}
enum "<<enumeration>>\nMediaType" as MediaType {
IMAGE
AUDIO
VIDEO
}
' ─────────────────────────────────────────
' INTERACTIONS
' ─────────────────────────────────────────
class Comment {
-commentId: String {id}
-text: String
-createdAt: Date
+create(): void
+delete(): void
}
class Like {
-likeId: String {id}
-createdAt: Date
+remove(): void
}
class SavedStory {
-savedAt: Date
+remove(): void
}
class Report {
-reportId: String {id}
-reason: ReportReason
-description: String
-createdAt: Date
-status: ReportStatus
-resolutionOutcome: String
+submit(): void
+resolve(outcome: String): void
}
enum "<<enumeration>>\nReportReason" as ReportReason {
SPAM
FALSE_CONTENT
HARASSMENT
PRIVACY_VIOLATION
EXPLICIT_MEDIA
OTHER
}
enum "<<enumeration>>\nReportStatus" as ReportStatus {
PENDING
RESOLVED
}
' ─────────────────────────────────────────
' GAMIFICATION
' ─────────────────────────────────────────
class Badge {
-badgeId: String {id}
-name: String
-description: String
-criteria: String
}
class UserBadge {
-awardedAt: Date
}
class NotificationPreference {
-preferenceId: String {id}
-type: NotificationType
-isEnabled: Boolean
+toggle(): void
}
class Notification {
-notificationId: String {id}
-message: String
-type: NotificationType
-isRead: Boolean
-createdAt: Date
+markAsRead(): void
}
enum "<<enumeration>>\nNotificationType" as NotificationType {
NEW_COMMENT
NEW_LIKE
MODERATION_ACTION
STORY_REMOVED
REPORT_RESOLVED
BADGE_EARNED
}
' ─────────────────────────────────────────
' RELATIONSHIPS
' ─────────────────────────────────────────
' 1. Admin inherits from User
Admin --|> User
' User - Profile (composition: profile deleted with user)
User "1"*-- "1" UserProfile : has
' User submits stories (aggregation: stories anonymized, not deleted)
User "1" o-- "0..*" Story : submits
' Story structure
Story "1"*-- "1" StoryLocation : located at
Story "1"*-- "1" TimePeriod : covers
Story "0..*" -- "0..3" Tag : tagged with
Story "1" *-- "0..*" MediaFile : contains
' Interactions
User "1" *-down- "0..*" Comment : writes
Story "1" *-- "0..*" Comment : has
User "1" -- "0..*" Like : gives
Story "1" *-- "0..*" Like : receives
User "1" *-down- "0..*" SavedStory :has
Story "1" *-- "0..*" SavedStory : saved via
' Reporting
User "1" -- "0..*" Report : submits
Story "1" -- "0..*" Report : reported by
Comment "1" -- "0..*" Report : reported by
' Admin
Admin "1" *-up- "0..*" Report : "reviews"
Admin ..> Tag
' Gamification (UserBadge as association class)
User "1" -- "0..*" UserBadge : earns
Badge "1" -- UserBadge : awarded as
User "1" *-- "0..*" Notification : receives
User "1" *-- "0..*" NotificationPreference : configures
' Map
MapHandler ..> Story : displays
MapHandler ..> StoryLocation : reads/creates
User ..> EmailService : uses
' Feed
FeedHandler ..> FilterCriteria : filters with
FeedHandler ..> Story : returns
' Timeline
TimelineHandler ..> TimePeriod : navigates
TimelineHandler ..> Story : returns
TimelineHandler ..> FilterCriteria : filters with
' Filter
FilterCriteria "0..*" -- "0..*" Tag : filters by
' Enums (dependency)
Story ..> StoryStatus
MediaFile ..> MediaType
Report ..> ReportReason
Report ..> ReportStatus
Notification ..> NotificationType
@enduml
'''