Files
mek-tech-consulting/market.js
T

101 lines
5.7 KiB
JavaScript
Raw Normal View History

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;