Bereinige und vereinfache Installations-Skripte
- Entferne alle überflüssigen Installations- und Konfigurationsskripte - Erstelle zwei vereinfachte Docker-Installationsskripte: - install-frontend.sh für Frontend-Installation - install-backend.sh für Backend-Installation - Verbessere Frontend Dockerfile mit besserer Unterstützung für native Dependencies - Aktualisiere Backend Dockerfile für automatische DB-Initialisierung - Korrigiere TypeScript-Fehler in personalized-cards.tsx - Erstelle env.ts für Umgebungsvariablen-Verwaltung - Füge ausführliche Installationsanleitung in INSTALL.md hinzu - Konfiguriere Docker-Compose für Host-Netzwerkmodus - Erweitere Dockerfiles mit Healthchecks für bessere Zuverlässigkeit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -1,367 +0,0 @@
|
||||
const sqlite3 = require("sqlite3");
|
||||
const faker = require("@faker-js/faker").faker;
|
||||
const { random, sample, sampleSize, sum } = require("lodash");
|
||||
const { DateTime } = require("luxon");
|
||||
const { open } = require("sqlite");
|
||||
const { v4: uuidv4 } = require("uuid");
|
||||
|
||||
const dbPath = "./db/sqlite.db";
|
||||
|
||||
// Configuration for test data generation
|
||||
let startDate = DateTime.fromISO("2024-10-08");
|
||||
let endDate = DateTime.fromISO("2024-11-08");
|
||||
let numberOfPrinters = 5;
|
||||
|
||||
// Use weekday names for better readability and ease of setting trends
|
||||
let avgPrintTimesPerDay = {
|
||||
Monday: 4,
|
||||
Tuesday: 2,
|
||||
Wednesday: 5,
|
||||
Thursday: 2,
|
||||
Friday: 3,
|
||||
Saturday: 0,
|
||||
Sunday: 0,
|
||||
}; // Average number of prints for each weekday
|
||||
|
||||
let avgPrintDurationPerDay = {
|
||||
Monday: 240, // Total average duration in minutes for Monday
|
||||
Tuesday: 30,
|
||||
Wednesday: 45,
|
||||
Thursday: 40,
|
||||
Friday: 120,
|
||||
Saturday: 0,
|
||||
Sunday: 0,
|
||||
}; // Average total duration of prints for each weekday
|
||||
|
||||
let printerUsage = {
|
||||
"Drucker 1": 0.5,
|
||||
"Drucker 2": 0.7,
|
||||
"Drucker 3": 0.6,
|
||||
"Drucker 4": 0.3,
|
||||
"Drucker 5": 0.4,
|
||||
}; // Usage percentages for each printer
|
||||
|
||||
// **New Configurations for Error Rates**
|
||||
let generalErrorRate = 0.05; // 5% chance any print job may fail
|
||||
let printerErrorRates = {
|
||||
"Drucker 1": 0.02, // 2% error rate for Printer 1
|
||||
"Drucker 2": 0.03,
|
||||
"Drucker 3": 0.01,
|
||||
"Drucker 4": 0.05,
|
||||
"Drucker 5": 0.04,
|
||||
}; // Error rates for each printer
|
||||
|
||||
const holidays = []; // Example holidays
|
||||
const existingJobs = [];
|
||||
|
||||
const initDB = async () => {
|
||||
console.log("Initializing database connection...");
|
||||
return open({
|
||||
filename: dbPath,
|
||||
driver: sqlite3.Database,
|
||||
});
|
||||
};
|
||||
|
||||
const createUser = (isPowerUser = false) => {
|
||||
const name = [faker.person.firstName(), faker.person.lastName()];
|
||||
|
||||
const user = {
|
||||
id: uuidv4(),
|
||||
github_id: faker.number.int(),
|
||||
username: `${name[0].slice(0, 2)}${name[1].slice(0, 6)}`.toUpperCase(),
|
||||
displayName: `${name[0]} ${name[1]}`.toUpperCase(),
|
||||
email: `${name[0]}.${name[1]}@example.com`,
|
||||
role: sample(["user", "admin"]),
|
||||
isPowerUser,
|
||||
};
|
||||
console.log("Created user:", user);
|
||||
return user;
|
||||
};
|
||||
|
||||
const createPrinter = (index) => {
|
||||
const printer = {
|
||||
id: uuidv4(),
|
||||
name: `Drucker ${index}`,
|
||||
description: faker.lorem.sentence(),
|
||||
status: random(0, 2),
|
||||
};
|
||||
console.log("Created printer:", printer);
|
||||
return printer;
|
||||
};
|
||||
|
||||
const isPrinterAvailable = (printer, startAt, duration) => {
|
||||
const endAt = startAt + duration * 60 * 1000; // Convert minutes to milliseconds
|
||||
return !existingJobs.some((job) => {
|
||||
const jobStart = job.startAt;
|
||||
const jobEnd = job.startAt + job.durationInMinutes * 60 * 1000;
|
||||
return (
|
||||
printer.id === job.printerId &&
|
||||
((startAt >= jobStart && startAt < jobEnd) ||
|
||||
(endAt > jobStart && endAt <= jobEnd) ||
|
||||
(startAt <= jobStart && endAt >= jobEnd))
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const createPrintJob = (users, printers, startAt, duration) => {
|
||||
const user = sample(users);
|
||||
let printer;
|
||||
|
||||
// Weighted selection based on printer usage
|
||||
const printerNames = Object.keys(printerUsage);
|
||||
const weightedPrinters = printers.filter((p) => printerNames.includes(p.name));
|
||||
|
||||
// Create a weighted array of printers based on usage percentages
|
||||
const printerWeights = weightedPrinters.map((p) => ({
|
||||
printer: p,
|
||||
weight: printerUsage[p.name],
|
||||
}));
|
||||
|
||||
const totalWeight = sum(printerWeights.map((pw) => pw.weight));
|
||||
const randomWeight = Math.random() * totalWeight;
|
||||
let accumulatedWeight = 0;
|
||||
for (const pw of printerWeights) {
|
||||
accumulatedWeight += pw.weight;
|
||||
if (randomWeight <= accumulatedWeight) {
|
||||
printer = pw.printer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!printer) {
|
||||
printer = sample(printers);
|
||||
}
|
||||
|
||||
if (!isPrinterAvailable(printer, startAt, duration)) {
|
||||
console.log("Printer not available, skipping job creation.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// **Determine if the job should be aborted based on error rates**
|
||||
let aborted = false;
|
||||
let abortReason = null;
|
||||
|
||||
// Calculate the combined error rate
|
||||
const printerErrorRate = printerErrorRates[printer.name] || 0;
|
||||
const combinedErrorRate = 1 - (1 - generalErrorRate) * (1 - printerErrorRate);
|
||||
|
||||
if (Math.random() < combinedErrorRate) {
|
||||
aborted = true;
|
||||
const errorMessages = [
|
||||
"Unbekannt",
|
||||
"Keine Ahnung",
|
||||
"Falsch gebucht",
|
||||
"Filament gelöst",
|
||||
"Druckabbruch",
|
||||
"Düsenverstopfung",
|
||||
"Schichthaftung fehlgeschlagen",
|
||||
"Materialmangel",
|
||||
"Dateifehler",
|
||||
"Temperaturproblem",
|
||||
"Mechanischer Fehler",
|
||||
"Softwarefehler",
|
||||
"Kalibrierungsfehler",
|
||||
"Überhitzung",
|
||||
];
|
||||
abortReason = sample(errorMessages); // Generate a random abort reason
|
||||
}
|
||||
|
||||
const printJob = {
|
||||
id: uuidv4(),
|
||||
printerId: printer.id,
|
||||
userId: user.id,
|
||||
startAt,
|
||||
durationInMinutes: duration,
|
||||
comments: faker.lorem.sentence(),
|
||||
aborted,
|
||||
abortReason,
|
||||
};
|
||||
console.log("Created print job:", printJob);
|
||||
return printJob;
|
||||
};
|
||||
|
||||
const generatePrintJobsForDay = async (users, printers, dayDate, totalJobsForDay, totalDurationForDay, db, dryRun) => {
|
||||
console.log(`Generating print jobs for ${dayDate.toISODate()}...`);
|
||||
|
||||
// Generate random durations that sum up approximately to totalDurationForDay
|
||||
const durations = [];
|
||||
let remainingDuration = totalDurationForDay;
|
||||
for (let i = 0; i < totalJobsForDay; i++) {
|
||||
const avgJobDuration = remainingDuration / (totalJobsForDay - i);
|
||||
const jobDuration = Math.max(
|
||||
Math.round(random(avgJobDuration * 0.8, avgJobDuration * 1.2)),
|
||||
5, // Minimum duration of 5 minutes
|
||||
);
|
||||
durations.push(jobDuration);
|
||||
remainingDuration -= jobDuration;
|
||||
}
|
||||
|
||||
// Shuffle durations to randomize job lengths
|
||||
const shuffledDurations = sampleSize(durations, durations.length);
|
||||
|
||||
for (let i = 0; i < totalJobsForDay; i++) {
|
||||
const duration = shuffledDurations[i];
|
||||
|
||||
// Random start time between 8 AM and 6 PM, adjusted to avoid overlapping durations
|
||||
const possibleStartHours = Array.from({ length: 10 }, (_, idx) => idx + 8); // 8 AM to 6 PM
|
||||
let startAt;
|
||||
let attempts = 0;
|
||||
do {
|
||||
const hour = sample(possibleStartHours);
|
||||
const minute = random(0, 59);
|
||||
startAt = dayDate.set({ hour, minute, second: 0, millisecond: 0 }).toMillis();
|
||||
attempts++;
|
||||
if (attempts > 10) {
|
||||
console.log("Unable to find available time slot, skipping job.");
|
||||
break;
|
||||
}
|
||||
} while (!isPrinterAvailable(sample(printers), startAt, duration));
|
||||
|
||||
if (attempts > 10) continue;
|
||||
|
||||
const printJob = createPrintJob(users, printers, startAt, duration);
|
||||
if (printJob) {
|
||||
if (!dryRun) {
|
||||
await db.run(
|
||||
`INSERT INTO printJob (id, printerId, userId, startAt, durationInMinutes, comments, aborted, abortReason)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
printJob.id,
|
||||
printJob.printerId,
|
||||
printJob.userId,
|
||||
printJob.startAt,
|
||||
printJob.durationInMinutes,
|
||||
printJob.comments,
|
||||
printJob.aborted ? 1 : 0,
|
||||
printJob.abortReason,
|
||||
],
|
||||
);
|
||||
}
|
||||
existingJobs.push(printJob);
|
||||
console.log("Inserted print job into database:", printJob.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const generateTestData = async (dryRun = false) => {
|
||||
console.log("Starting test data generation...");
|
||||
const db = await initDB();
|
||||
|
||||
// Generate users and printers
|
||||
const users = [
|
||||
...Array.from({ length: 7 }, () => createUser(false)),
|
||||
...Array.from({ length: 3 }, () => createUser(true)),
|
||||
];
|
||||
const printers = Array.from({ length: numberOfPrinters }, (_, index) => createPrinter(index + 1));
|
||||
|
||||
if (!dryRun) {
|
||||
// Insert users into the database
|
||||
for (const user of users) {
|
||||
await db.run(
|
||||
`INSERT INTO user (id, github_id, name, displayName, email, role)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
[user.id, user.github_id, user.username, user.displayName, user.email, user.role],
|
||||
);
|
||||
console.log("Inserted user into database:", user.id);
|
||||
}
|
||||
|
||||
// Insert printers into the database
|
||||
for (const printer of printers) {
|
||||
await db.run(
|
||||
`INSERT INTO printer (id, name, description, status)
|
||||
VALUES (?, ?, ?, ?)`,
|
||||
[printer.id, printer.name, printer.description, printer.status],
|
||||
);
|
||||
console.log("Inserted printer into database:", printer.id);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate print jobs for each day within the specified date range
|
||||
let currentDay = startDate;
|
||||
while (currentDay <= endDate) {
|
||||
const weekdayName = currentDay.toFormat("EEEE"); // Get weekday name (e.g., 'Monday')
|
||||
if (holidays.includes(currentDay.toISODate()) || avgPrintTimesPerDay[weekdayName] === 0) {
|
||||
console.log(`Skipping holiday or no jobs scheduled: ${currentDay.toISODate()}`);
|
||||
currentDay = currentDay.plus({ days: 1 });
|
||||
continue;
|
||||
}
|
||||
|
||||
const totalJobsForDay = avgPrintTimesPerDay[weekdayName];
|
||||
const totalDurationForDay = avgPrintDurationPerDay[weekdayName];
|
||||
|
||||
await generatePrintJobsForDay(users, printers, currentDay, totalJobsForDay, totalDurationForDay, db, dryRun);
|
||||
currentDay = currentDay.plus({ days: 1 });
|
||||
}
|
||||
|
||||
if (!dryRun) {
|
||||
await db.close();
|
||||
console.log("Database connection closed. Test data generation complete.");
|
||||
} else {
|
||||
console.log("Dry run complete. No data was written to the database.");
|
||||
}
|
||||
};
|
||||
|
||||
const setConfigurations = (config) => {
|
||||
if (config.startDate) startDate = DateTime.fromISO(config.startDate);
|
||||
if (config.endDate) endDate = DateTime.fromISO(config.endDate);
|
||||
if (config.numberOfPrinters) numberOfPrinters = config.numberOfPrinters;
|
||||
if (config.avgPrintTimesPerDay) avgPrintTimesPerDay = config.avgPrintTimesPerDay;
|
||||
if (config.avgPrintDurationPerDay) avgPrintDurationPerDay = config.avgPrintDurationPerDay;
|
||||
if (config.printerUsage) printerUsage = config.printerUsage;
|
||||
if (config.generalErrorRate !== undefined) generalErrorRate = config.generalErrorRate;
|
||||
if (config.printerErrorRates) printerErrorRates = config.printerErrorRates;
|
||||
};
|
||||
|
||||
// Example usage
|
||||
setConfigurations({
|
||||
startDate: "2024-10-08",
|
||||
endDate: "2024-11-08",
|
||||
numberOfPrinters: 6,
|
||||
avgPrintTimesPerDay: {
|
||||
Monday: 4, // High usage
|
||||
Tuesday: 2, // Low usage
|
||||
Wednesday: 3, // Low usage
|
||||
Thursday: 2, // Low usage
|
||||
Friday: 8, // High usage
|
||||
Saturday: 0,
|
||||
Sunday: 0,
|
||||
},
|
||||
avgPrintDurationPerDay: {
|
||||
Monday: 300, // High total duration
|
||||
Tuesday: 60, // Low total duration
|
||||
Wednesday: 90,
|
||||
Thursday: 60,
|
||||
Friday: 240,
|
||||
Saturday: 0,
|
||||
Sunday: 0,
|
||||
},
|
||||
printerUsage: {
|
||||
"Drucker 1": 2.3,
|
||||
"Drucker 2": 1.7,
|
||||
"Drucker 3": 0.1,
|
||||
"Drucker 4": 1.5,
|
||||
"Drucker 5": 2.4,
|
||||
"Drucker 6": 0.3,
|
||||
"Drucker 7": 0.9,
|
||||
"Drucker 8": 0.1,
|
||||
},
|
||||
generalErrorRate: 0.05, // 5% general error rate
|
||||
printerErrorRates: {
|
||||
"Drucker 1": 0.02,
|
||||
"Drucker 2": 0.03,
|
||||
"Drucker 3": 0.1,
|
||||
"Drucker 4": 0.05,
|
||||
"Drucker 5": 0.04,
|
||||
"Drucker 6": 0.02,
|
||||
"Drucker 7": 0.01,
|
||||
"PrinteDrucker 8": 0.03,
|
||||
},
|
||||
});
|
||||
|
||||
generateTestData(process.argv.includes("--dry-run"))
|
||||
.then(() => {
|
||||
console.log("Test data generation script finished.");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error generating test data:", err);
|
||||
});
|
Reference in New Issue
Block a user