From 2fec833aef6553e145f3b9db67246a94bad0a4d6 Mon Sep 17 00:00:00 2001 From: vjrj Date: Tue, 30 Jan 2018 18:05:11 +0100 Subject: [PATCH] Better publication and count of active fires in current map --- .../api/ActiveFires/server/publications.js | 110 +++--------------- imports/api/FireAlerts/server/publications.js | 38 +++++- imports/modules/server/other-checks.js | 25 ++++ imports/ui/pages/FiresMap/FiresMap.js | 66 ++++++----- 4 files changed, 111 insertions(+), 128 deletions(-) create mode 100644 imports/modules/server/other-checks.js diff --git a/imports/api/ActiveFires/server/publications.js b/imports/api/ActiveFires/server/publications.js index 1af883f..0b9b2d7 100644 --- a/imports/api/ActiveFires/server/publications.js +++ b/imports/api/ActiveFires/server/publications.js @@ -3,8 +3,8 @@ /* eslint-disable prefer-arrow-callback */ import { Meteor } from 'meteor/meteor'; -import { check, Match } from 'meteor/check'; -import { localize } from '/imports/startup/server/IPGeocoder'; +import { check } from 'meteor/check'; +import { NumberBetween } from '/imports/modules/server/other-checks'; import ActiveFires from '../ActiveFires'; const counter = new Counter('countActiveFires', ActiveFires.find({})); @@ -13,60 +13,14 @@ Meteor.publish('activefirestotal', function total() { return counter; }); -const validZoom = Match.Where((zoom) => { - // http://wiki.openstreetmap.org/wiki/Zoom_levels - check(zoom, Number); - return zoom >= 0 && zoom <= 19; -}); - -// https://github.com/3stack-software/meteor-match-library -function NumberBetween(min, max) { - return Match.Where((x) => { - check(x, Number); - return min <= x && x <= max; - }); -} - -function NullOr(type) { - return Match.Where((x) => { - if (x === null) { - return true; - } - check(x, type); - return true; - }); -} - -// http://wiki.openstreetmap.org/wiki/Zoom_levels -// http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale - -// http://cwestblog.com/2012/11/12/javascript-degree-and-radian-conversion/ -Math.radians = (degrees) => { - const rad = (degrees * Math.PI) / 180; - return rad; -}; - -const activefires = (zoom, lat, lng, height, width) => { - // latitude -90 and 90 and the longitude between -180 and 180 - check(lat, NumberBetween(-90, 90)); - check(lng, NumberBetween(-180, 180)); - - // console.log("Zoom: " + zoom + " lat: " + lat + " lng: " + lng); - const resolution = (156543.03 * Math.cos(Math.radians(lat))) / (2 ** zoom); - const distUnt = resolution * Math.max(height, width); - const distance = Math.trunc(distUnt); - // console.log(`so ${height}x${width} gives ${Math.trunc(resolution*height/1000)} x ${Math.trunc(resolution*width/1000)} km, so looking in ${distance}`); - // console.log(`So ${height}x${width} gives ${Math.trunc(resolution)} of resolution, so looking in ${Math.trunc(distance / 1000)}km`); - +const activefires = (northEastLng, northEastLat, southWestLng, southWestLat) => { const fires = ActiveFires.find({ ourid: { - $near: { - $geometry: { - type: 'Point', - coordinates: [lng, lat] - }, - $minDistance: 0, - $maxDistance: distance + $geoWithin: { + $box: [ + [southWestLng, southWestLat], + [northEastLng, northEastLat] + ] } } }, { @@ -80,48 +34,12 @@ const activefires = (zoom, lat, lng, height, width) => { return fires; }; - -Meteor.publish('allActiveFires', function allActive() { +Meteor.publish('activefiresmyloc', function activeInMyLoc(northEastLng, northEastLat, southWestLng, southWestLat) { // latitude -90 and 90 and the longitude between -180 and 180 + check(northEastLng, NumberBetween(-180, 180)); + check(southWestLat, NumberBetween(-90, 90)); + check(southWestLng, NumberBetween(-180, 180)); + check(northEastLat, NumberBetween(-90, 90)); - const { latitude, longitude } = localize().location; - // console.log(`${latitude}, ${longitude}`); - check(latitude, NumberBetween(-90, 90)); - check(longitude, NumberBetween(-180, 180)); - // https://docs.meteor.com/api/collections.html#Mongo-Collection-find - return ActiveFires.find({ - ourid: { - $near: { - $geometry: { - type: 'Point', - coordinates: [longitude, latitude] - }, - $minDistance: 0, - $maxDistance: 1000 // 156412000 - } - } - }, { - fields: { - _id: 0, - lat: 1, - lon: 1, - scan: 1 - }, - maxTimeMs: 30000 - }); -}); - -Meteor.publish('activefiresmyloc', function activeInMyLoc(zoom, lat, lng, height, width) { - check(zoom, validZoom); - check(lat, NullOr(Number)); - check(lng, NullOr(Number)); - check(height, NullOr(Number)); - check(width, NullOr(Number)); - // console.log(`Check active fires in ${lat},${lng} with zoom ${zoom} pixels in ${height}x${width} map`); - if (lat && lng) { - return activefires(zoom, lat, lng, height, width); - } - const geo = localize(); - // console.log(`${location.latitude}, ${location.longitude}`); - return activefires(zoom, geo.location.latitude, geo.location.longitude, height, width); + return activefires(northEastLng, northEastLat, southWestLng, southWestLat); }); diff --git a/imports/api/FireAlerts/server/publications.js b/imports/api/FireAlerts/server/publications.js index b3f5310..0b9c825 100644 --- a/imports/api/FireAlerts/server/publications.js +++ b/imports/api/FireAlerts/server/publications.js @@ -1,8 +1,42 @@ /* eslint-disable prefer-arrow-callback */ +/* eslint-disable import/no-absolute-path */ import { Meteor } from 'meteor/meteor'; +import { check } from 'meteor/check'; +import { NumberBetween } from '/imports/modules/server/other-checks'; +import moment from 'moment'; import FireAlerts from '../FireAlerts'; -Meteor.publish('fireAlerts', function fireAlerts() { - return FireAlerts.find(); +Meteor.publish('fireAlerts', function fireAlerts(northEastLng, northEastLat, southWestLng, southWestLat) { + // latitude -90 and 90 and the longitude between -180 and 180 + check(northEastLng, NumberBetween(-180, 180)); + check(southWestLat, NumberBetween(-90, 90)); + check(southWestLng, NumberBetween(-180, 180)); + check(northEastLat, NumberBetween(-90, 90)); + + // https://stackoverflow.com/questions/29327222/mongodb-find-created-results-by-date-today/29327353 + const start = new Date(); + start.setHours(0, 0, 0, 0); + const end = new Date(); + end.setHours(23, 59, 59, 999); + + const fires = FireAlerts.find({ + ourid: { + $geoWithin: { + $box: [ + [southWestLng, southWestLat], + [northEastLng, northEastLat] + ] + } + }, + createdAt: { $gte: start, $lt: end } + }, { + fields: { + lat: 1, + lon: 1, + scan: 1 + } + }); + // console.log(`Fires total: ${fires.count()}`); + return fires; }); diff --git a/imports/modules/server/other-checks.js b/imports/modules/server/other-checks.js new file mode 100644 index 0000000..85dcbbe --- /dev/null +++ b/imports/modules/server/other-checks.js @@ -0,0 +1,25 @@ +import { check, Match } from 'meteor/check'; + +export const validZoom = Match.Where((zoom) => { + // http://wiki.openstreetmap.org/wiki/Zoom_levels + check(zoom, Number); + return zoom >= 0 && zoom <= 19; +}); + +// https://github.com/3stack-software/meteor-match-library +export function NumberBetween(min, max) { + return Match.Where((x) => { + check(x, Number); + return min <= x && x <= max; + }); +} + +export function NullOr(type) { + return Match.Where((x) => { + if (x === null) { + return true; + } + check(x, type); + return true; + }); +} diff --git a/imports/ui/pages/FiresMap/FiresMap.js b/imports/ui/pages/FiresMap/FiresMap.js index 28dd155..22f83b4 100644 --- a/imports/ui/pages/FiresMap/FiresMap.js +++ b/imports/ui/pages/FiresMap/FiresMap.js @@ -34,8 +34,8 @@ import './FiresMap.scss'; const MAXZOOM = 6; const MAXZOOMREACTIVE = 6; const zoom = new ReactiveVar(8); -const center = new ReactiveVar([null, null]); -const mapSize = new ReactiveVar([400, 400]); +const center = new ReactiveVar([0, 0]); +const mapSize = new ReactiveVar(); // Remove map in subscription class FiresMap extends React.Component { @@ -59,9 +59,12 @@ class FiresMap extends React.Component { } componentDidMount() { - mapSize.set([this.divElement.clientHeight, this.divElement.clientWidth]); if (this.fireMap) { - this.addScale(); + if (this.getMap().getCenter()) { + const bounds = this.getMap().getBounds(); + mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]); + this.addScale(); + } } } @@ -69,9 +72,6 @@ class FiresMap extends React.Component { this.debounceView(viewport); } - onClickReset() { - } - getMap() { return this.fireMap.leafletElement; } @@ -82,6 +82,10 @@ class FiresMap extends React.Component { handleViewportChange(viewport) { console.log(`Viewport changed: ${JSON.stringify(viewport)}`); + const bounds = this.getMap().getBounds(); + // console.log(bounds); + mapSize.set([bounds.getNorthEast(), bounds.getSouthWest()]); + /* if (viewport.center === this.state.viewport.center && viewport.zoom === this.state.viewport.zoom) { // Do nothing, in same point @@ -89,7 +93,7 @@ class FiresMap extends React.Component { } zoom.set(viewport.zoom); center.set(viewport.center); - this.setState({ viewport }); + this.setState({ viewport }); */ } centerOnUserLocation(viewport) { @@ -124,7 +128,7 @@ class FiresMap extends React.Component { } render() { - console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length} of ${this.props.activefirestotal} total. Subs users ready ${this.props.subsready}, reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`); + console.log(`Rendering ${this.props.loading ? 'loading' : 'LOADED'} map ${this.props.activefires.length + this.props.firealerts.length} of ${this.props.activefirestotal} total. Subs users ready ${this.props.subsready}, reactive ${this.state.viewport.zoom >= MAXZOOMREACTIVE}`); return ( /* Large number of markers: @@ -141,9 +145,9 @@ class FiresMap extends React.Component {

- { this.props.activefires.length === 0 ? + { (this.props.activefires.length + this.props.firealerts.length) === 0 ? No hay fuegos activos en esta zona del mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo. Datos actualizados . : - En rojo, {{ count: this.props.activefires.length }} fuegos activos en el mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo por la NASA. Datos actualizados . + En rojo, {{ count: this.props.activefires.length + this.props.firealerts.length }} fuegos activos en el mapa. Hay un total de {{ countTotal: this.props.activefirestotal }} fuegos activos detectados en todo el mundo por la NASA. Datos actualizados . }

{isNotHomeAndMobile && @@ -178,6 +182,8 @@ class FiresMap extends React.Component { className="firesmap-leaflet-container" animate minZoom={5} + center={this.props.center} + zoom={this.props.zoom} preferCanvas onClick={this.onClickReset} viewport={this.state.viewport} @@ -237,47 +243,47 @@ FiresMap.propTypes = { t: PropTypes.func.isRequired }; +let init = true; + export default translate([], { wait: true })(withTracker(() => { let subscription; - let init = true; Meteor.autorun(() => { if (geolocation.get() && init) { center.set(geolocation.get()); - // console.log(`Geolocation ${geolocation.get()}`); + console.log(`Geolocation ${geolocation.get()}`); init = false; } - if (mapSize.get()) { + if (mapSize.get() && mapSize.get()[0].lng && mapSize.get()[1].lat) { subscription = Meteor.subscribe( 'activefiresmyloc', - zoom.get(), - center.get()[0], - center.get()[1], - mapSize.get()[0], - mapSize.get()[1] + mapSize.get()[0].lng, + mapSize.get()[0].lat, + mapSize.get()[1].lng, + mapSize.get()[1].lat + ); + Meteor.subscribe( + 'fireAlerts', + mapSize.get()[0].lng, + mapSize.get()[0].lat, + mapSize.get()[1].lng, + mapSize.get()[1].lat ); } }); Meteor.subscribe('activefirestotal'); - // Right now to all neighborhood alerts - Meteor.subscribe('fireAlerts'); Meteor.subscribe('settings'); const userSubs = Meteor.subscribe('userSubsToFires'); - // const subscription = Meteor.subscribe('activefiresmyloc', zoom.get()); - // Warning with the performance of this log: - // console.log(`Active fires ${ActiveFiresCollection.find().count()} of ${Counter.get('countActiveFires')}`); - // console.log(`Active neighborhood fires ${FireAlertsCollection.find().fetch().length} and users subscribed ${UserSubsToFiresCollection.find().fetch().length}`); - // console.log(UserSubsToFiresCollection.find().fetch()); const lastCheck = SiteSettings.findOne({ name: 'last-fire-check' }); + const fireAlerts = FireAlertsCollection.find().fetch(); return { - loading: !subscription.ready(), + loading: !subscription ? true : !subscription.ready(), userSubs: UserSubsToFiresCollection.find().fetch(), subsready: userSubs.ready(), // Not reactive query depending on zoom level activefires: ActiveFiresCollection.find({}, { reactive: zoom.get() >= MAXZOOMREACTIVE }).fetch(), - // activefires: ActiveFiresCollection.find({}).fetch(), - activefirestotal: Counter.get('countActiveFires'), - firealerts: FireAlertsCollection.find().fetch(), + activefirestotal: Counter.get('countActiveFires') + fireAlerts.length, + firealerts: fireAlerts, lastCheck: lastCheck ? lastCheck.value : null, center: geolocation.get(), zoom: zoom.get()