├── public
├── index.html
├── tracker.html
├── js
│ ├── tracker.js
│ └── viewer.js
└── viewer.html
├── README.md
├── package.json
├── .gitignore
├── index.js
└── LICENSE
/public/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # twitch-track-all-the-things
--------------------------------------------------------------------------------
/public/tracker.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Tracker
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "track-all-the-things",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "Eddie Zaneski",
11 | "license": "MIT",
12 | "dependencies": {
13 | "body-parser": "^1.15.2",
14 | "express": "^4.14.0",
15 | "socket.io": "^1.4.8"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/public/js/tracker.js:
--------------------------------------------------------------------------------
1 | document.addEventListener('DOMContentLoaded', () => {
2 | const socket = io('/')
3 |
4 | const positionOptions = {
5 | enableHighAccuracy: true,
6 | maximumAge: 0
7 | }
8 |
9 | setInterval(() => {
10 | navigator.geolocation.getCurrentPosition(pos => {
11 | const { latitude: lat, longitude: lng } = pos.coords
12 | socket.emit('updateLocation', { lat, lng })
13 | }, err => {
14 | console.error(err)
15 | }, positionOptions)
16 | }, 2000)
17 |
18 | })
19 |
--------------------------------------------------------------------------------
/public/viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
16 | Map Viewer
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const http = require('http')
4 | const path = require('path')
5 | const express = require('express')
6 | const bodyParser = require('body-parser')
7 | const socketIo = require('socket.io')
8 |
9 | const app = express()
10 | const server = http.createServer(app)
11 | const io = socketIo(server)
12 |
13 | const locationMap = new Map()
14 |
15 | app.use(express.static(path.join(__dirname, 'public')))
16 |
17 | app.get('/', (req, res) => {
18 | res.send('Hello!')
19 | })
20 |
21 | io.on('connection', socket => {
22 | socket.on('updateLocation', pos => {
23 | locationMap.set(socket.id, pos)
24 | })
25 |
26 | socket.on('requestLocations', () => {
27 | socket.emit('locationsUpdate', Array.from(locationMap))
28 | })
29 |
30 | socket.on('disconnect', () => {
31 | locationMap.delete(socket.id)
32 | })
33 | })
34 |
35 | server.listen(3000, err => {
36 | if (err) {
37 | throw err
38 | }
39 |
40 | console.log('server started on port 3000')
41 | })
42 |
--------------------------------------------------------------------------------
/public/js/viewer.js:
--------------------------------------------------------------------------------
1 | let map
2 | let markers = new Map()
3 |
4 | document.addEventListener('DOMContentLoaded', () => {
5 | const socket = io('/')
6 |
7 | socket.on('locationsUpdate', locations => {
8 | markers.forEach((marker, id) => {
9 | marker.setMap(null)
10 | markers.delete(id)
11 | })
12 |
13 | locations.forEach(([id, position]) => {
14 | if (position.lat && position.lng) {
15 | const marker = new google.maps.Marker({
16 | position,
17 | map
18 | })
19 | markers.set(id, marker)
20 | }
21 | })
22 | })
23 |
24 | setInterval(() => {
25 | socket.emit('requestLocations')
26 | }, 2000)
27 | })
28 |
29 | function initMap() {
30 | navigator.geolocation.getCurrentPosition(pos => {
31 | const { latitude: lat, longitude: lng } = pos.coords
32 | map = new google.maps.Map(document.getElementById('map'), {
33 | center: { lat, lng },
34 | zoom: 2
35 | })
36 | }, err => {
37 | console.error(err)
38 | })
39 | }
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Eddie Zaneski
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------