-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from baspete/2019updates
2019updates
- Loading branch information
Showing
107 changed files
with
1,618 additions
and
1,716 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Virtual Split-Flap Display | ||
|
||
![Screenshot](thumbnail.png) | ||
|
||
This is a simulation of a split-flap display (often called a Solari board) designed to run in a web browser. It dynamically loads JSON data from a data source and renders that data as characters and images on the board. Individual characters are animated using CSS sprites. | ||
|
||
The look and feel are fully configurable by changing the markup and using different sprite images, and the included files are simply examples intended to get you started with your own project. | ||
|
||
## Application Structure | ||
|
||
`/public/js` - The client-side code is in `split-flap.js`. This code loads jquery, underscore and backbone from dnjs.cloudflare.com. You may wish to change this if your application will run disconnected. | ||
|
||
`/public/img` - Image sprites. Customize these to change the look of the split flap elements or utilize different character sets or status indicators. I've included the .pxd file(s) so you can edit these in Pixelmator. | ||
|
||
`/public/css` - The base styles for this application. These can be extended or overridden by adding your own in `/public/plugins`. Note how the `.full`, `.character` and `.number` definitions here define different (sub)sets of images on the character sprites. If you edit the character sprites you must also edit these classes to match. | ||
|
||
`public/index.html` - Example HTML to render into the browser. This is where you define the layout of your board and define some basic constants. | ||
|
||
`/public/plugins` - Custom Javascript, CSS and images. Use these as a starting point to connect to new data sources, change the look and feel, etc. | ||
|
||
`/app.js` - A simple Node.js application to serve static files (HTML, Javascript, CSS and images) and to serve JSON data to populate the displays. If you already have a web/application server you might not need this file. | ||
|
||
## Installation | ||
|
||
``` | ||
git clone https://github.com/baspete/Split-Flap.git | ||
cd Split-Flap | ||
npm install | ||
node app.js | ||
``` | ||
|
||
Navigate to `http://locahost:8080` in your browser. | ||
|
||
## Customization | ||
|
||
The look and feel is customized by changing the markup, CSS and sprite images. Of course, any size changes you make to the images must be reflected in the sprite images and vice-versa. | ||
|
||
The display refresh interval and the data source url are set in the `<script>` block at the bottom of the HTML pages. Make sure this interval is set long enough so that the entire display has finished rendering before starting again. | ||
|
||
The row refresh cascade interval is set in the setTimeout() function in sf.chart.render(). Setting this too low results in a jerky animation as too many elements animate at once and slow your processor. | ||
|
||
The individual elements' animation speed is set in the fadeIn() and fadeOut() functions in sf.chart.splitFlap.show() | ||
|
||
## Data | ||
|
||
The example Node app at `app.js` exposes an API route at `/api/arrivals` which demonstrates sending data to `split-flap.js`. | ||
|
||
``` | ||
{ | ||
data: [ | ||
{ | ||
airline: "JBU", | ||
flight: 541, | ||
city: "Durban", | ||
gate: "A20", | ||
scheduled: "0233", | ||
status: "A" | ||
}, | ||
{ | ||
airline: "SWA", | ||
flight: 1367, | ||
city: "Roanoake", | ||
gate: "B13", | ||
scheduled: "1416", | ||
status: "B", | ||
remarks: "Delayed 13M" | ||
}, | ||
{ | ||
airline: "JBU", | ||
flight: 1685, | ||
city: "Charleston", | ||
gate: "A18", | ||
scheduled: "0042", | ||
status: "A" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
The files in `/public/plugins` are used to set the URL for the data and process the results. See `/public/plugins/adsb/custom.js` for an example. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* global require console process Promise module */ | ||
|
||
const express = require('express'), | ||
app = express(); | ||
|
||
function getRandomInt(max) { | ||
return Math.floor(Math.random() * Math.floor(max)); | ||
} | ||
|
||
function getTail() { | ||
let c = [ | ||
'a', | ||
'b', | ||
'c', | ||
'd', | ||
'e', | ||
'f', | ||
'g', | ||
'h', | ||
'i', | ||
'j', | ||
'k', | ||
'l', | ||
'm', | ||
'n', | ||
'o', | ||
'p', | ||
'q', | ||
'r', | ||
's', | ||
't', | ||
'u', | ||
'v', | ||
'w', | ||
'x', | ||
'y', | ||
'z' | ||
]; | ||
return `N${getRandomInt(9999)}${c[getRandomInt(c.length - 1)]}`; | ||
} | ||
|
||
function getAirline() { | ||
const airlines = [ | ||
'SWA', | ||
'AAL', | ||
'BAW', | ||
'DAL', | ||
'UAE', | ||
'KLM', | ||
'DLH', | ||
'ASA', | ||
'UAL', | ||
'FDX', | ||
'PXM', | ||
'SKW', | ||
'JBU', | ||
'ACA', | ||
'QXE', | ||
'NKS', | ||
'VIR', | ||
'LXJ', | ||
'QFA' | ||
]; | ||
return airlines[getRandomInt(airlines.length - 1)]; | ||
} | ||
|
||
function getTime() { | ||
return '01:23'; | ||
} | ||
|
||
function getFlight() { | ||
return getRandomInt(2000); | ||
} | ||
|
||
function getHeading() { | ||
return getRandomInt(359) | ||
.toString() | ||
.padStart(3, '0'); | ||
} | ||
|
||
function getGate() { | ||
const t = ['A', 'B', 'C'][getRandomInt(2)]; | ||
const g = getRandomInt(30); | ||
return `${t}${g}`; | ||
} | ||
|
||
function getCity() { | ||
const cities = [ | ||
'Atlanta', | ||
'Baltimore', | ||
'Charleston', | ||
'Durban', | ||
'Edinburgh', | ||
'Frankfurt', | ||
'Galveston', | ||
'Havana', | ||
'Iowa City', | ||
'Jakarta', | ||
'Karachi', | ||
'Los Angeles', | ||
'Mexico City', | ||
'Nairobi', | ||
'Ontario', | ||
'Pittsburgh', | ||
'Quebec City', | ||
'Roanoake', | ||
'San Diego', | ||
'Tallahassee' | ||
]; | ||
return cities[getRandomInt(20)]; | ||
} | ||
|
||
function getTime() { | ||
let hrs = getRandomInt(23) | ||
.toString() | ||
.padStart(2, '0'); | ||
let mins = getRandomInt(59) | ||
.toString() | ||
.padStart(2, '0'); | ||
return `${hrs}${mins}`; | ||
} | ||
|
||
// ======================================================================== | ||
// API | ||
|
||
app.use('/api/arrivals', (req, res) => { | ||
let r = { | ||
data: [] | ||
}; | ||
|
||
for (let i = 0; i < 18; i++) { | ||
// Create the data for a row. | ||
let data = { | ||
airline: getAirline(), | ||
flight: getFlight(), | ||
city: getCity(), | ||
gate: getGate(), | ||
scheduled: getTime() | ||
}; | ||
|
||
// Let's add an occasional delayed flight. | ||
data.status = getRandomInt(10) > 7 ? 'B' : 'A'; | ||
if (data.status === 'B') { | ||
data.remarks = `Delayed ${getRandomInt(50)}M`; | ||
} | ||
|
||
// Add the row the the response. | ||
r.data.push(data); | ||
} | ||
|
||
res.json(r); | ||
}); | ||
|
||
// ======================================================================== | ||
// STATIC FILES | ||
app.use('/', express.static('public')); | ||
|
||
// ======================================================================== | ||
// WEB SERVER | ||
const port = process.env.PORT || 8080; | ||
app.listen(port); | ||
console.log('split flap started on port ' + port); |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.