101 lines
5.7 KiB
JavaScript
101 lines
5.7 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { getDb } = require('../db');
|
|
|
|
const CITY_COORDS = {
|
|
'Amsterdam':{lat:52.3676,lng:4.9041},'Rotterdam':{lat:51.9244,lng:4.4777},
|
|
'Den Haag':{lat:52.0705,lng:4.3007},'Utrecht':{lat:52.0907,lng:5.1214},
|
|
'Eindhoven':{lat:51.4416,lng:5.4697},'Groningen':{lat:53.2194,lng:6.5665},
|
|
'Tilburg':{lat:51.5719,lng:5.0672},'Almere':{lat:52.3508,lng:5.2647},
|
|
'Haarlem':{lat:52.3874,lng:4.6462},'Nijmegen':{lat:51.8126,lng:5.8372},
|
|
'Arnhem':{lat:51.9969,lng:6.1832},'Amersfoort':{lat:52.1561,lng:5.3878},
|
|
'Apeldoorn':{lat:52.2112,lng:5.9474},'Zwolle':{lat:52.5168,lng:6.0830},
|
|
'Enschede':{lat:52.2215,lng:6.8937},'Maastricht':{lat:50.8514,lng:5.6900},
|
|
'Leiden':{lat:52.1601,lng:4.4970},'Delft':{lat:51.9999,lng:4.3540},
|
|
'Breda':{lat:51.5719,lng:4.7683},'Hengelo':{lat:52.2636,lng:6.7945},
|
|
'Dronten':{lat:52.5689,lng:5.7175},'Schiphol-Rijk':{lat:52.2845,lng:4.7555},
|
|
'Schiphol':{lat:52.3105,lng:4.7683},'Zaandam':{lat:52.4382,lng:4.8158},
|
|
'Veldhoven':{lat:51.4184,lng:5.4030},'Deventer':{lat:52.2661,lng:6.1557},
|
|
'Wageningen':{lat:51.9692,lng:5.6653},'Eygelshoven':{lat:50.7639,lng:6.0473},
|
|
'Veghel':{lat:51.6665,lng:5.5556},'Leusden':{lat:52.1418,lng:5.4165},
|
|
'Rosmalen':{lat:51.6699,lng:5.7867},'Eemshaven':{lat:53.4430,lng:6.8530},
|
|
'Sliedrecht':{lat:51.8220,lng:4.7733}
|
|
};
|
|
|
|
router.get('/', (req, res) => {
|
|
const db = getDb();
|
|
const allDcs = db.prepare('SELECT * FROM datacenters').all();
|
|
const allCompanies = db.prepare('SELECT * FROM tech_companies').all();
|
|
const regions = [...new Set(allDcs.map(d => d.region).filter(Boolean))].sort();
|
|
const industries = [...new Set(allCompanies.map(c => c.industry).filter(Boolean))].sort();
|
|
const dwVendors = [...new Set(allCompanies.flatMap(c => (c.data_warehouse||'').split(',').map(s=>s.trim()).filter(Boolean)))].sort();
|
|
const allVendors = [...new Set(allDcs.flatMap(d => ((d.network_vendors||'')+','+(d.server_vendors||'')+','+(d.storage_vendors||'')).split(',').map(s=>s.trim()).filter(Boolean)))].sort();
|
|
const cities = [...new Set(allCompanies.map(c => c.city).filter(Boolean))].sort();
|
|
const totalPower = allDcs.reduce((s,d) => s + (d.power_mw||0), 0);
|
|
|
|
const dcMapPoints = allDcs.map(d => ({
|
|
name: d.name, city: d.city, region: d.region, operator: d.operator,
|
|
power: d.power_mw, tier: d.tier, type: d.type,
|
|
lat: (CITY_COORDS[d.city] || {}).lat || 52.0,
|
|
lng: (CITY_COORDS[d.city] || {}).lng || 5.0
|
|
}));
|
|
|
|
res.render('market-intel', {
|
|
datacenters: allDcs, companies: allCompanies, regions, industries, dwVendors, allVendors, cities,
|
|
totalPower, dcMapPoints
|
|
});
|
|
});
|
|
|
|
// Realtime API: search datacenters
|
|
router.get('/search/dc', (req, res) => {
|
|
const db = getDb();
|
|
const { search, vendor, region, type, sort } = req.query;
|
|
let sql = 'SELECT * FROM datacenters WHERE 1=1';
|
|
const params = [];
|
|
if (search) { sql += ' AND (name LIKE ? OR operator LIKE ? OR city LIKE ? OR network_vendors LIKE ? OR server_vendors LIKE ? OR storage_vendors LIKE ?)'; const s = '%'+search+'%'; params.push(s,s,s,s,s,s); }
|
|
if (vendor) { sql += ' AND (network_vendors LIKE ? OR server_vendors LIKE ? OR storage_vendors LIKE ?)'; const v = '%'+vendor+'%'; params.push(v,v,v); }
|
|
if (region) { sql += ' AND region LIKE ?'; params.push('%'+region+'%'); }
|
|
if (type) { sql += ' AND type = ?'; params.push(type); }
|
|
sql += ' ORDER BY ' + (sort === 'name' ? 'name' : 'power_mw DESC');
|
|
res.json(db.prepare(sql).all(...params));
|
|
});
|
|
|
|
// Realtime API: search companies
|
|
router.get('/search/co', (req, res) => {
|
|
const db = getDb();
|
|
const { search, industry, dw, city, sort } = req.query;
|
|
let sql = 'SELECT * FROM tech_companies WHERE 1=1';
|
|
const params = [];
|
|
if (search) { sql += ' AND (name LIKE ? OR industry LIKE ? OR city LIKE ? OR data_warehouse LIKE ? OR bi_tools LIKE ? OR cloud_provider LIKE ? OR ai_ml LIKE ? OR database_vendor LIKE ?)'; const s = '%'+search+'%'; params.push(s,s,s,s,s,s,s,s); }
|
|
if (industry) { sql += ' AND industry LIKE ?'; params.push('%'+industry+'%'); }
|
|
if (dw) { sql += ' AND data_warehouse LIKE ?'; params.push('%'+dw+'%'); }
|
|
if (city) { sql += ' AND city LIKE ?'; params.push('%'+city+'%'); }
|
|
sql += ' ORDER BY ' + (sort === 'name' ? 'name' : sort === 'employees' ? 'employees DESC' : 'lead_score DESC');
|
|
res.json(db.prepare(sql).all(...params));
|
|
});
|
|
|
|
// Map data
|
|
router.get('/map.json', (req, res) => {
|
|
const db = getDb();
|
|
const dcs = db.prepare('SELECT * FROM datacenters').all();
|
|
const companies = db.prepare('SELECT name, city, industry, employees, lead_score, data_warehouse FROM tech_companies').all();
|
|
const dcPoints = dcs.map(d => ({...d, lat: (CITY_COORDS[d.city]||{}).lat||52.0, lng: (CITY_COORDS[d.city]||{}).lng||5.0}));
|
|
const compPoints = companies.map(c => ({name:c.name, city:c.city, lat:(CITY_COORDS[c.city]||{}).lat||52.0, lng:(CITY_COORDS[c.city]||{}).lng||5.0, industry:c.industry, employees:c.employees, lead_score:c.lead_score}));
|
|
res.json({ datacenters: dcPoints, companies: compPoints });
|
|
});
|
|
|
|
// Filter options
|
|
router.get('/filters.json', (req, res) => {
|
|
const db = getDb();
|
|
const allDcs = db.prepare('SELECT * FROM datacenters').all();
|
|
const allCompanies = db.prepare('SELECT * FROM tech_companies').all();
|
|
res.json({
|
|
regions: [...new Set(allDcs.map(d => d.region).filter(Boolean))].sort(),
|
|
industries: [...new Set(allCompanies.map(c => c.industry).filter(Boolean))].sort(),
|
|
dwVendors: [...new Set(allCompanies.flatMap(c => (c.data_warehouse||'').split(',').map(s=>s.trim()).filter(Boolean)))].sort(),
|
|
cities: [...new Set(allCompanies.map(c => c.city).filter(Boolean))].sort(),
|
|
vendors: [...new Set(allDcs.flatMap(d => ((d.network_vendors||'')+','+(d.server_vendors||'')+','+(d.storage_vendors||'')).split(',').map(s=>s.trim()).filter(Boolean)))].sort()
|
|
});
|
|
});
|
|
|
|
module.exports = router; |