MIF_E31221222/sigap-website/prisma/seeds/demographic.ts

128 lines
5.0 KiB
TypeScript

// prisma/seeds/DemographicsSeeder.ts
import { PrismaClient } from "@prisma/client";
export class DemographicsSeeder {
constructor(private prisma: PrismaClient) { }
async run(): Promise<void> {
console.log("Seeding demographics data...");
// Mendapatkan semua districts
const districts = await this.prisma.districts.findMany();
const cities = await this.prisma.cities.findMany();
// Seed demografis untuk 6 tahun terakhir
const currentYear = new Date().getFullYear();
const years = [currentYear - 5, currentYear - 4, currentYear - 3, currentYear - 2, currentYear - 1, currentYear];
// Menghapus data demographics yang sudah ada
await this.prisma.$executeRaw`TRUNCATE TABLE "demographics" CASCADE`;
let counter = 0;
// Untuk tiap tahun
for (const year of years) {
// Pertama generate data level district
const districtDemographics = [];
for (const district of districts) {
// Generate data demografis level district
const districtPopulation = this.getRandomNumber(10000, 100000);
const districtLandArea = await this.getDistrictLandArea(district.id);
const districtDensity = districtLandArea > 0
? districtPopulation / districtLandArea
: this.getRandomNumber(500, 3000);
const districtUnemployed = Math.floor(districtPopulation * this.getRandomNumber(0.03, 0.15));
// Simpan data district untuk agregasi level kota
districtDemographics.push({
district_id: district.id,
city_id: district.city_id,
population: districtPopulation,
unemployed: districtUnemployed,
density: districtDensity
});
// Simpan data demografis level district
await this.prisma.demographics.create({
data: {
city_id: district.city_id,
district_id: district.id,
year,
population: districtPopulation,
population_density: districtDensity,
number_of_unemployed: districtUnemployed
}
});
counter++;
}
// Kemudian generate data level kota berdasarkan agregasi dari district
for (const city of cities) {
// Filter district demographics untuk kota ini
const cityDistricts = districtDemographics.filter(d => d.city_id === city.id);
if (cityDistricts.length > 0) {
// Agregasi data dari semua district dalam kota
const cityPopulation = cityDistricts.reduce((sum, d) => sum + d.population, 0);
const cityUnemployed = cityDistricts.reduce((sum, d) => sum + d.unemployed, 0);
// Hitung total land area kota
const cityLandArea = await this.getCityLandArea(city.id);
// Hitung kepadatan populasi kota
const cityDensity = cityLandArea > 0
? cityPopulation / cityLandArea
: cityDistricts.reduce((sum, d) => sum + d.density, 0) / cityDistricts.length;
// Simpan data demografis level kota
await this.prisma.demographics.create({
data: {
city_id: city.id,
district_id: cityDistricts[0].district_id, // Menggunakan district pertama sebagai placeholder
year,
population: cityPopulation,
population_density: cityDensity,
number_of_unemployed: cityUnemployed
}
});
counter++;
}
}
}
console.log(`${counter} demographics records seeded`);
}
private getRandomNumber(min: number, max: number): number {
return Math.random() * (max - min) + min;
}
private async getDistrictLandArea(districtId: string): Promise<number> {
const geo = await this.prisma.geographics.findFirst({
where: { district_id: districtId }
});
return geo?.land_area || 0;
}
private async getCityLandArea(cityId: string): Promise<number> {
const geo = await this.prisma.geographics.findFirst({
where: {
city_id: cityId,
district_id: null
}
});
if (geo?.land_area) return geo.land_area;
// Jika tidak ada data land area level kota, jumlahkan dari semua district
const districtsGeo = await this.prisma.geographics.findMany({
where: { city_id: cityId, district_id: { not: null } }
});
return districtsGeo.reduce((sum, geo) => sum + (geo.land_area || 0), 0);
}
}