266 lines
8.0 KiB
JavaScript
266 lines
8.0 KiB
JavaScript
/**
|
|
* WalkGuide — Synthetic Test Data Generator
|
|
* Menghasilkan data dummy yang realistis untuk semua skenario load test.
|
|
*/
|
|
import { uuidv4 } from "https://jslib.k6.io/k6-utils/1.4.0/index.js";
|
|
|
|
// ── Alphabet untuk uniqueUserId (12 char alphanumeric) ──────────────────────
|
|
const ALPHANUM =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
|
|
function randomString(len, chars = ALPHANUM) {
|
|
let out = "";
|
|
for (let i = 0; i < len; i++) {
|
|
out += chars[Math.floor(Math.random() * chars.length)];
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function randomInt(min, max) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
}
|
|
|
|
function randomFloat(min, max, decimals = 6) {
|
|
return parseFloat((Math.random() * (max - min) + min).toFixed(decimals));
|
|
}
|
|
|
|
function randomElement(arr) {
|
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
}
|
|
|
|
// ── Koordinat realistis: sekitar Surabaya ───────────────────────────────────
|
|
const SURABAYA_CENTER = { lat: -7.2575, lng: 112.7521 };
|
|
|
|
export function randomSurabayaCoord(radiusDegrees = 0.05) {
|
|
return {
|
|
lat: SURABAYA_CENTER.lat + randomFloat(-radiusDegrees, radiusDegrees),
|
|
lng: SURABAYA_CENTER.lng + randomFloat(-radiusDegrees, radiusDegrees),
|
|
};
|
|
}
|
|
|
|
// ── User / Guardian data ─────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Generate payload untuk register GUARDIAN
|
|
*/
|
|
export function guardianRegisterPayload(suffix = "") {
|
|
const uid = suffix || randomString(8);
|
|
return {
|
|
email: `guardian_${uid}@walkguide-test.com`,
|
|
password: `Pass@${randomString(6)}!`,
|
|
displayName: `Guardian ${uid}`,
|
|
role: "ROLE_GUARDIAN",
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generate payload untuk register USER (tunanetra)
|
|
*/
|
|
export function userRegisterPayload(suffix = "") {
|
|
const uid = suffix || randomString(8);
|
|
return {
|
|
email: `user_${uid}@walkguide-test.com`,
|
|
password: `Pass@${randomString(6)}!`,
|
|
displayName: `User ${uid}`,
|
|
role: "ROLE_USER",
|
|
};
|
|
}
|
|
|
|
// ── Location data ────────────────────────────────────────────────────────────
|
|
|
|
const DIRECTION_LABELS = [
|
|
"NORTH",
|
|
"NORTHEAST",
|
|
"EAST",
|
|
"SOUTHEAST",
|
|
"SOUTH",
|
|
"SOUTHWEST",
|
|
"WEST",
|
|
"NORTHWEST",
|
|
];
|
|
|
|
/**
|
|
* Generate satu location update payload (simulasi GPS setiap 5 detik)
|
|
*/
|
|
export function locationUpdatePayload(
|
|
baseLat = SURABAYA_CENTER.lat,
|
|
baseLng = SURABAYA_CENTER.lng,
|
|
) {
|
|
return {
|
|
lat: baseLat + randomFloat(-0.001, 0.001),
|
|
lng: baseLng + randomFloat(-0.001, 0.001),
|
|
accuracy: randomFloat(3.0, 15.0, 1),
|
|
speed: randomFloat(0.5, 2.5, 2), // walking speed m/s
|
|
heading: randomFloat(0.0, 359.9, 1),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generate array of location updates (simulasi walking path)
|
|
*/
|
|
export function walkingPath(
|
|
steps = 10,
|
|
startLat = SURABAYA_CENTER.lat,
|
|
startLng = SURABAYA_CENTER.lng,
|
|
) {
|
|
const path = [];
|
|
let lat = startLat,
|
|
lng = startLng;
|
|
for (let i = 0; i < steps; i++) {
|
|
lat += randomFloat(-0.0002, 0.0002);
|
|
lng += randomFloat(-0.0002, 0.0002);
|
|
path.push({
|
|
lat,
|
|
lng,
|
|
accuracy: randomFloat(3, 10, 1),
|
|
speed: randomFloat(0.8, 1.8, 2),
|
|
heading: randomFloat(0, 360, 1),
|
|
});
|
|
}
|
|
return path;
|
|
}
|
|
|
|
// ── Obstacle data ────────────────────────────────────────────────────────────
|
|
|
|
const YOLO_LABELS = [
|
|
"person",
|
|
"car",
|
|
"motorcycle",
|
|
"bicycle",
|
|
"truck",
|
|
"bus",
|
|
"traffic light",
|
|
"stop sign",
|
|
"bench",
|
|
"chair",
|
|
"potted plant",
|
|
"fire hydrant",
|
|
"parking meter",
|
|
"dog",
|
|
"cat",
|
|
"suitcase",
|
|
];
|
|
|
|
const OBSTACLE_DIRECTIONS = ["LEFT", "CENTER", "RIGHT"];
|
|
const OBSTACLE_DISTANCES = ["Very Close", "Close", "Medium", "Far"];
|
|
|
|
/**
|
|
* Generate satu obstacle log payload (output YOLO detection)
|
|
*/
|
|
export function obstacleLogPayload() {
|
|
const coord = randomSurabayaCoord(0.02);
|
|
return {
|
|
label: randomElement(YOLO_LABELS),
|
|
confidence: randomFloat(0.5, 0.99, 4),
|
|
direction: randomElement(OBSTACLE_DIRECTIONS),
|
|
estimatedDist: randomElement(OBSTACLE_DISTANCES),
|
|
lat: coord.lat,
|
|
lng: coord.lng,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Generate burst obstacle logs (simulasi: 5 FPS deteksi selama beberapa detik)
|
|
*/
|
|
export function obstacleLogBurst(count = 5) {
|
|
return Array.from({ length: count }, () => obstacleLogPayload());
|
|
}
|
|
|
|
// ── SOS data ─────────────────────────────────────────────────────────────────
|
|
|
|
const SOS_TRIGGER_TYPES = ["VOICE_COMMAND", "BUTTON", "MANUAL"];
|
|
|
|
export function sosPayload() {
|
|
const coord = randomSurabayaCoord(0.03);
|
|
return {
|
|
triggerType: randomElement(SOS_TRIGGER_TYPES),
|
|
lat: coord.lat,
|
|
lng: coord.lng,
|
|
};
|
|
}
|
|
|
|
// ── Notification data ─────────────────────────────────────────────────────────
|
|
|
|
const NOTIFICATION_MESSAGES = [
|
|
"Hati-hati ada kendaraan di depan!",
|
|
"Sudah sampai tujuan belum?",
|
|
"Minta kabar, kamu baik-baik saja?",
|
|
"Ada yang bisa dibantu?",
|
|
"Jangan lupa berhati-hati di jalan.",
|
|
"Aku pantau dari sini ya.",
|
|
"Sudah mau hujan, cari tempat teduh.",
|
|
"Ada mobil di sebelah kanan!",
|
|
"Tolong berhenti dulu.",
|
|
"Aman ya? Jawab kalau dengar.",
|
|
];
|
|
|
|
export function sendNotificationPayload() {
|
|
return {
|
|
notifType: "TEXT",
|
|
content: randomElement(NOTIFICATION_MESSAGES),
|
|
};
|
|
}
|
|
|
|
// ── AI Config data ────────────────────────────────────────────────────────────
|
|
|
|
export function aiConfigPayload() {
|
|
return {
|
|
confidenceThreshold: randomFloat(0.3, 0.8, 2),
|
|
alertDistanceClose: randomFloat(1.0, 2.5, 1),
|
|
alertDistanceMedium: randomFloat(2.5, 5.0, 1),
|
|
maxInferenceFps: randomInt(3, 10),
|
|
enabledLabels: "ALL",
|
|
};
|
|
}
|
|
|
|
// ── User Settings data ────────────────────────────────────────────────────────
|
|
|
|
export function userSettingsPayload() {
|
|
return {
|
|
ttsLanguage: randomElement(["id-ID", "en-US"]),
|
|
ttsPitch: randomFloat(0.8, 1.5, 1),
|
|
ttsSpeed: randomFloat(0.7, 1.3, 1),
|
|
warnNoGuardian: true,
|
|
hapticEnabled: true,
|
|
};
|
|
}
|
|
|
|
// ── Geofence Config data ──────────────────────────────────────────────────────
|
|
|
|
export function geofenceConfigPayload() {
|
|
const coord = randomSurabayaCoord(0.01);
|
|
return {
|
|
centerLat: coord.lat,
|
|
centerLng: coord.lng,
|
|
radiusMeters: randomFloat(200, 1000, 0),
|
|
enabled: true,
|
|
};
|
|
}
|
|
|
|
// ── Unique user id (mirror dari backend logic) ───────────────────────────────
|
|
|
|
export function fakeUniqueUserId() {
|
|
return randomString(12);
|
|
}
|
|
|
|
// ── Generic helpers ───────────────────────────────────────────────────────────
|
|
|
|
export const testData = {
|
|
guardianRegisterPayload,
|
|
userRegisterPayload,
|
|
locationUpdatePayload,
|
|
walkingPath,
|
|
obstacleLogPayload,
|
|
obstacleLogBurst,
|
|
sosPayload,
|
|
sendNotificationPayload,
|
|
aiConfigPayload,
|
|
userSettingsPayload,
|
|
geofenceConfigPayload,
|
|
fakeUniqueUserId,
|
|
randomSurabayaCoord,
|
|
randomElement,
|
|
randomInt,
|
|
randomFloat,
|
|
};
|