fixing a ton of sloppy mess...
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
# Benchmark Evidence Template
|
||||
|
||||
This file is intentionally a template, not a fabricated result. Fill it after running benchmarks on the required machine/device.
|
||||
|
||||
## Flutter Device Benchmark
|
||||
|
||||
| Metric | Tool | Threshold | Result | Evidence File |
|
||||
|---|---|---:|---:|---|
|
||||
| Memory baseline | DevTools Memory | report MB | TBD | screenshot TBD |
|
||||
| Memory leak check | DevTools Memory | no steady growth | TBD | screenshot TBD |
|
||||
| Frame rate / jank | DevTools Performance | >= 90% frames < 16ms | TBD | screenshot TBD |
|
||||
| CPU profile | DevTools CPU Profiler | top 3 operations documented | TBD | screenshot TBD |
|
||||
| API latency | Dio logs | < 1500ms | TBD | log TBD |
|
||||
| Cold start | `flutter run --profile --trace-startup` | < 3000ms | TBD | trace TBD |
|
||||
| APK size | `flutter build apk --analyze-size` | < 50MB | TBD | report TBD |
|
||||
|
||||
## Backend Load Benchmark
|
||||
|
||||
| Metric | Tool | Threshold | Result | Evidence File |
|
||||
|---|---|---:|---:|---|
|
||||
| Throughput | k6/JMeter | >= 100 req/s | TBD | k6 summary TBD |
|
||||
| p95 latency | k6/JMeter | < 500ms | TBD | k6 summary TBD |
|
||||
| Error rate | k6/JMeter | < 1% | TBD | k6 summary TBD |
|
||||
| Slow query | DB/Actuator logs | no query > 200ms | TBD | log TBD |
|
||||
| JVM memory | Actuator metrics | no heap exhaustion | TBD | metrics TBD |
|
||||
|
||||
## Commands To Run
|
||||
|
||||
```powershell
|
||||
cd "D:\CodeSpace\Final Project Gabungan - Broken Test\walkguide-mobile\walkguide_app"
|
||||
flutter run --profile --trace-startup
|
||||
flutter build apk --analyze-size
|
||||
```
|
||||
|
||||
```bash
|
||||
cd "walkguide-backend/demo/k6-tests"
|
||||
./run-all-tests.sh smoke
|
||||
./run-all-tests.sh load
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
# WalkGuide Design Pattern Documentation
|
||||
|
||||
## Builder - Creational
|
||||
- Backend DTO/entity builders via Lombok `@Builder`.
|
||||
- Files: `PairingStatusResponse.java`, `AgoraTokenResponse.java`, entity classes such as `PairingRelation.java`.
|
||||
- Reason: response/entity construction has many optional fields, so builder calls are clearer than long constructors.
|
||||
|
||||
## Singleton / Service Locator - Creational
|
||||
- Flutter registers app-wide services once with GetIt.
|
||||
- File: `walkguide-mobile/walkguide_app/lib/app/injection_container.dart`.
|
||||
- Examples: `TtsService`, `WebSocketService`, `CallService`, `YoloDetector`.
|
||||
- Reason: resource-heavy services need one shared lifecycle.
|
||||
|
||||
## Facade - Structural
|
||||
- Flutter service classes hide low-level plugins from UI.
|
||||
- Files: `TtsService`, `HapticService`, `FcmService`, `CallService`, `WebSocketService`.
|
||||
- Reason: screens call simple domain-oriented methods instead of plugin APIs directly.
|
||||
|
||||
## Repository - Structural
|
||||
- Backend repositories abstract JPA persistence.
|
||||
- Files: `UserRepository`, `PairingRelationRepository`, `LocationHistoryRepository`, etc.
|
||||
- Reason: service layer works against repository contracts, not SQL.
|
||||
|
||||
## Observer - Behavioral
|
||||
- Flutter BLoC/Cubit and ChangeNotifier notify screens on state changes.
|
||||
- Backend WebSocket broker pushes location/SOS/notification updates to subscribers.
|
||||
- Files: `AppCubit`, `WebSocketService`, `LocationBroadcaster`.
|
||||
- Reason: real-time features need push updates without polling.
|
||||
|
||||
## Strategy - Behavioral
|
||||
- Obstacle direction/distance analysis can vary independently from camera capture.
|
||||
- File: `core/ai/obstacle_analyzer.dart`.
|
||||
- Reason: detection interpretation is isolated so thresholds/rules can evolve.
|
||||
|
||||
## Chain of Responsibility - Behavioral
|
||||
- Dio interceptors handle token injection, refresh, and error flow.
|
||||
- File: `core/network/api_client.dart`.
|
||||
- Reason: each request passes through consistent auth/error handling before reaching UI.
|
||||
@@ -0,0 +1,29 @@
|
||||
# WalkGuide Traceability Audit
|
||||
|
||||
## Use Case To Code
|
||||
|
||||
| Use Case | Flutter Entry | Backend Entry | Status |
|
||||
|---|---|---|---|
|
||||
| Register/Login | `features/auth/*` | `AuthController`, `AuthService` | Implemented |
|
||||
| Pair Guardian/User | `features/pairing/pairing_screens.dart` | `PairingController`, `PairingService` | Implemented |
|
||||
| Start/Stop WalkGuide | `features/walk_guide/walk_guide_screen.dart` | `POST /user/walkguide/start`, `POST /user/walkguide/stop` | Implemented |
|
||||
| Obstacle Detection | `core/ai/*`, `walk_guide_screen.dart` | `POST /user/obstacle` | Partially implemented; real `.tflite` model file still required |
|
||||
| Location Tracking | `LocationReporterService`, navigation/walk screens | `LocationService`, `LocationBroadcaster` | Implemented |
|
||||
| SOS | `features/sos/sos_screen.dart` | `SosService`, `GuardianController` | Implemented |
|
||||
| Notifications | `features/notifications/notification_screen.dart` | `NotificationService`, `FcmService` | Partially implemented; backend FCM is log-only without credentials |
|
||||
| Guardian Dashboard | `guardian_dashboard_screen.dart` | `GuardianDashboardService` | Implemented |
|
||||
| Call | `features/call/call_screen.dart`, `CallService` | `CallController`, `AgoraTokenService` | Partially implemented; Agora App ID/credential required for live call |
|
||||
| Geofence | guardian dashboard screens | `GeofenceService` | Implemented |
|
||||
|
||||
## Design Deviations
|
||||
|
||||
- Flutter uses a pragmatic mix of BLoC/Cubit, ChangeNotifier, and StatefulWidget. This deviates from strict full-BLoC architecture but keeps feature screens small for the exam demo.
|
||||
- Offline storage uses `SharedPreferences` queue instead of a full Drift database for cached entities. The dependency exists, but production-grade SQLite cache is not fully wired.
|
||||
- Backend FCM service is log-only until Firebase Admin credentials are provided.
|
||||
- Agora call flow is implemented at API and service level, but live RTC depends on a real Agora App ID.
|
||||
|
||||
## Remaining Evidence
|
||||
|
||||
- Export rendered OOAD diagrams from the PlantUML files in this folder.
|
||||
- Run backend tests and archive JaCoCo/Surefire reports.
|
||||
- Run Flutter benchmarks on a physical Android device and add screenshots/results.
|
||||
@@ -0,0 +1,71 @@
|
||||
@startuml
|
||||
skinparam classAttributeIconSize 0
|
||||
|
||||
class User {
|
||||
+Long id
|
||||
+String email
|
||||
+String role
|
||||
+String uniqueUserId
|
||||
+String displayName
|
||||
+String fcmToken
|
||||
}
|
||||
|
||||
class PairingRelation {
|
||||
+Long id
|
||||
+PairingStatus status
|
||||
+LocalDateTime invitedAt
|
||||
+LocalDateTime respondedAt
|
||||
}
|
||||
|
||||
class LocationHistory
|
||||
class ActivityLog
|
||||
class ObstacleLog
|
||||
class GuardianNotification
|
||||
class SosEvent
|
||||
class UserSettings
|
||||
class AiConfig
|
||||
class VoiceCommandConfig
|
||||
class HardwareShortcut
|
||||
class GeofenceConfig
|
||||
class RefreshToken
|
||||
|
||||
User "1" -- "0..*" LocationHistory
|
||||
User "1" -- "0..*" ActivityLog
|
||||
User "1" -- "0..*" ObstacleLog
|
||||
User "1" -- "0..*" SosEvent
|
||||
User "1" -- "0..1" UserSettings
|
||||
User "1" -- "0..*" RefreshToken
|
||||
User "1" -- "0..*" PairingRelation : guardian
|
||||
User "1" -- "0..*" PairingRelation : user
|
||||
PairingRelation "1" -- "0..*" GuardianNotification
|
||||
PairingRelation "1" -- "0..1" AiConfig
|
||||
PairingRelation "1" -- "0..*" VoiceCommandConfig
|
||||
PairingRelation "1" -- "0..*" HardwareShortcut
|
||||
PairingRelation "1" -- "0..1" GeofenceConfig
|
||||
|
||||
class AuthController
|
||||
class PairingController
|
||||
class UserController
|
||||
class GuardianController
|
||||
class CallController
|
||||
class AuthService
|
||||
class PairingService
|
||||
class LocationService
|
||||
class NotificationService
|
||||
class SosService
|
||||
class AgoraTokenService
|
||||
class FcmService
|
||||
class LocationBroadcaster
|
||||
|
||||
AuthController --> AuthService
|
||||
PairingController --> PairingService
|
||||
UserController --> LocationService
|
||||
UserController --> SosService
|
||||
GuardianController --> NotificationService
|
||||
GuardianController --> SosService
|
||||
CallController --> AgoraTokenService
|
||||
CallController --> FcmService
|
||||
LocationService --> LocationBroadcaster
|
||||
NotificationService --> LocationBroadcaster
|
||||
SosService --> LocationBroadcaster
|
||||
@enduml
|
||||
@@ -0,0 +1,35 @@
|
||||
@startuml
|
||||
skinparam componentStyle rectangle
|
||||
|
||||
component "Flutter Mobile App" {
|
||||
[Presentation Screens]
|
||||
[ApiClient + Interceptors]
|
||||
[TTS/STT/YOLO/Location Services]
|
||||
[WebSocketService]
|
||||
[CallService]
|
||||
}
|
||||
|
||||
component "Spring Boot Backend" {
|
||||
[Controllers]
|
||||
[Services]
|
||||
[Repositories]
|
||||
[Security/JWT]
|
||||
[WebSocket Broker]
|
||||
}
|
||||
|
||||
database "PostgreSQL" as DB
|
||||
cloud "Firebase FCM" as FCM
|
||||
cloud "Agora RTC" as Agora
|
||||
cloud "OpenStreetMap/OSRM" as Maps
|
||||
|
||||
[Presentation Screens] --> [ApiClient + Interceptors]
|
||||
[ApiClient + Interceptors] --> [Controllers] : REST /api/v1
|
||||
[WebSocketService] --> [WebSocket Broker] : STOMP /ws
|
||||
[CallService] --> [Controllers] : /shared/call
|
||||
[Controllers] --> [Services]
|
||||
[Services] --> [Repositories]
|
||||
[Repositories] --> DB
|
||||
[Services] --> FCM
|
||||
[CallService] --> Agora
|
||||
[Presentation Screens] --> Maps
|
||||
@enduml
|
||||
@@ -0,0 +1,101 @@
|
||||
@startuml
|
||||
hide circle
|
||||
skinparam linetype ortho
|
||||
|
||||
entity users {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
email : VARCHAR
|
||||
password : VARCHAR
|
||||
role : VARCHAR
|
||||
unique_user_id : CHAR(12)
|
||||
display_name : VARCHAR
|
||||
fcm_token : VARCHAR
|
||||
created_at : TIMESTAMP
|
||||
}
|
||||
|
||||
entity pairing_relations {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
guardian_id : BIGINT <<FK>>
|
||||
user_id : BIGINT <<FK>>
|
||||
status : VARCHAR
|
||||
invited_at : TIMESTAMP
|
||||
responded_at : TIMESTAMP
|
||||
}
|
||||
|
||||
entity activity_logs {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
user_id : BIGINT <<FK>>
|
||||
log_type : VARCHAR
|
||||
description : TEXT
|
||||
metadata : JSONB
|
||||
created_at : TIMESTAMP
|
||||
}
|
||||
|
||||
entity obstacle_logs {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
user_id : BIGINT <<FK>>
|
||||
label : VARCHAR
|
||||
confidence : FLOAT
|
||||
direction : VARCHAR
|
||||
estimated_dist : VARCHAR
|
||||
lat : DOUBLE
|
||||
lng : DOUBLE
|
||||
}
|
||||
|
||||
entity location_history {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
user_id : BIGINT <<FK>>
|
||||
lat : DOUBLE
|
||||
lng : DOUBLE
|
||||
accuracy : FLOAT
|
||||
speed : FLOAT
|
||||
heading : FLOAT
|
||||
}
|
||||
|
||||
entity guardian_notifications {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
guardian_id : BIGINT <<FK>>
|
||||
user_id : BIGINT <<FK>>
|
||||
notif_type : VARCHAR
|
||||
content : TEXT
|
||||
is_read : BOOLEAN
|
||||
}
|
||||
|
||||
entity sos_events {
|
||||
* id : BIGSERIAL <<PK>>
|
||||
--
|
||||
user_id : BIGINT <<FK>>
|
||||
trigger_type : VARCHAR
|
||||
lat : DOUBLE
|
||||
lng : DOUBLE
|
||||
status : VARCHAR
|
||||
}
|
||||
|
||||
entity user_settings
|
||||
entity ai_configs
|
||||
entity voice_command_configs
|
||||
entity hardware_shortcuts
|
||||
entity geofence_configs
|
||||
entity refresh_tokens
|
||||
|
||||
users ||--o{ pairing_relations : guardian_id
|
||||
users ||--o{ pairing_relations : user_id
|
||||
users ||--o{ activity_logs
|
||||
users ||--o{ obstacle_logs
|
||||
users ||--o{ location_history
|
||||
users ||--o{ guardian_notifications : guardian_id
|
||||
users ||--o{ guardian_notifications : user_id
|
||||
users ||--o{ sos_events
|
||||
users ||--o| user_settings
|
||||
users ||--o{ refresh_tokens
|
||||
pairing_relations ||--o| ai_configs
|
||||
pairing_relations ||--o{ voice_command_configs
|
||||
pairing_relations ||--o{ hardware_shortcuts
|
||||
pairing_relations ||--o| geofence_configs
|
||||
@enduml
|
||||
@@ -0,0 +1,19 @@
|
||||
@startuml
|
||||
actor User
|
||||
participant "Flutter LoginScreen" as UI
|
||||
participant "ApiClient/Dio" as Dio
|
||||
participant "AuthController" as Controller
|
||||
participant "AuthService" as Service
|
||||
database "PostgreSQL" as DB
|
||||
|
||||
User -> UI : enter email/password
|
||||
UI -> Dio : POST /api/v1/auth/login
|
||||
Dio -> Controller : LoginRequest
|
||||
Controller -> Service : login(req)
|
||||
Service -> DB : find user + refresh token
|
||||
DB --> Service : user
|
||||
Service --> Controller : AuthDataResponse
|
||||
Controller --> Dio : ApiResponse<AuthDataResponse>
|
||||
Dio --> UI : tokens + role
|
||||
UI -> UI : save tokens and route by role
|
||||
@enduml
|
||||
@@ -0,0 +1,23 @@
|
||||
@startuml
|
||||
actor Guardian
|
||||
actor User
|
||||
participant "GuardianPairingScreen" as GUI
|
||||
participant "PairingController" as Controller
|
||||
participant "PairingService" as Service
|
||||
database "PostgreSQL" as DB
|
||||
participant "FcmService" as FCM
|
||||
|
||||
Guardian -> GUI : input uniqueUserId
|
||||
GUI -> Controller : POST /shared/pairing/invite
|
||||
Controller -> Service : inviteUser(guardianId, uniqueUserId)
|
||||
Service -> DB : validate and create PENDING relation
|
||||
Service -> FCM : notify user
|
||||
Service --> Controller : PairingStatusResponse
|
||||
Controller --> GUI : invite status
|
||||
|
||||
User -> Controller : POST /shared/pairing/respond
|
||||
Controller -> Service : respondToPairing(userId, pairingId, accept)
|
||||
Service -> DB : update ACTIVE/REJECTED
|
||||
Service -> DB : seed default AI/voice/shortcut configs
|
||||
Service -> FCM : notify guardian
|
||||
@enduml
|
||||
@@ -0,0 +1,22 @@
|
||||
@startuml
|
||||
actor User
|
||||
actor Guardian
|
||||
participant "SosScreen" as UI
|
||||
participant "UserController" as UserController
|
||||
participant "SosService" as SosService
|
||||
database "PostgreSQL" as DB
|
||||
participant "FcmService" as FCM
|
||||
participant "LocationBroadcaster" as WS
|
||||
participant "GuardianDashboard" as Dashboard
|
||||
|
||||
User -> UI : press SOS / voice command
|
||||
UI -> UserController : POST /api/v1/user/sos
|
||||
UserController -> SosService : triggerSos(userId, req)
|
||||
SosService -> DB : save sos_events
|
||||
SosService -> FCM : push high-priority SOS
|
||||
SosService -> WS : /queue/sos/{guardianId}
|
||||
WS -> Dashboard : realtime SOS alert
|
||||
Guardian -> Dashboard : acknowledge
|
||||
Dashboard -> SosService : PUT /guardian/sos/{id}/acknowledge
|
||||
SosService -> DB : status ACKNOWLEDGED
|
||||
@enduml
|
||||
@@ -0,0 +1,7 @@
|
||||
@startuml
|
||||
[*] --> TRIGGERED : User sends SOS
|
||||
TRIGGERED --> ACKNOWLEDGED : Guardian acknowledges
|
||||
ACKNOWLEDGED --> RESOLVED : incident handled
|
||||
TRIGGERED --> RESOLVED : auto/manual close
|
||||
RESOLVED --> [*]
|
||||
@enduml
|
||||
@@ -0,0 +1,45 @@
|
||||
@startuml
|
||||
left to right direction
|
||||
actor "User\n(Visually Impaired)" as User
|
||||
actor "Guardian" as Guardian
|
||||
actor "Firebase FCM" as FCM
|
||||
actor "Agora RTC" as Agora
|
||||
actor "OpenStreetMap/OSRM" as Map
|
||||
|
||||
rectangle "WalkGuide System" {
|
||||
usecase "Register/Login" as UCAuth
|
||||
usecase "Pair Guardian and User" as UCPair
|
||||
usecase "Start WalkGuide" as UCWalk
|
||||
usecase "Detect Obstacle" as UCDetect
|
||||
usecase "Report Location" as UCLoc
|
||||
usecase "Trigger SOS" as UCSos
|
||||
usecase "Read Notifications" as UCNotif
|
||||
usecase "Call Partner" as UCCall
|
||||
usecase "Monitor Dashboard" as UCDash
|
||||
usecase "Configure AI, TTS,\nVoice Commands, Geofence" as UCConfig
|
||||
usecase "Acknowledge SOS" as UCAck
|
||||
usecase "Navigate Route" as UCNav
|
||||
}
|
||||
|
||||
User --> UCAuth
|
||||
Guardian --> UCAuth
|
||||
Guardian --> UCPair
|
||||
User --> UCPair
|
||||
User --> UCWalk
|
||||
UCWalk --> UCDetect : <<include>>
|
||||
UCWalk --> UCLoc : <<include>>
|
||||
User --> UCSos
|
||||
User --> UCNotif
|
||||
User --> UCCall
|
||||
Guardian --> UCCall
|
||||
Guardian --> UCDash
|
||||
Guardian --> UCConfig
|
||||
Guardian --> UCAck
|
||||
User --> UCNav
|
||||
|
||||
UCSos --> FCM
|
||||
UCNotif --> FCM
|
||||
UCCall --> Agora
|
||||
UCCall --> FCM
|
||||
UCNav --> Map
|
||||
@enduml
|
||||
Reference in New Issue
Block a user