mirror of
https://github.com/asimonson1125/asimonson1125.github.io.git
synced 2026-02-25 05:09:49 -06:00
Update hotspots for legend
This commit is contained in:
@@ -8,8 +8,8 @@ body {
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map {
|
html, body, #map {
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,3 +23,17 @@ body {
|
|||||||
.leaflet-tile-pane {
|
.leaflet-tile-pane {
|
||||||
filter: brightness(50%);
|
filter: brightness(50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
border: solid #999999 3px;
|
||||||
|
color: #eee;
|
||||||
|
background-color: rgba(44, 44, 44, .8);
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#legendOccGrad {
|
||||||
|
background-image: linear-gradient(to right, transparent, red);
|
||||||
|
padding: 0 2em;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: black .2em .2em;
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
let map = L.map("map", {
|
let map = L.map("map", {
|
||||||
zoomControl: false,
|
zoomControl: false,
|
||||||
attributionControl: false,
|
attributionControl: false,
|
||||||
}).setView([43.084679, -77.674702], 17);
|
}).setView([43.084679, -77.674702], 17);
|
||||||
// L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
// L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
// maxZoom: 19,
|
// maxZoom: 19,
|
||||||
// attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
// attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
// }).addTo(map);
|
// }).addTo(map);
|
||||||
|
|
||||||
var CartoDB_DarkMatterNoLabels = L.tileLayer(
|
var CartoDB_DarkMatterNoLabels = L.tileLayer(
|
||||||
"https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png",
|
"https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png",
|
||||||
{
|
{
|
||||||
attribution:
|
attribution:
|
||||||
@@ -15,25 +15,25 @@ let map = L.map("map", {
|
|||||||
subdomains: "abcd",
|
subdomains: "abcd",
|
||||||
maxZoom: 20,
|
maxZoom: 20,
|
||||||
}
|
}
|
||||||
).addTo(map);
|
).addTo(map);
|
||||||
|
|
||||||
// var CartoDB_PositronNoLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png', {
|
// var CartoDB_PositronNoLabels = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png', {
|
||||||
// attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
// attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||||
// subdomains: 'abcd',
|
// subdomains: 'abcd',
|
||||||
// maxZoom: 20
|
// maxZoom: 20
|
||||||
// }).addTo(map); // good hacky filter: invert(100%) hue-rotate(180deg) brightness(100%) contrast(100%);
|
// }).addTo(map); // good hacky filter: invert(100%) hue-rotate(180deg) brightness(100%) contrast(100%);
|
||||||
|
|
||||||
// var CartoDB_Positron = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
|
// var CartoDB_Positron = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
|
||||||
// attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
// attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
|
||||||
// subdomains: 'abcd',
|
// subdomains: 'abcd',
|
||||||
// maxZoom: 20
|
// maxZoom: 20
|
||||||
// }).addTo(map);
|
// }).addTo(map);
|
||||||
|
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
function shuffle(array) {
|
function shuffle(array) {
|
||||||
let currentIndex = array.length,
|
let currentIndex = array.length,
|
||||||
randomIndex;
|
randomIndex;
|
||||||
|
|
||||||
@@ -51,48 +51,49 @@ let map = L.map("map", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setMarker(attrs, ref) {
|
function setMarker(attrs, ref) {
|
||||||
// let red = parseInt("ff", 16);
|
// let red = parseInt("ff", 16);
|
||||||
// let green = parseInt("78", 16);
|
// let green = parseInt("78", 16);
|
||||||
// let style = {"fillColor": `#${red.toString(16)}${green.toString(16)}00`};
|
// let style = {"fillColor": `#${red.toString(16)}${green.toString(16)}00`};
|
||||||
let ratio = attrs.properties.count / attrs.properties.capacity;
|
let ratio = attrs.properties.count / attrs.properties.capacity;
|
||||||
ratio = ratio > 1 ? 1 : ratio;
|
let adjustedratio = ratio > 1 ? 1 : ratio;
|
||||||
let red = 255 * ratio;
|
let red = 255 * adjustedratio;
|
||||||
let style = { fillColor: `rgba(${red}, 0, 0, ${ratio})` };
|
let style = { fillColor: `rgba(255, 0, 0, ${adjustedratio})` };
|
||||||
ref.setStyle(style);
|
ref.setStyle(style);
|
||||||
ref.bindPopup(
|
ref.bindPopup(
|
||||||
`${attrs.properties.name}<br />Current Occupation: ${attrs.properties.count}`
|
`${attrs.properties.name}<br />Current Occupation: ${attrs.properties.count}<br />${Math.round(ratio*100)}% capacity`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEachFeature(feature, layer) {
|
function onEachFeature(feature, layer) {
|
||||||
// does this feature have a property named popupContent?
|
// does this feature have a property named popupContent?
|
||||||
if (!feature.properties || !feature.properties.name) {
|
if (!feature.properties || !feature.properties.name) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setMarker(feature, layer);
|
setMarker(feature, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const polyStyle = {
|
const polyStyle = {
|
||||||
color: "#ff7800",
|
color: "#ff7800",
|
||||||
weight: 5,
|
weight: 5,
|
||||||
opacity: 0.65,
|
opacity: 0.65,
|
||||||
};
|
};
|
||||||
|
|
||||||
const geojsonMarkerOptions = {
|
const geojsonMarkerOptions = {
|
||||||
|
pane: "nodePane",
|
||||||
radius: 8,
|
radius: 8,
|
||||||
fillColor: "#ff7800",
|
fillColor: "#ff7800",
|
||||||
color: "#ff7800",
|
color: "#ff7800",
|
||||||
weight: 3,
|
weight: 3,
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
fillOpacity: 1,
|
fillOpacity: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
const pointStyle = {};
|
const pointStyle = {};
|
||||||
|
|
||||||
function ritCustomize(input) {
|
function ritCustomize(input) {
|
||||||
badOnes = [166]; // Nathan's (166) is a duplicate of Ben and Jerry's
|
badOnes = [166]; // Nathan's (166) is a duplicate of Ben and Jerry's
|
||||||
for (let i = input.length - 1; i >= 0; i--) {
|
for (let i = input.length - 1; i >= 0; i--) {
|
||||||
if (badOnes.indexOf(input[i].mdo_id) >= 0) {
|
if (badOnes.indexOf(input[i].mdo_id) >= 0) {
|
||||||
@@ -100,10 +101,10 @@ let map = L.map("map", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unused: "Campus", "Gleason_Engineering_Student_Area"
|
// Unused: "Campus", "Gleason_Engineering_Student_Area"
|
||||||
const no_mdo_ids = {
|
const no_mdo_ids = {
|
||||||
Library_A_Level: { type: "Point", coordinates: [-77.676355, 43.083974] },
|
Library_A_Level: { type: "Point", coordinates: [-77.676355, 43.083974] },
|
||||||
Library_1st_Floor: { type: "Point", coordinates: [-77.676355, 43.083874] },
|
Library_1st_Floor: { type: "Point", coordinates: [-77.676355, 43.083874] },
|
||||||
Library_2nd_Floor: { type: "Point", coordinates: [-77.676355, 43.083774] },
|
Library_2nd_Floor: { type: "Point", coordinates: [-77.676355, 43.083774] },
|
||||||
@@ -115,9 +116,9 @@ let map = L.map("map", {
|
|||||||
type: "Point",
|
type: "Point",
|
||||||
coordinates: [-77.681365, 43.085376],
|
coordinates: [-77.681365, 43.085376],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function ritCustomizeCoords(input) {
|
function ritCustomizeCoords(input) {
|
||||||
try {
|
try {
|
||||||
if (input.properties.name == "Beanz") {
|
if (input.properties.name == "Beanz") {
|
||||||
input.geometry.coordinates = [-77.66904, 43.083876];
|
input.geometry.coordinates = [-77.66904, 43.083876];
|
||||||
@@ -136,11 +137,15 @@ let map = L.map("map", {
|
|||||||
};
|
};
|
||||||
return geojsonObj;
|
return geojsonObj;
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pts;
|
let pts;
|
||||||
const densityMapUrl = "/hotspotsrit" // https://maps.rit.edu/proxySearch/densityMapDetail.php?mdo=1
|
let nodePane = map.createPane("nodePane");
|
||||||
async function init() {
|
nodePane.style.zIndex = "600";
|
||||||
|
let nodeGroup;
|
||||||
|
const densityMapUrl = "/hotspotsrit"; // https://maps.rit.edu/proxySearch/densityMapDetail.php?mdo=1
|
||||||
|
|
||||||
|
async function init(legend = false) {
|
||||||
let counts = fetch(densityMapUrl + "/cached");
|
let counts = fetch(densityMapUrl + "/cached");
|
||||||
|
|
||||||
let locations = fetch(
|
let locations = fetch(
|
||||||
@@ -156,7 +161,8 @@ let map = L.map("map", {
|
|||||||
for (let i = 0; i < counts.length; i++) {
|
for (let i = 0; i < counts.length; i++) {
|
||||||
if (counts[i].mdo_id == x.properties.mdo_id) {
|
if (counts[i].mdo_id == x.properties.mdo_id) {
|
||||||
x.properties.count = counts[i].count;
|
x.properties.count = counts[i].count;
|
||||||
x.properties.capacity = counts[i].max_occ == null ? 100 : counts[i].max_occ;
|
x.properties.capacity =
|
||||||
|
counts[i].max_occ == null ? 100 : counts[i].max_occ;
|
||||||
x = ritCustomizeCoords(x);
|
x = ritCustomizeCoords(x);
|
||||||
pts[x.properties.mdo_id] = x;
|
pts[x.properties.mdo_id] = x;
|
||||||
break;
|
break;
|
||||||
@@ -175,7 +181,8 @@ let map = L.map("map", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let ptsLayer = L.geoJSON(Object.values(pts), {
|
nodeGroup = L.geoJSON(Object.values(pts), {
|
||||||
|
pane: "nodePane",
|
||||||
pointToLayer: function (feature, latlng) {
|
pointToLayer: function (feature, latlng) {
|
||||||
return L.circleMarker(latlng, geojsonMarkerOptions);
|
return L.circleMarker(latlng, geojsonMarkerOptions);
|
||||||
},
|
},
|
||||||
@@ -188,24 +195,72 @@ let map = L.map("map", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onEachFeature: onEachFeature,
|
onEachFeature: onEachFeature,
|
||||||
}).addTo(map);
|
});
|
||||||
|
nodeGroup.addTo(map);
|
||||||
|
nodeGroup.bringToFront();
|
||||||
|
|
||||||
const features = ptsLayer.getLayers();
|
const features = nodeGroup.getLayers();
|
||||||
for (let i = 0; i < features.length; i++) {
|
for (let i = 0; i < features.length; i++) {
|
||||||
const key = features[i].feature.properties.mdo_id;
|
const key = features[i].feature.properties.mdo_id;
|
||||||
pts[key].properties.reference = features[i];
|
pts[key].properties.reference = features[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
legend ? makeLegend() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeLegend() {
|
||||||
|
let legend = L.control({ position: "bottomright" });
|
||||||
|
|
||||||
|
legend.onAdd = function (mapref) {
|
||||||
|
let div = L.DomUtil.create("div", "info legend");
|
||||||
|
div.innerHTML = "<div id='legendOccGrad'>Occupancy / Max Occupancy Gradient</div>"
|
||||||
|
div.innerHTML +=
|
||||||
|
`<p>Markers represent locations where data is collected<br />
|
||||||
|
Vectors represent the migration of aggregate occupation</br>
|
||||||
|
vectors to/from nodeless points involve locations not tracked by RIT</p>`;
|
||||||
|
|
||||||
|
return div;
|
||||||
|
};
|
||||||
|
|
||||||
|
let statControl = L.control({ position: "topright" });
|
||||||
|
|
||||||
|
statControl.onAdd = function (mapref) {
|
||||||
|
let div = L.DomUtil.create("div", "info legend");
|
||||||
|
div.innerHTML = "<p>Occupancy is updated every 5 minutes<br /><br /><span id='shotCounter'></span><br />Next update in <span id='countdownClock'></span> seconds</p>"
|
||||||
|
return div;
|
||||||
|
//
|
||||||
|
};
|
||||||
|
|
||||||
|
statControl.addTo(map);
|
||||||
|
legend.addTo(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateLegend(shotcount=undefined){
|
||||||
|
document.getElementById('shotCounter').textContent = `Previous update created ${shotcount} migration${shotcount == 1 ? "" : "s"}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const space_coords = [43.09224, -77.674799];
|
||||||
|
const UC_coords = [43.080361, -77.683296];
|
||||||
|
const perkins_coords = [43.08616, -77.661796];
|
||||||
|
function setSpace(features) {
|
||||||
|
features.forEach((x) => {
|
||||||
|
const centroid = getCoordArray(x);
|
||||||
|
if (centroid[1] > -77.673157) {
|
||||||
|
x.properties.space = perkins_coords;
|
||||||
|
} else if (centroid[1] < -77.677503 && centroid[0] < 43.08395) {
|
||||||
|
x.properties.space = UC_coords;
|
||||||
|
} else {
|
||||||
|
x.properties.space = space_coords;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// let laid = L.geoJson(pts).addTo(map)
|
let bullets = L.layerGroup([]);
|
||||||
// laid.remove()
|
async function shootVector(
|
||||||
|
|
||||||
let bullets = L.layerGroup([]);
|
|
||||||
async function shootVector(
|
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
{ speed = 500, color = null, onlyAnimate = true, trail = true } = {}
|
{ speed = 500, color = null, onlyAnimate = true, trail = true } = {}
|
||||||
) {
|
) {
|
||||||
options = {
|
options = {
|
||||||
onlyAnimate: onlyAnimate,
|
onlyAnimate: onlyAnimate,
|
||||||
animate: {
|
animate: {
|
||||||
@@ -223,9 +278,9 @@ let map = L.map("map", {
|
|||||||
options.fadeSpeed = 60000 * 15;
|
options.fadeSpeed = 60000 * 15;
|
||||||
arcGen(fromC, toC, (options = options));
|
arcGen(fromC, toC, (options = options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCoordArray(ref) {
|
function getCoordArray(ref) {
|
||||||
if (ref.properties == undefined) return ref;
|
if (ref.properties == undefined) return ref;
|
||||||
let coords;
|
let coords;
|
||||||
try {
|
try {
|
||||||
@@ -234,9 +289,9 @@ let map = L.map("map", {
|
|||||||
coords = ref.properties.reference.getBounds().getCenter();
|
coords = ref.properties.reference.getBounds().getCenter();
|
||||||
}
|
}
|
||||||
return [coords.lat, coords.lng];
|
return [coords.lat, coords.lng];
|
||||||
}
|
}
|
||||||
|
|
||||||
function arcGen(latlng1, latlng2, options = {}) {
|
function arcGen(latlng1, latlng2, options = {}) {
|
||||||
var latlngs = [];
|
var latlngs = [];
|
||||||
|
|
||||||
var offsetX = latlng2[1] - latlng1[1],
|
var offsetX = latlng2[1] - latlng1[1],
|
||||||
@@ -272,9 +327,9 @@ let map = L.map("map", {
|
|||||||
).addTo(map);
|
).addTo(map);
|
||||||
|
|
||||||
return curvedPath;
|
return curvedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcDistances(nodes) {
|
function calcDistances(nodes) {
|
||||||
nodes.forEach((x) => {
|
nodes.forEach((x) => {
|
||||||
x.properties.distances = {};
|
x.properties.distances = {};
|
||||||
const coords1 = getCoordArray(x);
|
const coords1 = getCoordArray(x);
|
||||||
@@ -286,11 +341,18 @@ let map = L.map("map", {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const space = [43.09224, -77.674799];
|
let countdownTo;
|
||||||
async function getUpdate() {
|
function updateCountdown() {
|
||||||
|
const now = new Date().getTime();
|
||||||
|
document.getElementById('countdownClock').textContent = Math.round((countdownTo - now) / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getUpdate() {
|
||||||
console.log("Updating Occupancy Matrix");
|
console.log("Updating Occupancy Matrix");
|
||||||
|
countdownTo = new Date().getTime() + 5 * 60 * 1000;
|
||||||
|
|
||||||
let counts = await fetch(densityMapUrl + "/current");
|
let counts = await fetch(densityMapUrl + "/current");
|
||||||
counts = await counts.json();
|
counts = await counts.json();
|
||||||
|
|
||||||
@@ -324,17 +386,18 @@ let map = L.map("map", {
|
|||||||
timeBetween / 1000
|
timeBetween / 1000
|
||||||
} second intervals`
|
} second intervals`
|
||||||
);
|
);
|
||||||
|
updateLegend(shots.length);
|
||||||
for (let i = 0; i < shots.length; i++) {
|
for (let i = 0; i < shots.length; i++) {
|
||||||
loadShot(shots[i], timeDelay[i], { trail: true });
|
loadShot(shots[i], timeDelay[i], { trail: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadShot(shot, delay, { trail = false } = {}) {
|
async function loadShot(shot, delay, { trail = false } = {}) {
|
||||||
await sleep(delay);
|
await sleep(delay);
|
||||||
shootVector(shot[0], shot[1], { trail: trail });
|
shootVector(shot[0], shot[1], { trail: trail });
|
||||||
}
|
}
|
||||||
|
|
||||||
function findOneShot(nodes, target) {
|
function findOneShot(nodes, target) {
|
||||||
let sortedByDistance = nodes.sort((a, b) => {
|
let sortedByDistance = nodes.sort((a, b) => {
|
||||||
return (
|
return (
|
||||||
target.properties.distances[a.properties.mdo_id] -
|
target.properties.distances[a.properties.mdo_id] -
|
||||||
@@ -347,9 +410,9 @@ let map = L.map("map", {
|
|||||||
return sortedByDistance[x];
|
return sortedByDistance[x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getShots(nodes) {
|
function getShots(nodes) {
|
||||||
let noChange = false;
|
let noChange = false;
|
||||||
let shots = [];
|
let shots = [];
|
||||||
let sourcesAndSinks = nodes.filter((x) => {
|
let sourcesAndSinks = nodes.filter((x) => {
|
||||||
@@ -405,26 +468,29 @@ let map = L.map("map", {
|
|||||||
// if no more people on campus, get them from space
|
// if no more people on campus, get them from space
|
||||||
sourcesAndSinks.forEach((x) => {
|
sourcesAndSinks.forEach((x) => {
|
||||||
while (x.properties.diff > 0) {
|
while (x.properties.diff > 0) {
|
||||||
shots.push([x, space]);
|
shots.push([x, x.properties.space]);
|
||||||
x.properties.diff--;
|
x.properties.diff--;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (x.properties.diff < 0) {
|
while (x.properties.diff < 0) {
|
||||||
shots.push([space, x]);
|
shots.push([x.properties.space, x]);
|
||||||
x.properties.diff++;
|
x.properties.diff++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return shots;
|
return shots;
|
||||||
}
|
}
|
||||||
|
|
||||||
init().then(() => {
|
const useLegend = window.location.pathname.replaceAll("/", "") == "hotspots"
|
||||||
|
init(useLegend).then(() => {
|
||||||
// map.on("click", () => {
|
// map.on("click", () => {
|
||||||
// shootVector(pts[2], pts[8]);
|
// shootVector(pts[2], pts[8]);
|
||||||
// });
|
// });
|
||||||
// shootVector(pts[0], pts[1], {speed: 500});
|
// shootVector(pts[0], pts[1], {speed: 500});
|
||||||
calcDistances(Object.values(pts));
|
let ptsarr = Object.values(pts);
|
||||||
getUpdate()
|
calcDistances(ptsarr);
|
||||||
|
setSpace(ptsarr);
|
||||||
|
getUpdate();
|
||||||
|
setInterval(updateCountdown, 1000);
|
||||||
setInterval(getUpdate, 60000 * 5);
|
setInterval(getUpdate, 60000 * 5);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,33 @@
|
|||||||
{
|
{
|
||||||
"Lower 48 Alt. Energy Map": {
|
"RIT Hotspots": {
|
||||||
|
"status": "WIP",
|
||||||
|
"classes": "pinned geospacial programming",
|
||||||
|
"bgi": "hotspotsrit.png",
|
||||||
|
"content": "Live crowd migration map using RIT occupancy data",
|
||||||
|
"links": [
|
||||||
|
[
|
||||||
|
"github", "https://github.com/asimonson1125/hotspotsrit", "git repo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"globe", "https://asimonson.com/hotspots", "demo"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LogicFlow": {
|
||||||
|
"status": "incomplete",
|
||||||
|
"classes": "programming",
|
||||||
|
"bgi": "logicflow.jpg",
|
||||||
|
"content": "Translate paragraphs to logical flowcharts, powered by ChatGPT Winner of CSHacks' Best Use of AI by Paychex",
|
||||||
|
"links": [
|
||||||
|
[
|
||||||
|
"github", "https://github.com/asimonson1125/LogicFlow", "git repo"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"globe", "https://devpost.com/software/logicflow", "Hackathon listing"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Alternative Energy Map": {
|
||||||
"status": "complete",
|
"status": "complete",
|
||||||
"classes": "pinned geospacial",
|
"classes": "pinned geospacial",
|
||||||
"bgi": "geovisF.png",
|
"bgi": "geovisF.png",
|
||||||
@@ -14,7 +42,7 @@
|
|||||||
},
|
},
|
||||||
"OccupyRIT": {
|
"OccupyRIT": {
|
||||||
"status": "WIP",
|
"status": "WIP",
|
||||||
"classes": "pinned programming",
|
"classes": "programming",
|
||||||
"bgi": "occupyRIT.png",
|
"bgi": "occupyRIT.png",
|
||||||
"content": "Collects RIT Gym Occupancy data, determining busiest workout times",
|
"content": "Collects RIT Gym Occupancy data, determining busiest workout times",
|
||||||
"links": [
|
"links": [
|
||||||
|
|||||||
BIN
src/static/photos/hotspotsrit.png
Normal file
BIN
src/static/photos/hotspotsrit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 350 KiB |
BIN
src/static/photos/logicflow.jpg
Normal file
BIN
src/static/photos/logicflow.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Reference in New Issue
Block a user