fix: Update district coordinates and improve unit seeding logic
This commit is contained in:
parent
9f9b14992d
commit
2c11cc5991
|
@ -64,7 +64,7 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
console.log("Processing unit:", unit.code_unit, unit.name, {
|
console.log("Processing unit:", unit.code_unit, unit.name, {
|
||||||
longitude: unit.longitude,
|
longitude: unit.longitude,
|
||||||
latitude: unit.latitude,
|
latitude: unit.latitude,
|
||||||
district: unit.district_name || unit.district_name
|
district: unit.district_name
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -75,7 +75,7 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
address: unit.address,
|
address: unit.address,
|
||||||
phone: unit.phone,
|
phone: unit.phone,
|
||||||
type: unit.type,
|
type: unit.type,
|
||||||
district: unit.district_name || unit.district_name || "",
|
district: unit.district_name || "",
|
||||||
district_id: unit.district_id,
|
district_id: unit.district_id,
|
||||||
},
|
},
|
||||||
geometry: {
|
geometry: {
|
||||||
|
@ -87,18 +87,6 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
// Only filter out units with BOTH coordinates being exactly 0, allow any valid coordinate
|
|
||||||
.filter((feature) => {
|
|
||||||
const coords = feature.geometry.coordinates;
|
|
||||||
const isValid = coords[0] !== 0 || coords[1] !== 0;
|
|
||||||
|
|
||||||
// Debug which units are being filtered out
|
|
||||||
if (!isValid) {
|
|
||||||
console.log("Filtering out unit with invalid coordinates:", feature.properties.id, feature.properties.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}, [unitsData])
|
}, [unitsData])
|
||||||
|
|
||||||
|
@ -123,7 +111,7 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
description: incident.description || "No description",
|
description: incident.description || "No description",
|
||||||
category: incident.crime_categories.name,
|
category: incident.crime_categories.name,
|
||||||
date: incident.timestamp,
|
date: incident.timestamp,
|
||||||
district: crime.districts?.name || "",
|
district: crime.districts.name,
|
||||||
district_id: crime.district_id,
|
district_id: crime.district_id,
|
||||||
categoryColor: categoryColorMap[incident.crime_categories.name] || "#22c55e",
|
categoryColor: categoryColorMap[incident.crime_categories.name] || "#22c55e",
|
||||||
distance_to_unit: incident.locations.distance_to_unit || "Unknown",
|
distance_to_unit: incident.locations.distance_to_unit || "Unknown",
|
||||||
|
@ -248,7 +236,7 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
zoom: 14,
|
zoom: 14,
|
||||||
pitch: 45,
|
pitch: 45,
|
||||||
bearing: 0,
|
bearing: 0,
|
||||||
duration: 1000,
|
duration: 2000,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set the selected unit and query parameters
|
// Set the selected unit and query parameters
|
||||||
|
@ -312,7 +300,7 @@ export default function UnitsLayer({ crimes, units = [], filterCategory, visible
|
||||||
zoom: 15,
|
zoom: 15,
|
||||||
pitch: 45,
|
pitch: 45,
|
||||||
bearing: 0,
|
bearing: 0,
|
||||||
duration: 1000,
|
duration: 2000,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create incident object from properties
|
// Create incident object from properties
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
Nama Unit,Alamat,Telepon,lat,long
|
unit,alamat,telepon,lat,long
|
||||||
Polres Jember,"Jl. R.A. Kartini No.17, Sawahan Cantian, Kepatihan, Kec. Patrang, Kabupaten Jember, Jawa Timur 68137",331-484285,-8.17092173103588,113.70548051820701
|
Polres Jember,"Jl. R.A. Kartini No.17, Sawahan Cantian, Kepatihan, Kec. Patrang, Kabupaten Jember, Jawa Timur 68137",331-484285,-8.170921731,113.7054805
|
||||||
Polsek Kaliwates,"Jl. Hayam Wuruk No.153 Kelurahan Sempusari Kecamatan Kaliwates Kabupaten Jember, Jawa Timur",0331-484026,-8.186524646936217,113.67250084656763
|
Polsek Kaliwates,"Jl. Hayam Wuruk No.153 Kelurahan Sempusari Kecamatan Kaliwates Kabupaten Jember, Jawa Timur",0331-484026,-8.186524647,113.6725008
|
||||||
Polsek Sumbersari,"Jl. MT Haryono, Sumbersari, Kabupaten Jember, Jawa Timur 68124",0331-330647,-8.183296304066134,113.74236702752034
|
Polsek Sumbersari,"Jl. MT Haryono, Sumbersari, Kabupaten Jember, Jawa Timur 68124",0331-330647,-8.183296304,113.742367
|
||||||
Polsek Patrang,"Jl. Slamet Riyadi No.48, Patrang, Jember, Jawa Timur 68111",0331-422569,-8.149057988295857,113.72303569447361
|
Polsek Patrang,"Jl. Slamet Riyadi No.48, Patrang, Jember, Jawa Timur 68111",0331-422569,-8.149057988,113.7230357
|
||||||
Polsek Arjasa,"Jl. Supriadi No.101, Krajan Selatan, Patemon, Kec. Pakusari, Kabupaten Jember, Jawa Timur 68191",0331-540116,-8.122196807958975,113.74731612680222
|
Polsek Arjasa,"Jl. Supriadi No.101, Krajan Selatan, Patemon, Kec. Pakusari, Kabupaten Jember, Jawa Timur 68191",0331-540116,-8.122196808,113.7473161
|
||||||
Polsek Jelbuk,"Leces II, Sukojember, Kec. Jelbuk, Kabupaten Jember, Jawa Timur 68192",0331-540110,-8.068867091094502,113.76484762708661
|
Polsek Jelbuk,"Leces II, Sukojember, Kec. Jelbuk, Kabupaten Jember, Jawa Timur 68192",0331-540110,-8.068867091,113.7648476
|
||||||
Polsek Kalisat,"Jl. DR. Wahidin, Krajan II, Kalisat, Kec. Kalisat, Kabupaten Jember, Jawa Timur 68161",0331-591110,-8.128279710551354,113.81238843263388
|
Polsek Kalisat,"Jl. DR. Wahidin, Krajan II, Kalisat, Kec. Kalisat, Kabupaten Jember, Jawa Timur 68161",0331-591110,-8.128279711,113.8123884
|
||||||
Polsek Sukowono,"Jl. Chairil Anwar, Krajan, Cumedak, Jember, Kabupaten Jember, Jawa Timur 64194",0331-566210,-8.051079803763889,113.83506285032118
|
Polsek Sukowono,"Jl. Chairil Anwar, Krajan, Cumedak, Jember, Kabupaten Jember, Jawa Timur 64194",0331-566210,-8.051079804,113.8350629
|
||||||
Polsek Sempolan,"Krajan, Sumberjati, Kec. Silo, Kabupaten Jember, Jawa Timur 68184",0331-521010,-8.186214080516393,113.87653656806364
|
Polsek Silo,"Krajan, Sumberjati, Kec. Silo, Kabupaten Jember, Jawa Timur 68184",0331-521010,-8.186214081,113.8765366
|
||||||
Polsek Sumber Jambe,"Jl. PB. Sudirman No.81, Pasar, Sumberjambe, Kec. Sumberjambe, Kabupaten Jember, Jawa Timur 68195",0331-566268,-8.067557248871932,113.9001121479762
|
Polsek Sumber Jambe,"Jl. PB. Sudirman No.81, Pasar, Sumberjambe, Kec. Sumberjambe, Kabupaten Jember, Jawa Timur 68195",0331-566268,-8.067557249,113.9001121
|
||||||
Polsek Ledokombo,"Jl. Bungur Ledokombo No.114, Pasar, Ledokombo, Kec. Ledokombo, Kabupaten Jember, Jawa Timur 68196",0331-591011,-8.135526826985,113.87370140934554
|
Polsek Ledokombo,"Jl. Bungur Ledokombo No.114, Pasar, Ledokombo, Kec. Ledokombo, Kabupaten Jember, Jawa Timur 68196",0331-591011,-8.135526827,113.8737014
|
||||||
Polsek Pakusari,"Jl. Prambanan, Krajan, Kertosari, Kec. Pakusari, Kabupaten Jember, Jawa Timur 68181",0331-4436043,-8.164534108294927,113.76611131781641
|
Polsek Pakusari,"Jl. Prambanan, Krajan, Kertosari, Kec. Pakusari, Kabupaten Jember, Jawa Timur 68181",0331-4436043,-8.164534108,113.7661113
|
||||||
Polsek Jenggawah,"Jl. Kawi No. 23 Jenggawah, Kab. Jember, Propinsi Jawa Timur 68171",0331-757330,-8.256791120691595,113.6522206707149
|
Polsek Jenggawah,"Jl. Kawi No. 23 Jenggawah, Kab. Jember, Propinsi Jawa Timur 68171",0331-757330,-8.256791121,113.6522207
|
||||||
Polsek Mayang,"Jl. Banyuwangi, Mayang, Majang, Jawa Timur 68182",0331-591512,-8.177356153143444,113.79956203127406
|
Polsek Mayang,"Jl. Banyuwangi, Mayang, Majang, Jawa Timur 68182",0331-591512,-8.177356153,113.799562
|
||||||
Polsek Mumbulsari,"Jl. Budi Utomo No.16, Mumbulsari, Kabupaten Jember, Jawa Timur 68174",0331-793262,-8.252854089767183,113.74221255216453
|
Polsek Mumbulsari,"Jl. Budi Utomo No.16, Mumbulsari, Kabupaten Jember, Jawa Timur 68174",0331-793262,-8.25285409,113.7422126
|
||||||
Polsek Tempurejo,"Jl. KH. Abdurrahman, Tempurejo, Jember, Jawa Timur 68173",0331-757410,-8.300592195854021,113.68858041964509
|
Polsek Tempurejo,"Jl. KH. Abdurrahman, Tempurejo, Jember, Jawa Timur 68173",0331-757410,-8.300592196,113.6885804
|
||||||
Polsek Rambipuji,"Jl. Dharmawangsa 47 Rambipuji, Curahancar, Rambipuji, Kec. Rambipuji, Kabupaten Jember, Jawa Timur 68152",0331-711430,-8.20428708115188,113.61328234847777
|
Polsek Rambipuji,"Jl. Dharmawangsa 47 Rambipuji, Curahancar, Rambipuji, Kec. Rambipuji, Kabupaten Jember, Jawa Timur 68152",0331-711430,-8.204287081,113.6132823
|
||||||
Polsek Sukorambi,"Jl. Mujahir No. 5, Sukorambi, Jember Lor, Patrang, Jember, Jawa Timur 68118",0331-489523,-8.169930311064727,113.6605586889699
|
Polsek Sukorambi,"Jl. Mujahir No. 5, Sukorambi, Jember Lor, Patrang, Jember, Jawa Timur 68118",0331-489523,-8.169930311,113.6605587
|
||||||
Polsek Panti,"Jalan Panglima Besar Sudirman 19 Desa Panti Kecamatan Panti, Jember Jawa Timur 68153",0331-711330,-8.17194959166762,113.62022456331853
|
Polsek Panti,"Jalan Panglima Besar Sudirman 19 Desa Panti Kecamatan Panti, Jember Jawa Timur 68153",0331-711330,-8.171949592,113.6202246
|
||||||
Polsek Bangsalsari,"Jl. Jenderal Ahmad Yani No.16, Kalisatan, Bangsalsari, Kec. Bangsalsari, Kabupaten Jember, Jawa Timur 68154",0331-711401,-8.200901080105067,113.5338098619667
|
Polsek Bangsalsari,"Jl. Jenderal Ahmad Yani No.16, Kalisatan, Bangsalsari, Kec. Bangsalsari, Kabupaten Jember, Jawa Timur 68154",0331-711401,-8.20090108,113.5338099
|
||||||
Polsek Balung,"Jl. Rambipuji-Balung, Jember, Jawa Timur 68152",0331-621210,-8.269718539539422,113.54065466193254
|
Polsek Balung,"Jl. Rambipuji-Balung, Jember, Jawa Timur 68152",0331-621210,-8.26971854,113.5406547
|
||||||
Polsek Ambulu,"Jl. Raya Suyitman, Ambulu, Jember, Jawa Timur 68172",0336-881007,-8.344079809223068,113.60731912704142
|
Polsek Ambulu,"Jl. Raya Suyitman, Ambulu, Jember, Jawa Timur 68172",0336-881007,-8.344079809,113.6073191
|
||||||
Polsek Wuluhan,"Jl. Ambulu, Wuluhan, Kabupaten Jember, Jawa Timur 68162",0336-881003,-8.338356022692308,113.55182787728441
|
Polsek Wuluhan,"Jl. Ambulu, Wuluhan, Kabupaten Jember, Jawa Timur 68162",0336-881003,-8.338356023,113.5518279
|
||||||
Polsek Puger,"Jl. Achmad Yani 57 Puger, Umbulsari, Kabupaten Jember, Jawa Timur 68164",0336-721119,-8.366494602192043,113.47296865214837
|
Polsek Puger,"Jl. Achmad Yani 57 Puger, Umbulsari, Kabupaten Jember, Jawa Timur 68164",0336-721119,-8.366494602,113.4729687
|
||||||
Polsek Gumukmas,"Jl. Achmad Yani 89 Gumukmas, Gumukmas, Jember, Jawa Timur 68165",0336-321391,-8.315087051246818,113.41296867361133
|
Polsek Gumukmas,"Jl. Achmad Yani 89 Gumukmas, Gumukmas, Jember, Jawa Timur 68165",0336-321391,-8.315087051,113.4129687
|
||||||
Polsek Kencong,"Jl. Diponegoro, No. 35, Kencong, Jember 68167",0336-321210,-8.279794453467883,113.37664036194629
|
Polsek Kencong,"Jl. Diponegoro, No. 35, Kencong, Jember 68167",0336-321210,-8.279794453,113.3766404
|
||||||
Polsek Tanggul,"Jl. Urip Sumoharjo N0.50 Tanggul 68155, Tanggul Wetan, Tanggul, Jawa Timur 68155",0336-441110,-8.16605008923455,113.46115044482765
|
Polsek Tanggul,"Jl. Urip Sumoharjo N0.50 Tanggul 68155, Tanggul Wetan, Tanggul, Jawa Timur 68155",0336-441110,-8.166050089,113.4611504
|
||||||
Polsek Sumberbaru,"Jl. Panglima Besar Sudirman, No. 3, Sumberbaru, Jember, Jawa Timur 68173",0336-324210,-8.119255727431387,113.39383676380444
|
Polsek Sumberbaru,"Jl. Panglima Besar Sudirman, No. 3, Sumberbaru, Jember, Jawa Timur 68173",0336-324210,-8.119255727,113.3938368
|
||||||
Polsek Semboro,"Jl. Telomoyo Dusun Semboro pasar, Desa Semboro, Jember, Jawa Timur 68157",0336-444200,-8.206242110979067,113.43480704846874
|
Polsek Semboro,"Jl. Telomoyo Dusun Semboro pasar, Desa Semboro, Jember, Jawa Timur 68157",0336-444200,-8.206242111,113.434807
|
||||||
Polsek Umbulsari,"Jl. Ahmad Yani No.44, Umbulsari, Jember, Jawa Timur 68166",0336-321191,-8.263912399533561,113.44837139079566
|
Polsek Umbulsari,"Jl. Ahmad Yani No.44, Umbulsari, Jember, Jawa Timur 68166",0336-321191,-8.2639124,113.4483714
|
||||||
Polsek Jombang,"Jl. KH. Dewantara No. 88 Jombang, Jember, Jawa Timur 68168",0336-321100,-8.245938093985266,113.32178564847065
|
Polsek Jombang,"Jl. KH. Dewantara No. 88 Jombang, Jember, Jawa Timur 68168",0336-321100,-8.245938094,113.3217856
|
||||||
Polsek Ajung,"Ajung Kulon, Ajung, Kec. Ajung, Kabupaten Jember, Jawa Timur 68175",,-8.215016859569301,113.66807277175127
|
Polsek Ajung,"Ajung Kulon, Ajung, Kec. Ajung, Kabupaten Jember, Jawa Timur 68175",,-8.21501686,113.6680728
|
||||||
|
|
|
|
@ -51,8 +51,8 @@ export const districtCenters = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
kecamatan: "Kaliwates",
|
kecamatan: "Kaliwates",
|
||||||
lat: -8.1725,
|
lat: -8.18488005872404,
|
||||||
lng: 113.6875,
|
lng: 113.66669228812724
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
kecamatan: "Kencong",
|
kecamatan: "Kencong",
|
||||||
|
|
|
@ -2,11 +2,13 @@ import { locations, PrismaClient, unit_type, units } from '@prisma/client';
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import { parse } from 'csv-parse';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { createClient } from '../../app/_utils/supabase/client';
|
import { createClient } from '../../app/_utils/supabase/client';
|
||||||
import { generateId, generateIdWithDbCounter } from '../../app/_utils/common';
|
import { generateId, generateIdWithDbCounter } from '../../app/_utils/common';
|
||||||
|
|
||||||
|
|
||||||
// Interface untuk data Excel row
|
// Interface untuk data Excel row
|
||||||
interface ExcelRow {
|
interface ExcelRow {
|
||||||
KESATUAN: string;
|
KESATUAN: string;
|
||||||
|
@ -46,6 +48,14 @@ interface CreateLocationDto {
|
||||||
location?: string;
|
location?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ICsvUnitLocations {
|
||||||
|
unit: string;
|
||||||
|
alamat: string;
|
||||||
|
telepon: string;
|
||||||
|
lat: string;
|
||||||
|
long: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class UnitSeeder {
|
export class UnitSeeder {
|
||||||
private mapboxToken: string;
|
private mapboxToken: string;
|
||||||
|
|
||||||
|
@ -103,15 +113,8 @@ export class UnitSeeder {
|
||||||
const address = polresLocation.address;
|
const address = polresLocation.address;
|
||||||
const phone = polresLocation.telepon?.replace(/-/g, '');
|
const phone = polresLocation.telepon?.replace(/-/g, '');
|
||||||
|
|
||||||
const polresId = await generateIdWithDbCounter('units', {
|
// Create a custom ID for Polres (using 00 as the district suffix)
|
||||||
prefix: 'UT',
|
const polresId = `UT-0000`;
|
||||||
segments: {
|
|
||||||
sequentialDigits: 4,
|
|
||||||
},
|
|
||||||
format: '{prefix}-{sequence}',
|
|
||||||
separator: '-',
|
|
||||||
uniquenessStrategy: 'counter',
|
|
||||||
});
|
|
||||||
|
|
||||||
unitsToInsert.push({
|
unitsToInsert.push({
|
||||||
city_id: city.id,
|
city_id: city.id,
|
||||||
|
@ -139,25 +142,8 @@ export class UnitSeeder {
|
||||||
// Wait for all location lookups to complete
|
// Wait for all location lookups to complete
|
||||||
const results = await Promise.all(locationPromises);
|
const results = await Promise.all(locationPromises);
|
||||||
|
|
||||||
// Generate all IDs upfront
|
|
||||||
const idPromises = Array(results.length)
|
|
||||||
.fill(0)
|
|
||||||
.map(() =>
|
|
||||||
generateIdWithDbCounter('units', {
|
|
||||||
prefix: 'UT',
|
|
||||||
segments: {
|
|
||||||
sequentialDigits: 4,
|
|
||||||
},
|
|
||||||
format: '{prefix}-{sequence}',
|
|
||||||
separator: '-',
|
|
||||||
uniquenessStrategy: 'counter',
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const ids = await Promise.all(idPromises);
|
|
||||||
|
|
||||||
// Process results and add to unitsToInsert
|
// Process results and add to unitsToInsert
|
||||||
results.forEach(({ district, location }, index) => {
|
results.forEach(({ district, location }) => {
|
||||||
if (!location) {
|
if (!location) {
|
||||||
console.warn(`No location found for district: ${district.name}`);
|
console.warn(`No location found for district: ${district.name}`);
|
||||||
return;
|
return;
|
||||||
|
@ -166,7 +152,11 @@ export class UnitSeeder {
|
||||||
const [lng, lat] = [location.lng, location.lat];
|
const [lng, lat] = [location.lng, location.lat];
|
||||||
const address = location.address;
|
const address = location.address;
|
||||||
const phone = location.telepon?.replace(/-/g, '');
|
const phone = location.telepon?.replace(/-/g, '');
|
||||||
const newId = ids[index];
|
|
||||||
|
// Extract the last two digits from district_id for the unit ID
|
||||||
|
const districtIdStr = district.id.toString();
|
||||||
|
const lastTwoDigits = districtIdStr.slice(-2);
|
||||||
|
const newId = `UT-00${lastTwoDigits}`;
|
||||||
|
|
||||||
unitsToInsert.push({
|
unitsToInsert.push({
|
||||||
district_id: district.id,
|
district_id: district.id,
|
||||||
|
@ -183,7 +173,7 @@ export class UnitSeeder {
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Prepared unit data for district: ${district.name}, ID: ${newId}`
|
`Prepared unit data for district: ${district.name}, ID: ${newId} (from district ID: ${district.id})`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -227,99 +217,119 @@ export class UnitSeeder {
|
||||||
address: string;
|
address: string;
|
||||||
telepon: string;
|
telepon: string;
|
||||||
} | null> {
|
} | null> {
|
||||||
// const getCoordinatesFromMapbox = async (
|
// Path to the CSV file
|
||||||
// query: string
|
|
||||||
// ): Promise<{ lng: number; lat: number } | null> => {
|
|
||||||
// const suggestUrl = `https://api.mapbox.com/search/searchbox/v1/suggest?q=${encodeURIComponent(
|
|
||||||
// query
|
|
||||||
// )}&session_token=${uuidv4()}&access_token=${this.mapboxToken}`;
|
|
||||||
|
|
||||||
// // console.log(`Suggest URL: ${suggestUrl}`);
|
|
||||||
|
|
||||||
// const res = await axios.get(suggestUrl);
|
|
||||||
// const suggestions = res?.data?.suggestions;
|
|
||||||
|
|
||||||
// if (!suggestions || suggestions.length === 0) return null;
|
|
||||||
|
|
||||||
// const mapboxId = suggestions[0].mapbox_id;
|
|
||||||
|
|
||||||
// // console.log(`Mapbox ID for ${query}: ${mapboxId}`);
|
|
||||||
|
|
||||||
// if (!mapboxId) return null;
|
|
||||||
|
|
||||||
// const retrieveUrl = `https://api.mapbox.com/search/searchbox/v1/retrieve/${mapboxId}?session_token=${uuidv4()}&access_token=${this.mapboxToken}`;
|
|
||||||
|
|
||||||
// // console.log(`Retrieve URL: ${retrieveUrl}`);
|
|
||||||
|
|
||||||
// const retrieveResponse = await axios.get(retrieveUrl);
|
|
||||||
// const features = retrieveResponse?.data.features;
|
|
||||||
|
|
||||||
// const [lng, lat] = features[0].geometry.coordinates;
|
|
||||||
|
|
||||||
// return { lng, lat };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Buka file Excel untuk ambil data nama dan alamat Polsek
|
|
||||||
const fallbackFilePath = path.join(
|
const fallbackFilePath = path.join(
|
||||||
__dirname,
|
__dirname,
|
||||||
'../data/excels/administrations/polsek_jember.xlsx'
|
'../data/excels/administrations/polsek_jember.csv'
|
||||||
);
|
);
|
||||||
|
|
||||||
const workbook = XLSX.readFile(fallbackFilePath);
|
try {
|
||||||
const sheetName = workbook.SheetNames[0];
|
// Read the CSV file
|
||||||
const sheet = workbook.Sheets[sheetName];
|
const csvData = await new Promise<ICsvUnitLocations[]>((resolve, reject) => {
|
||||||
const rows = XLSX.utils.sheet_to_json(sheet) as {
|
const results: ICsvUnitLocations[] = [];
|
||||||
'Nama Unit': string;
|
|
||||||
Alamat: string;
|
|
||||||
Telepon: string;
|
|
||||||
lat: number;
|
|
||||||
long: number;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
// Temukan Polsek berdasarkan kecamatan (nama kecamatan ada dalam alamat)
|
fs.createReadStream(fallbackFilePath)
|
||||||
const matchedRow = rows.find(
|
.pipe(parse({
|
||||||
(row) =>
|
columns: true,
|
||||||
row.Alamat?.toLowerCase().includes(districtName.toLowerCase()) ||
|
skip_empty_lines: true,
|
||||||
row['Nama Unit'].toLowerCase().includes(districtName.toLowerCase())
|
}))
|
||||||
);
|
.on('data', (data: ICsvUnitLocations) => results.push(data))
|
||||||
|
.on('end', () => resolve(results))
|
||||||
|
.on('error', (error) => reject(error));
|
||||||
|
});
|
||||||
|
|
||||||
// console.log(`Matched row for ${districtName}:`, matchedRow);
|
// Special handling for districts with similar names or potential conflicts
|
||||||
|
const exactMatchingRow = csvData.find(
|
||||||
if (!matchedRow) {
|
(row) => row.unit === `Polsek ${districtName}`
|
||||||
console.warn(
|
|
||||||
`No matching Polsek found in sheet for district: ${districtName}`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If we have an exact match, use it
|
||||||
|
if (exactMatchingRow) {
|
||||||
|
console.log(`Found exact match for district: ${districtName}`);
|
||||||
|
return this.parsePoliceUnitData(exactMatchingRow, districtName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case handling for conflicting districts (Mumbulsari and Umbulsari)
|
||||||
|
if (districtName.toLowerCase() === 'mumbulsari') {
|
||||||
|
// Check for exact match of Polsek Mumbulsari
|
||||||
|
const mumbulsariRow = csvData.find(
|
||||||
|
(row) => row.unit.toLowerCase() === 'polsek mumbulsari'
|
||||||
|
);
|
||||||
|
if (mumbulsariRow) {
|
||||||
|
return this.parsePoliceUnitData(mumbulsariRow, districtName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (districtName.toLowerCase() === 'umbulsari') {
|
||||||
|
// Check for exact match of Polsek Umbulsari
|
||||||
|
const umbulsariRow = csvData.find(
|
||||||
|
(row) => row.unit.toLowerCase() === 'polsek umbulsari'
|
||||||
|
);
|
||||||
|
if (umbulsariRow) {
|
||||||
|
return this.parsePoliceUnitData(umbulsariRow, districtName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For city name (Jember), find Polres
|
||||||
|
if (districtName.toLowerCase() === 'jember') {
|
||||||
|
const polresRow = csvData.find(
|
||||||
|
(row) => row.unit.toLowerCase().includes('polres')
|
||||||
|
);
|
||||||
|
if (polresRow) {
|
||||||
|
return this.parsePoliceUnitData(polresRow, districtName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// More flexible matching for other districts
|
||||||
|
const matchedRow = csvData.find(
|
||||||
|
(row) =>
|
||||||
|
row.unit.toLowerCase().includes(districtName.toLowerCase()) ||
|
||||||
|
row.alamat.toLowerCase().includes(districtName.toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matchedRow) {
|
||||||
|
console.warn(
|
||||||
|
`No matching Polsek found in CSV for district: ${districtName}`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.parsePoliceUnitData(matchedRow, districtName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error reading CSV for district ${districtName}:`, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to parse police unit data
|
||||||
|
private parsePoliceUnitData(row: ICsvUnitLocations, districtName: string): {
|
||||||
|
lng: number;
|
||||||
|
lat: number;
|
||||||
|
address: string;
|
||||||
|
telepon: string;
|
||||||
|
} | null {
|
||||||
|
// Double check that we have valid coordinates
|
||||||
|
const lng = parseFloat(row.long);
|
||||||
|
const lat = parseFloat(row.lat);
|
||||||
|
|
||||||
|
if (isNaN(lng) || isNaN(lat)) {
|
||||||
|
console.warn(`Invalid coordinates for district ${districtName}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const polsekName = matchedRow['Nama Unit'];
|
const polsekName = row.unit;
|
||||||
const polsekAddress = matchedRow.Alamat;
|
const polsekAddress = row.alamat;
|
||||||
const telepon = matchedRow.Telepon;
|
const telepon = row.telepon;
|
||||||
const coordinates = {
|
|
||||||
lng: matchedRow.long,
|
|
||||||
lat: matchedRow.lat,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ambil koordinat dari Mapbox, tapi alamat tetap pakai dari sheet
|
|
||||||
// const coordinates = await getCoordinatesFromMapbox(polsekName);
|
|
||||||
|
|
||||||
// if (!coordinates) {
|
|
||||||
// console.warn(`Mapbox couldn't find coordinates for: ${polsekName}`);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log(
|
|
||||||
// `Coordinates for ${polsekName} (${districtName}): ${coordinates.lng}, ${coordinates.lat}`
|
|
||||||
// );
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Polsek Name: ${polsekName}, Address: ${polsekAddress}, Telepon: ${telepon}`
|
`District: ${districtName} -> Polsek Name: ${polsekName}, Address: ${polsekAddress}, Coordinates: ${lng}, ${lat}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...coordinates,
|
lng,
|
||||||
|
lat,
|
||||||
telepon,
|
telepon,
|
||||||
address: polsekAddress, // ambil dari sheet, bukan dari Mapbox
|
address: polsekAddress,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue