update - full refactor

This commit is contained in:
ZanzyTHEbar 2022-05-04 17:23:27 +02:00
parent c08619e9ca
commit 861e1e994d
26 changed files with 2157 additions and 374 deletions

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"cSpell.words": [
"loucass",
"pcvr",
"photobiological"
]
}

View File

@ -1,32 +1,51 @@
[![GitHub issues](https://img.shields.io/github/issues/RedHawk989/EyeTrackVR?style=plastic)](https://github.com/RedHawk989/EyeTrackVR/issues) [![GitHub forks](https://img.shields.io/github/forks/RedHawk989/EyeTrackVR?style=plastic)](https://github.com/RedHawk989/EyeTrackVR/network) [![GitHub stars](https://img.shields.io/github/stars/RedHawk989/EyeTrackVR?style=plastic)](https://github.com/RedHawk989/EyeTrackVR/stargazers)
- [EyeTrackVR](#eyetrackvr)
- [This project is in development and is not fully finished](#this-project-is-in-development-and-is-not-fully-finished)
- [Hardware](#hardware)
- [About IR Emitter Safety](#about-ir-emitter-safety)
- [Make sure you are using NON-focused emmiters and at around 5ma total power](#make-sure-you-are-using-non-focused-emmiters-and-at-around-5ma-total-power)
- [Firmware](#firmware)
- [Headset support](#headset-support)
- [Contact](#contact)
- [Licenses](#licenses)
# EyeTrackVR
Open source and affordable VR eye tracker platform for VR Chat via OSC
#### This project is in development and is not fully finished.
Open source and *affordable* VR eye tracker platform for [VRChat](https://hello.vrchat.com/) via `OSC` and `UDP` protocol.
#### This project is in development and is not fully finished
## Hardware
3d files for mounting brackets will be found here https://github.com/RedHawk989/EyeTrackVR-Hardware
IR emmitter files will also be located there.
Hardware will hopefully be a esp cam 32 with a 160fov ir camera this is not confirmed and very likely could change
3d files for mounting brackets will be found [here](https://github.com/RedHawk989/EyeTrackVR-Hardware)
IR emitter files will also be located there.
## ABOUT IR EMMITTER SAFETY
Please exercise extreme caution when messing around with IR emmitters.
Once safety testing has been compleated links and files will be provided for the emmitters. Please do not try to make, or use any emmitters unless you know exactly what you are doing as it could be very harmful for your eyes if not done correctly.
When files and reasorces are released DO NOT BYPASS OR NOT DO ANY SAFTY FEATURES PUT IN PLACE. This can result in a very harmful outcome.
The saftey measures were put in place to REDUCE the potential falure risk. All further safety responsibilities is on the user.
Hardware will hopefully be a `ESP32-Cam` with a `160fov ir camera`. ***This is not confirmed and very likely could change***.
## About IR Emitter Safety
Please *exercise extreme caution* when messing around with IR emitters.
<u style="color:#ff0e01;">Once safety testing has been completed links and files will be provided for the emitters</u>. Please do not try to make, or use any emitters unless you know exactly what you are doing as it could be very harmful for your eyes if not done correctly.
When files and resources are released <u style="color:#ff0e01;">**DO NOT BYPASS (OR NOT DO) ANY SAFETY FEATURES PUT IN PLACE**</u>. This can result in irreversible bodily harm.
The safety measures were put in place to REDUCE the potential failure risk. All further safety responsibilities is on the user.
This includes visually checking with an IR camera that the brightness is correct.
**Make sure you are using NON-focused emmiters and at around 5ma total power**
##### Make sure you are using NON-focused emmiters and at around 5ma total power
https://www.ncbi.nlm.nih.gov/labs/pmc/articles/PMC3116568/
[Effect of infrared radiation on the lens](./docs/Reference_Docs/saftey/effect_of_ir_on_the_lens.pdf)
https://www.osha.gov/sites/default/files/training-library_nir_stds_20021011.ppt
[Training-library Nir Stds](./docs/Reference_Docs/saftey/training-library_nir_stds_20021011.ppt)
https://dammedia.osram.info/media/bin/osram-dam-2496608/AN002_Details%20on%20photobiological%20safety%20of%20LED%20light%20sources.pdf
[AN002_Details on photobiological safety of LED light sources](./docs/Reference_Docs/saftey/AN002_Details_on_photobiological_safety_of_LED_light_sources.pdf)
## Firmware
Current testing has been with loucass003's firmware found here https://github.com/Futurabeast/futura-face-cam
There has been work for a different firmware by a community member but that has not been tested by me here https://github.com/lorow/OpenIris
Current testing has been with `loucass003's` firmware found [here](https://github.com/Futurabeast/futura-face-cam).
There has been work for a different firmware by a community member but that ***has not been tested by me*** [here](https://github.com/lorow/OpenIris).
## Headset support
Initial support will be Quest 2 (pcvr)
Support for other headsets from the community.
@ -34,7 +53,17 @@ Support for other headsets from the community.
Please join our discord for updates and any questions.
https://discord.gg/kkXYbVykZX
[![Discord](https://img.shields.io/badge/Discord-7289DA?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/kkXYbVykZX)
# Licenses
[![GitHub license](https://img.shields.io/github/license/RedHawk989/EyeTrackVR?style=plastic)](https://github.com/RedHawk989/EyeTrackVR/blob/master/LICENSE)
***All software is under the MIT license.
All documentation, including the Wiki, is under the Creative Commons CC-BY-SA-4.0 license***.
<!-- <div align="center">
<img src="./docs/assets/images/licenses/licenses.svg" width="300" alt="Open Licenses" />
</div> -->
[Top](#eyetrackvr)

94
docs/README.md Normal file
View File

@ -0,0 +1,94 @@
---
layout: default
title: Summary
nav_order: 1
has_children: false
---
# Summary
Welcome to the documentation for the Cyan Decarbonizer version 1, a DIY small-scale open hardware direct air carbon capture (DACC) system.
| ![Build Status](./assets/images/assemblyinst/cyan_side_view.png) |
|:--:|
| *The outer box and fan are optional for experimentation. The humidification chamber and air pump are the minimum required items.* |
## Purpose
This portable system operates at a small enough scale to empower individuals to tangibly experience carbon removal. It is also designed to get people actively thinking and sharing their carbon footprint and their role in the carbon cycle.
You can take a 5-minute tour of a Cyan system and learn more about the details of the project here:
<div align="center">
<a href="https://www.youtube.com/watch?v=yOzDFJZBM_w&t=2s"><img src="./assets/images/assemblyinst/cyan_blk_bg.png" width="400" alt="Cyan version 1" /></a>
</div>
If you have twenty-something minutes, details about the device design, current challenges, opportunities and big questions, and the Cyan mission's general goals and aspirations are available here:
<div align="center">
<a href="https://www.youtube.com/watch?v=98940CgZHI0" target="_blank"><img src="./assets/images/vtEUvj4.jpeg" width="400" alt="TSM: Hello, Cyan! - with Dahl Winters" /></a>
</div>
# Vision
Cyan is named in honor of `cyanobacteria`. As cyanobacteria did with oxygen, the vision was that many of these small-scale DACC units might come to have a significant impact on atmospheric CO2 and thus climate change. If not directly due to their small size, then indirectly through the promotion of DACC as a technology and through the educational experience of using Cyan.
The educational experience might be the biggest way that Cyan units will combat climate change. One can quickly see what CO2 emissions look like in trapped form, how much it weighs, and how long it takes to capture it. DACC starts to become a conversation point among friends and family. People start wanting to run Cyans to erase the emissions from their light bulbs, for example. And if they can neutralize those emissions, whats next? Household emissions? Should I buy a bigger DACC unit to cover my homes emissions? And so on.
# The Documentation, Q&A, Wiki, and Project Updates
The [Cyan Assembly Instructions](./Reference_Docs/assembly/Cyan_Assembly_Instructions.pdf) will get you started with an overview of how it works, a parts list, and instructions for putting it together. All this information is also found on our [Wiki](https://github.com/openair-collective/openair-cyan/wiki).
We now have a [Cyan Q&A](./Reference_Docs/extras/Cyan_Q_and_A.md) that goes over some common general and technical questions.
The [Supporting System Calculations](./Reference_Docs/data/Cyan%20-%20Supporting%20System%20Calculations.xlsx) describe the logic that went into designing the system, from a LCA/TEA perspective.
The [CO2 Capture Measurements](./Reference_Docs/data/Cyan%20-%20CO2%20Capture%20Measurements.xlsx) describe results obtained so far on how well this system can perform.
To report your `modifications`, `experimental results`, and `feedback` for making Cyan better, please visit the [Cyan DataShare](https://sites.google.com/view/cyan-datashare/) site.
To see an overview of where we are with current progress, please view the [Projects board](https://github.com/openair-collective/openair-cyan/projects/1).
Lastly, to view Cyan Project Progress updates on the OpenAir Forum, those are [available here](https://www.openairforum.org/t/cyan-project-progress/105/14).
# Carbon Capture Details
<div align="center">
<img src="./assets/images/assemblyinst/Cyan_Process.jpg" width="600" alt="Diagram of Cyan's Carbon Removal Process" />
</div>
## Inputs and Outputs
The input material, `calcium hydroxide`, can be found in any home improvement store as **`hydrated lime`**. However, for Cyan to be *carbon-negative* the input must either be sourced from a low-carbon supplier or obtained from waste cement.
The output material, `calcium carbonate` can be used in building materials (cement-lime) or as **`agricultural lime`**.
***`Magnesium hydroxide`*** is also an option for use as the input material. Though perhaps *more expensive* depending on the source, it is less alkaline than calcium hydroxide and has performed as well to slightly better than calcium hydroxide in carbon capture effectiveness in our Cyan tests. It can also be used to make tiles or blocks when mixed with cement and optionally biochar. We hope to have a low-carbon supplier later this year.
## Emissions Reduction
At present, a Cyan will remove over the course of `24 hours` the *same amount of CO2* emitted by running a 9-watt LED bulb for 3 hours. That is `2 grams of CO2 for 10 grams of input material` - or a 0.2:1 ratio.
*It is within theoretical possibility for this unit to remove the emissions of 20 9-watt LED bulbs for 3 hours (a whole house at night), that is 0.382 kg of CO2 that would need to be captured. Adequate surface area needs to be provided within the unit to do this and we are presently working on that*.
## Achieving Negative Emissions
The calcium hydroxide needs to be exposed to high humidity from between `3 to 16 hours` to achieve a good level of carbonation. Keeping the electricity consumption low will ensure Cyan removes more CO2 than it emits through electricity use.
`Cyan uses 1.5 watts of electricity` to power the air pump which bubbles air through water and humidifies the calcium hydroxide, allowing CO2 to be absorbed. However, the air pump *does not* need to be run continuously to maintain adequate humidification. A duty cycle of, say, ***10 minutes on & 50 minutes off*** is possible and suggested for negative emissions (more CO2 removed than consumed by the air pump).
The fan uses `3 watts` but only needs to be run intermittently to refresh the air inside the box. The fan is also useful to speed up dry time but this is *not essential for operation*. If you're going for negative emissions, air drying would really help unless you are using renewable energy to power your unit.
# Licenses
[![GitHub license](https://img.shields.io/github/license/openair-collective/openair-cyan?style=plastic)](https://github.com/openair-collective/openair-cyan/blob/master/LICENSE)
***All hardware materials and designs provided here are licensed under the [CERN-OHL-P](https://opensource.org/CERN-OHL-P) hardware license.
All software is under the GNU General Public License v3.0 (GPL-3.0).
All documentation, including the Wiki, is under the Creative Commons CC-BY-SA-4.0 license***.
<div align="center">
<img src="./assets/images/licenses/licenses.svg" width="300" alt="Open Licenses" />
</div>
[Top](#summary)

38
docs/_config.yml Normal file
View File

@ -0,0 +1,38 @@
title: 'Open Air Cyan Documentation'
remote_theme: just-the-docs/just-the-docs
color_scheme: 'light'
search_enabled: true
logo: './assets/images/openair-logo.png'
heading_level: 6
previews: 3
preview_words_before: 5
preview_words_after: 10
tokenizer_separator: /[\s/]+/
rel_url: true
button: true
aux_links:
'Documentation':
- '//github.com/openair-collective/openair-cyan/tree/main/docs/Reference_Docs'
'Code':
- '//github.com/openair-collective/openair-cyan/tree/dev/Code'
aux_links_new_tab: false
heading_anchors: true
gh_edit_link: true # show or hide edit this page link
gh_edit_link_text: 'Edit this page on GitHub.'
gh_edit_repository: 'https://github.com/openair-collective/openair-cyan/' # the github URL for your repo
gh_edit_branch: 'docs' # the branch that your docs is served from
gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: 'edit' # "tree" or "edit" if you want the user to jump into the editor immediately
ga_tracking: UA-5555555-55 # Google Analytics tracking code - Dahl Winters please update this to your own code
ga_tracking_anonymize_ip: true # Use GDPR compliant Google Analytics settings (true by default)
# Google Forms configuration
# comment-post: https://docs.google.com/forms/d/e/1FAIpQLScuqqkKDIUbPJpGfyLQJQe3mBNvQh45-eryzMWbqm7k7ALjGA
# comment-read: https://docs.google.com/spreadsheets/d/1szz__qSlPZ5LmDlR9ovNqdSCOgoUAYCWg-gWwkCQlmw/
# comment-post-fields: [entry.1141065141, entry.484163683, entry.231340692]
google_forms_comments:
google_app_script: https://script.google.com/macros/s/AKfycbwnErJEKIMcwQ5tlNS9rZ1KxHkhkJGkR9BNvKfkaz4X7MrZzc42VKN4ehzQ9AhfGChJ/exec
recaptcha_site_key: 6LfKJsMfAAAAAFLjDTY0PG9RdcpLBuiuoFNyQLsh
chunked_comment_loading: true
lazy_load_comments: true
comment_replies_enabled: true

View File

@ -0,0 +1,968 @@
{%- comment -%}
This section is to determine whether or not chunked comment loading is enabled.
By default this is turned ON. If the page has enabled or disabled this feature explicitly,
the individual page value is used. Otherwise the site's value, if any, is used.
{%- endcomment -%}
{%- assign chunked_loading_enabled = true -%}
{%- if page.chunked_comment_loading == false -%}
{%- assign chunked_loading_enabled = false -%}
{%- else -%}
{%- if site.google_forms_comments.chunked_comment_loading == false and page.chunked_comment_loading != true -%}
{%- assign chunked_loading_enabled = false -%}
{%- endif -%}
{%- endif -%}
{%- comment -%}
This section is to determine whether or not lazy loading of the comments is enabled.
By default this is turned OFF. If the page has enabled or disabled this feature explicitly,
the individual page value is used. Otherwise the site's value, if any, is used.
{%- endcomment -%}
{%- assign lazy_load_enabled = false -%}
{%- if page.lazy_load_comments == true -%}
{%- assign lazy_load_enabled = true -%}
{%- elsif site.google_forms_comments.lazy_load_comments == true -%}
{%- unless page.lazy_load_comments == false -%}
{%- assign lazy_load_enabled = true -%}
{%- endunless -%}
{%- endif -%}
{%- comment -%}
This section is to determine whether or recaptcha is enabled.
{%- endcomment -%}
{%- assign recaptcha_enabled = false -%}
{%- if site.google_forms_comments.recaptcha_site_key -%}
{%- assign recaptcha_enabled = true -%}
{%- endif -%}
{%- comment -%}
This section is to determine whether or comment replies are enabled.
{%- endcomment -%}
{%- assign comment_replies_enabled = false -%}
{%- if site.google_forms_comments.comment_replies_enabled == true -%}
{%- assign comment_replies_enabled = true -%}
{%- endif -%}
{%- if site.comment-read or site.google_forms_comments.google_app_script -%}
<script>
{%- comment -%}
Helper functions used so that we can forego using jQuery
functions. When appscripts is enabled, this allows us to
get rid of the jQuery dependency (for comments) altogether.
{%- endcomment -%}
function setText(elementId, textContent) {
document.getElementById(elementId).textContent = textContent;
};
function show(elementId) {
document.getElementById(elementId).style.display = 'inline';
};
function hide(elementId) {
document.getElementById(elementId).style.display = 'none';
};
function getValue(elementId) {
return document.getElementById(elementId).value;
};
function setValue(elementId, value) {
return document.getElementById(elementId).value = value;
};
function fadeIn(element) {
var duration = 400;
element.style.opacity = 0;
let opacity = 0;
const timer = setInterval(function() {
opacity += 50 / duration;
if (opacity >= 1) {
clearInterval(timer);
opacity = 1;
}
element.style.opacity = opacity;
}, 50);
};
function disableButtonWithLoader(elementId) {
var buttonToDisable = document.getElementById(elementId);
if (buttonToDisable == null) {
return;
}
buttonToDisable.disabled = true;
setText(elementId, "\xa0");
}
function disablePostCommentButton() {
disableButtonWithLoader("comment-submit");
};
function enablePostCommentButton() {
var postCommentButton = document.getElementById("comment-submit");
postCommentButton.disabled = false;
setText("comment-submit", "Post");
};
{%- comment -%}
/* Load Required 3rd-Party Scripts. We use the following:
- jquery for DOM manipulation
- jquery-csv for parsing Google Sheets CSV data to JSON
- validator for escaping user-entered comments to prevent malicious code input in comments
Make sure to update these to the latest versions every once in a while. */
{%- endcomment -%}
{%- comment -%}
/* Initial load of the comments section contnet. This ensures that we are only loading
JQuery and other scripts once we actually need them */
{%- endcomment -%}
async function initialCommentLoad() {
disableButtonWithLoader("load-comment-button");
{%- unless site.google_forms_comments.google_app_script -%}
{%- comment -%}
/* Load JQuery */
{%- endcomment -%}
var loadJquery = document.createElement("script");
loadJquery.type = "text/javascript";
loadJquery.src = "https://code.jquery.com/jquery-3.6.0.min.js";
document.head.appendChild(loadJquery);
{%- endunless -%}
{%- if recaptcha_enabled -%}
{%- comment -%}
/* Load Recaptcha */
{%- endcomment -%}
var loadRecaptcha = document.createElement("script");
loadRecaptcha.src = "https://www.google.com/recaptcha/api.js?render={{ site.google_forms_comments.recaptcha_site_key }}";
document.head.appendChild(loadRecaptcha);
{%- endif -%}
{%- comment -%}
/* Load Validator (to ensure we don't run code from comments for example) */
{%- endcomment -%}
var loadValidator = document.createElement("script");
loadValidator.src = "https://cdnjs.cloudflare.com/ajax/libs/validator/13.5.2/validator.min.js";
document.head.appendChild(loadValidator);
{%- comment -%}
/* Await Scripts Loaded */
{%- endcomment -%}
{%- if recaptcha_enabled -%}
await loadRecaptcha.onload;
{%- endif -%}
await loadValidator.onload;
{%- if site.google_forms_comments.google_app_script -%}
reloadComments();
{%- else -%}
loadJquery.onload = function() {
{%- comment -%}
/* We need to ensure that jQuery is ready before we can load JQuery CSV (used for .csv parsing) */
{%- endcomment -%}
async function checkJQuery() {
if (typeof jQuery === "undefined") {
return false;
} else {
clearTimeout(interval);
{%- comment -%}
/* Load JQuery CSV (need regular JQuery first) */
{%- endcomment -%}
var loadJqueryCsv = document.createElement("script");
loadJqueryCsv.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-csv/1.0.11/jquery.csv.min.js";
document.head.appendChild(loadJqueryCsv);
{%- comment -%}
/* Wait for JQuery CSV to finish loading */
{%- endcomment -%}
await loadJqueryCsv.onload;
{%- comment -%}
/* Now, load the comments */
{%- endcomment -%}
reloadComments();
}
};
{%- comment -%}
/* check if JQuery is ready every 250 MS
this timer will be cleared after the check passes */
{%- endcomment -%}
var interval = setInterval(checkJQuery, 250);
};
{%- endif -%}
};
var thisPageUrl = "{{ page.url }}";
const EXTRA_INFO_START = "chunkedCommentInfoStart";
const EXTRA_INFO_END = "chunkedCommentInfoEnd";
{%- comment -%}
/* Visbile comments are those already dislayed to the user.
Hidden comments are those that are already retrieved from Google Sheets but not shown yet (i.e. with a load more button visible).
Net new comments are those that have been added since the comment submit button was pressed. Usually this will be the single added
comment. */
{%- endcomment -%}
var visibleComments = [];
var hiddenComments = [];
var netNewComments = [];
{%- if comment_replies_enabled -%}
var commentIds = new Set();
{%- endif -%}
{%- comment -%}
/* Format the comment's date to our desired format */
{%- endcomment -%}
function formatDate(stringDate) {
var date = new Date(stringDate);
var dateOptions = { year: 'numeric', month: 'long', day: 'numeric'};
var timeOptions = { hour: 'numeric', minute: 'numeric' };
return `${date.toLocaleDateString("en-us", dateOptions)} at ${date.toLocaleTimeString("en-us", timeOptions)}`;
};
{%- comment -%}
/* Called when the comments have been loaded or relaoded.
Comments that we have already displayed on the page will be ignored */
{%- endcomment -%}
async function displayComments(comments) {
show("comments-and-input");
hide("load-comments");
var hasVisibleComments = visibleComments.length > 0;
{%- comment -%}
/* if we have no comments, show the 'no comments available' section */
{%- endcomment -%}
if (comments == null || comments === "" || comments == []) {
if (!hasVisibleComments) {
show("no-comments");
hide("load-more-comments");
hide("num-comments-displayed");
}
return;
}
{%- if comment_replies_enabled -%}
commentIds = new Set();
{%- endif -%}
{%- if site.google_forms_comments.google_app_script -%}
var newHiddenComments = comments
{%- if comment_replies_enabled -%}
.map(item => {
commentIds.add(Date.parse(item.timestamp)?.toString());
return item;
})
{%- endif -%}
.sort((a, b) => (new Date(a.timestamp).getTime() || 0) - (new Date(b.timestamp).getTime() || 0))
.map(item => JSON.stringify(item));
{%- else -%}
{%- comment -%}
/* Add headers so json objects are named properly */
{%- endcomment -%}
comments = `timestamp,name,comment,isAuthor\n${comments}`;
var newHiddenComments = $.csv.toObjects(comments)
{%- if comment_replies_enabled -%}
.map(item => {
commentIds.add(Date.parse(item.timestamp)?.toString());
return item;
})
{%- endif -%}
.sort((a, b) => (new Date(a.timestamp).getTime() || 0) - (new Date(b.timestamp).getTime() || 0))
.map(item => JSON.stringify(item));
{%- endif -%}
if (hasVisibleComments) {
netNewComments = newHiddenComments
.filter(item => !visibleComments.includes(item))
.filter(item => !hiddenComments.includes(item));
}
hiddenComments = newHiddenComments
.filter(item => !visibleComments.includes(item))
.filter(item => !netNewComments.includes(item));
loadMoreComments(false || !hasVisibleComments);
};
{%- comment -%}
/* Loads more comments if there are any left to display from those already loaded from the server */
{%- endcomment -%}
function loadMoreComments(isLoadMoreAction) {
{%- if chunked_loading_enabled -%}
var newCommentsToDisplay = hiddenComments.slice(-5);
{%- else -%}
var newCommentsToDisplay = hiddenComments;
{%- endif -%}
if (isLoadMoreAction) {
{%- comment -%}
/* iterate over each comment that came from Google Sheets */
{%- endcomment -%}
newCommentsToDisplay.reverse().forEach(element => displaySingleComment(element, true));
hiddenComments = hiddenComments.filter(item => !newCommentsToDisplay.includes(item) && !visibleComments.includes(item));
} else {
{%- comment -%}
/* add the new comments if there are any */
{%- endcomment -%}
netNewComments.forEach(element => displaySingleComment(element, false));
netNewComments = []
}
setText("num-comments-displayed", `Showing ${visibleComments.length} of ${visibleComments.length + hiddenComments.length} comments`);
if (hiddenComments.length == 0) {
hide("load-more-comments");
} else {
show("load-more-comments");
}
};
{%- if comment_replies_enabled -%}
var currentFadeItem = null;
function fadeColor(element) {
if (currentFadeItem != null) {
clearInterval(currentFadeItem);
currentFadeItem = null;
}
var duration = 1000;
var step = 25;
let opacity = 1;
const timer = setInterval(function() {
opacity -= (1 / (duration / step));
if (opacity <= 0) {
clearInterval(timer);
currentFadeItem = null;
opacity = 0;
}
element.style.background = "rgba(3, 155, 229, "+ opacity +")";
}, step);
currentFadeItem = timer;
};
function smoothScrollTo(element) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
};
function jumpToComment(commentId) {
var element = document.getElementsByClassName("" + commentId)[0];
while(element == null && hiddenComments.length > 0) {
loadMoreComments(true);
element = document.getElementsByClassName("" + commentId)[0];
}
if (element != null) {
smoothScrollTo(element);
fadeColor(element);
}
};
function clearCommentReplyItem() {
document.getElementById("comment-reply-info").innerHTML = ``;
};
function replyToComment(commentId) {
document.getElementById("comment-reply-info").innerHTML = `<small class="comment-reply-clear" onclick="clearCommentReplyItem()">&nbsp;&nbsp;&nbsp;</small><small onClick="jumpToComment('${commentId}')">Replying to comment <a id="reply-to-comment-id">${commentId}</a></small>`;
smoothScrollTo(document.getElementsByClassName("comments-form")[0]);
};
{%- endif -%}
function getCommentInfo(comment) {
var extraCommentInfo = comment?.match(EXTRA_INFO_START + ".+" + EXTRA_INFO_END);
return {
text : comment?.replace(extraCommentInfo, ""),
extraCommentInfo : JSON.parse(extraCommentInfo?.toString()?.replace(EXTRA_INFO_START, "")?.replace(EXTRA_INFO_END, "") ?? "{}")
};
};
function displaySingleComment(element, isPrepend) {
{%- comment -%}
/* don't re-add existing comments */
{%- endcomment -%}
if (visibleComments.includes(element)) {
return;
}
var jsonElement = JSON.parse(element);
var comment = getCommentInfo(jsonElement.comment);
{%- comment -%}
/* If the author was the one who commented back, add this 'verified' logic */
{%- endcomment -%}
var verifiedAuthorTag = "";
if (jsonElement.isAuthor == true || jsonElement.isAuthor === "TRUE") {
verifiedAuthorTag = "&nbsp;<strong>(Author)</strong>";
}
{%- comment -%}
/* Create the new item using HTML and append it to the user-visible comment section */
{%- endcomment -%}
var newItem = document.createElement("div");
newItem.classList.add("comment-item");
{%- if comment_replies_enabled -%}
newItem.classList.add("reply-item");
var commentReplyId = "" + Date.parse(jsonElement.timestamp);
newItem.classList.add(commentReplyId);
var replyToHtml = null;
var replyId = comment?.extraCommentInfo?.replyToCommentId;
if (replyId != null && replyId != "" && commentIds.has(replyId)) {
replyToHtml = `<p class="comment-reply-id" onclick="jumpToComment('${replyId}')"><<< ${replyId}</p>`;
}
var currentCommentReplyButton = `<span class="comment-reply-button" onclick="replyToComment(${commentReplyId})"><img />Reply</span>`;
{%- endif -%}
newItem.innerHTML = `
<p class="commenter-name">${validator.escape(jsonElement.name.toString())}${verifiedAuthorTag}
<small>${formatDate(jsonElement.timestamp)}
{%- if comment_replies_enabled -%}
${currentCommentReplyButton ?? ""}
{%- endif -%}
</small>
</p>
<div>
{%- if comment_replies_enabled -%}
${replyToHtml ?? ""}
{%- endif -%}
<p>${validator.escape(comment?.text?.toString()).replace(new RegExp('\r?\n','g'), '<br />')}</p>
</div>
`.trim();
if (isPrepend) {
document.getElementById("comment-container").prepend(newItem);
} else {
document.getElementById("comment-container").append(newItem);
}
fadeIn(newItem);
visibleComments.push(element);
{%- comment -%}
/* Hide the 'no comments available' section since we have added a comment */
{%- endcomment -%}
hide("no-comments");
show("num-comments-displayed");
};
{%- if site.google_forms_comments.google_app_script -%}
function reloadComments() {
fetch(`{{ site.google_forms_comments.google_app_script }}?url=${thisPageUrl}`)
.then(response => response.json())
.then(response => {
var error = response?.error || null;
if (error != null) {
console.error(error);
setText("comment-submit-error", error);
show("comment-submit-error");
} else {
setText("comment-submit-error", '');
hide("comment-submit-error");
displayComments(response);
}
});
};
{%- else -%}
{%- comment -%}
/* Calls to the Google Sheets gviz API to load the comment data
Since we are storing comments for all of our blog articles in one sheet, we filter
by page URL. */
{%- endcomment -%}
function reloadComments() {
{%- comment -%}
/*
Use SQL in the gviz URL to load the correct csv.
In this implementation, columns are mapped to the following:
A - timestamp, the time the comment was left
B - page url, the page the comment was left on
C - name, the text left in the comment name field
D - comment, the text left in the comment field
E - isAuthor, boolean indicating if the comment was left by the actual author
*/
{%- endcomment -%}
var sqlStatement = encodeURIComponent(`SELECT A, C, D, E WHERE B = '${thisPageUrl}'`);
fetch(`{{ site.comment-read }}/gviz/tq?tqx=out:csv&sheet=comments&tq=${sqlStatement}&headers=0`)
.then(response => response.text())
.then(response => displayComments(response));
};
{%- endif -%}
{%- comment -%}
/* encodes the form data for http transport */
{%- endcomment -%}
const encodeFormData = (data) => {
return Object.keys(data)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
.join('&');
};
{%- if recaptcha_enabled -%}
function checkRecaptcha() {
{%- comment -%}
Disallow posting a new comment until this one has posted or failed.
{%- endcomment -%}
disablePostCommentButton();
grecaptcha.ready(function() {
var pageAction = "comment_submit_{{ page.title }}".replace(/[^A-Za-z/_]/g, "");
grecaptcha.execute('{{ site.google_forms_comments.recaptcha_site_key }}', { action: pageAction }).then(function(token) {
postComment(token);
});
});
return false;
};
{%- endif -%}
function getCommentContent() {
var comment = getValue("comment-comment")?.toString();
var extraCommentInfo = {};
{%- if comment_replies_enabled -%}
var replyToCommentId = document?.getElementById("reply-to-comment-id")?.text;
if (replyToCommentId != null && replyToCommentId != "") {
extraCommentInfo.replyToCommentId = replyToCommentId;
}
{%- endif -%}
if (Object.keys(extraCommentInfo).length !== 0) {
comment = EXTRA_INFO_START + JSON.stringify(extraCommentInfo) + EXTRA_INFO_END + comment;
}
return comment;
};
{%- comment -%}
/* Posts a comment */
{%- endcomment -%}
{%- if site.google_forms_comments.google_app_script -%}
function postComment(recaptchaToken) {
disablePostCommentButton();
var username = getValue("comment-name");
var comment = getCommentContent();
fetch(`{{ site.google_forms_comments.google_app_script }}`, {
method: 'POST',
mode: 'cors',
redirect: "follow",
headers: {
"Content-Type": "text/plain;charset=utf-8"
},
body: JSON.stringify({
url : thisPageUrl?.toString(),
name : username?.toString(),
comment : comment?.toString(),
recaptchaToken: (recaptchaToken || null)
})
}).then(response => response.json())
.then(response => {
var error = response?.error || null;
if (error != null) {
console.error(error);
setText("comment-submit-error", error);
show("comment-submit-error");
} else {
setValue("comment-name", '');
setValue("comment-comment", '');
setText("comment-submit-error", '');
hide("comment-submit-error");
displayComments(response);
{%- if comment_replies_enabled -%}
clearCommentReplyItem();
{%- endif -%}
}
})
.catch(error => {console.log(error);})
.finally(() => { enablePostCommentButton(); });
return false;
};
{%- else -%}
function postComment(recaptchaToken) {
disablePostCommentButton();
var username = getValue("comment-name");
var comment = getCommentContent();
fetch(`{{ site.comment-post }}/formResponse`, {
method: 'POST',
mode: 'no-cors',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: encodeFormData({
"{{ site.comment-post-fields[0] }}" : thisPageUrl?.toString(),
"{{ site.comment-post-fields[1] }}" : username?.toString(),
"{{ site.comment-post-fields[2] }}" : comment?.toString()
})
}).then(response => {
setValue("comment-name", '');
setValue("comment-comment", '');
{%- if comment_replies_enabled -%}
clearCommentReplyItem();
{%- endif -%}
reloadComments();
})
.catch(error => {console.log(error);})
.finally(() => { enablePostCommentButton(); });
return false;
};
{%- endif -%}
{%- unless lazy_load_enabled -%}
initialCommentLoad();
{%- endunless -%}
</script>
{%- comment -%}
<!--
HTML for displaying the actual comment section.
It has a state for both when the article has comments and when it does not. -->
{%- endcomment -%}
<h4 class="post-subtitle">Comments</h4>
<div id="load-comments" class="comments">
<button id="load-comment-button" class="comment-button" onclick="initialCommentLoad()">Load Comments</button>
</div>
<div id="comments-and-input">
<div id="comment-section" class="comments">
<p id="num-comments-displayed"></p>
<button id="load-more-comments" class="comment-button" onclick="loadMoreComments(true)" type="button">Load Older Comments</button>
<div id="no-comments" class="comment-info-text">
<p>There are currently no comments on this article, be the first to add one below</p>
</div>
<div id="comment-container"></div>
</div>
<h4 class="post-subtitle">Add a Comment</h4>
<div class="comments">
<div class="comment-info-text">
<p>Note that I may remove comments for any reason, so try to be civil. If you are looking for a response to your comment, either leave your email address or check back on this page periodically.</p>
{%- if site.google_forms_comments.google_app_script -%}
<p id="comment-submit-error"></p>
{%- endif -%}
</div>
<div class="comments-form">
{%- if recaptcha_enabled -%}
<form onsubmit="return checkRecaptcha()" id="comment-form" autocomplete="off">
{%- else -%}
<form onsubmit="return postComment()" id="comment-form" autocomplete="off">
{%- endif -%}
<ul>
<li>
<input id="comment-name" name="username" type="text" placeholder="Name" required="" value="">
{%- if comment_replies_enabled -%}
<p id="comment-reply-info"></p>
{%- endif -%}
</li>
<li><textarea id="comment-comment" name="comment" placeholder="Comment" required=""></textarea></li>
<li><button id="comment-submit" type="submit" class="comment-button">Post</button></li>
</ul>
{%- if recaptcha_enabled -%}
<p id="comment-recaptcha-disclaimer">This site is protected by reCAPTCHA and the Google
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
{%- endif -%}
<p>
</form>
</div>
</div>
</div>
{%- comment -%}
<!--
Styling information.
This might typically be in an scss file but is added here so only a single
file needs to be added to a project trying to implement this feature. -->
{%- endcomment -%}
<style>
@import url("https://fonts.googleapis.com/css?family=Source+Sans+Pro");
.comment-item {
position: relative;
padding: 0.5em 2.5em;
background: white;
font-family: "Source Sans Pro", sans-serif;
width: 95%;
margin: 1em auto;
box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.comment-item:after {
content: "";
position: relative;
display: block;
clear: both;
}
.comment-item p {
line-height: 1.6;
}
.comment-item small {
padding-left: 0.7em;
color: #999;
font-size: 0.8em;
}
.commenter-name {
color: #367588;
text-decoration: none;
font-size: 1em;
font-weight: 700;
}
.commenter-name strong {
color: #e91e63;
text-decoration: none;
font-size: 1em;
font-weight: 700;
}
{%- if comment_replies_enabled -%}
.comment-reply-button {
float: right;
cursor: pointer;
}
.comment-reply-button img {
display: inline;
vertical-align: middle;
width: 1.2em;
height: 1.2em;
margin: 0;
content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23999999'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z'/%3E%3C/svg%3E");
}
.comment-reply-button:hover {
color: #e91e63;
}
.comment-reply-button:hover img {
content:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 0 24 24' width='24px' fill='%23e91e63'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z'/%3E%3C/svg%3E");
}
.comment-reply-id {
color: #e91e63;
font-size: .9em;
cursor: pointer;
}
#comment-reply-info {
float: right;
font-size: .9em;
color: #e91e63;
cursor: pointer;
}
#comment-reply-info small {
vertical-align: middle;
}
.comment-reply-clear {
color: #e91e63;
font-size: 1.1em;
cursor: pointer;
}
{%- endif -%}
#comment-reply-info p {
margin: 0;
}
.comments-form {
margin-left: 1em;
margin-right: 1em;
width: 95%;
font-family: "Source Sans Pro", sans-serif;
}
.comments-form ul {
list-style: none;
margin-left: -40px;
}
.comments-form ul li {
margin-bottom: 15px;
}
.comments {
align-items: center;
border-top: 0.5px solid #e5e5e5;
padding-top: 1rem;
position: relative;
}
.comment-button {
border: 0;
border-radius: 8px;
background: #148ee2;
color: #fff;
font-family: "Source Sans Pro", sans-serif;
font-weight: bold;
font-size: 0.9em;
text-transform: uppercase;
margin-bottom: 20px;
outline-style: none;
padding: 10px 20px;
width: auto;
min-width: 25%;
}
#comment-submit {
width: auto;
min-width: 25%;
position: relative;
}
.comment-button:disabled::after,
.comment-button[disabled]::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border: 4px solid transparent;
border-top-color: #ffffff;
border-radius: 50%;
-webkit-animation: button-loading-spinner 1s ease infinite;
animation: button-loading-spinner 1s ease infinite;
}
@keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}
@-webkit-keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}
#load-more-comments {
width: auto;
}
#load-more-comments,
#num-comments-displayed {
display: none;
}
#comment-name,
#comment-comment {
width: 50%;
padding: 10px;
border: 0;
border-radius: 8px;
background: #f7f7f7;
font-family: "Source Sans Pro", sans-serif;
}
#comment-name::-webkit-input-placeholder,
#comment-comment::-webkit-input-placeholder {
font-family: "Source Sans Pro", sans-serif;
}
#comment-name::-moz-placeholder,
#comment-comment::-moz-placeholder {
font-family: "Source Sans Pro", sans-serif;
}
#comment-name:-ms-input-placeholder,
#comment-comment:-ms-input-placeholder {
font-family: "Source Sans Pro", sans-serif;
}
#comment-name::-ms-input-placeholder,
#comment-comment::-ms-input-placeholder {
font-family: "Source Sans Pro", sans-serif;
}
#comment-name::placeholder,
#comment-comment::placeholder {
font-family: "Source Sans Pro", sans-serif;
}
#comment-name:focus,
#comment-comment:focus {
background: #fff;
font-family: "Source Sans Pro", sans-serif;
}
#comment-comment {
width: 100%;
height: 80px;
resize: vertical;
min-height: 80px;
}
{%- if recaptcha_enabled -%}
{%- comment -%}
If you want to use the regular recaptcha badge (instead of the text currently below
the submit button), remove this and the text disclaimer in the HTML above. Note that
according to their FAQ page, one or the other must be displayed.
https://developers.google.com/recaptcha/docs/faq#id-like-to-hide-the-recaptcha-badge.-what-is-allowed
{%- endcomment -%}
.grecaptcha-badge {
visibility: hidden;
}
#comment-recaptcha-disclaimer {
text-align: justify;
text-align-last: center;
font-size: .7em;
font-family: "Source Sans Pro", sans-serif;
}
{%- endif -%}
{%- if site.google_forms_comments.google_app_script -%}
#comment-submit-error {
color: red;
display: none;
}
{%- endif -%}
.comment-info-text {
letter-spacing: 0.5px;
text-align: center;
}
.comment-info-text p {
margin: 0 0 1rem;
text-align: justify;
text-align-last: center;
font-size: .9em;
}
#comment-container {
width: 100%;
}
#comment-section, #load-comments {
display: flex;
flex-direction: column;
justify-content: center;
}
{%- if lazy_load_enabled -%}
#comments-and-input {
display: none;
}
{%- else -%}
#load-comments {
display: none;
}
{%- endif -%}
</style>
{%- endif -%}

View File

@ -0,0 +1,34 @@
<!-- Generate footer -->
<style>
a {
text-decoration: none;
color: blue;
}
img {
vertical-align: middle;
}
.footer-logo {
width: 100%;
height: auto;
margin-top: -10px;
margin-bottom: 10px;
text-align: center;
display: inline-block;
}
</style>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="footer-logo">
<a href="/">
<img width="100px" height="30px" title="Open-Air-Logo" src="./assets/images/openair-logo.png"
alt="logo">
</a>
Copyright &copy; 2019-current OpenAir-Collective. Distributed by an <a
href="https://github.com/openair-collective/openair-cyan/blob/main/LICENSE">GPL 3.0.</a>
</div>
</div>
</div>
</div>

235
docs/_includes/form.html Normal file
View File

@ -0,0 +1,235 @@
<head>
<style>
html {
font-family: Arial, Helvetica, sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue';
display: inline-block;
}
h1 {
font-size: 1.8rem;
}
h5 {
background: #03a9f4;
width: 100%;
height: 11px;
border-style: none;
border-radius: 10px;
}
i {
font-size: 2.2rem;
}
p {
font-size: 1.4rem;
}
body {
margin: 0;
}
hr {
margin-left: 3px;
width: 99%;
background-color: #dadce0;
}
.content-form {
padding: 5%;
}
.card-grid {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 2rem;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.input-group {
display: flex;
}
.card {
background-color: white;
box-shadow: 2px 2px 12px 1px rgba(8, 8, 8, 0.5);
border-radius: 10px;
}
.card-header {
font-size: 1.2rem;
font-weight: bold;
color: #47464b;
}
input[type=submit] {
border: none;
color: #FEFCFB;
background-color: #034078;
padding: 15px 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
width: 100px;
margin-right: 10px;
margin-left: 10px;
border-radius: 10px;
transition-duration: 0.4s;
}
input[type=submit]:hover {
background-color: #1282A2;
}
input[type=text],
input[type=number],
select {
width: 50%;
padding: 12px 20px;
margin: 18px;
display: inline-block;
border: 1px solid #ccc;
border-radius: 10px;
box-sizing: border-box;
}
.value {
font-size: 1.2rem;
color: #1282A2;
}
.state {
font-size: 1.2rem;
color: #1282A2;
}
button {
border: none;
color: #FEFCFB;
padding: 15px 32px;
text-align: center;
font-size: 16px;
width: 100px;
border-radius: 10px;
transition-duration: 0.4s;
}
.button-on {
background-color: #034078;
}
.button-on:hover {
background-color: #1282A2;
}
.button-off {
background-color: #858585;
}
.button-off:hover {
background-color: #252524;
}
.ideation label {
font-size: 1.2rem;
width: 100%;
padding: 10px;
display: inline-block;
text-align: left;
}
.ideation large {
width: 100%;
padding-left: 10px;
padding-top: 10px;
padding-right: 10px;
display: inline-block;
text-align: left;
font-weight: bold;
}
.ideation small {
width: 100%;
padding: 10px;
display: inline-block;
text-align: left;
}
input[type=button] {
padding: 1px 2px;
margin-left: 10px;
text-align: right;
border-radius: 6px;
display: inline-block;
width: auto;
font-size: large;
color: #1b0c8787;
}
</style>
</head>
<body>
<div class="content-form">
<div style="color: #47464b;" align="center" class="title">
<h1>Sheet Design to Improve CYAN Capacity</h1>
<hr>
</div>
<div class="card-grid">
<div class="card">
<h5></h5>
<form action="" method="POST">
<section class="ideation">
<p>
<large style="font-size: xx-large;">CYAN Ideation - Sheet Design</large>
<small style="font-size: large;">
We are looking for a way to form calcium hydroxide (or
magnesium hydroxide) into easily-made sheets. The idea is that this would allow us
to extend the current single-layer CYAN design to one with multiple layers that can
capture even more CO2. Humid CO2-filled air will be passed parallel to the
sheets. Then the sheets will be weighed before and after to calculate the weight change,
which is relatable to the amount of CO2 taken up. <br>
<br>
The calcium hydroxide will yield calcium carbonate upon absorbing CO2. Note that
calcium carbonate is a solid that will not dissolve in water. This property could be
used to separate out the calcium carbonate. Calcium hydroxide is slightly soluble in
water.<br>
<br>
Requirements:<br>
<ul>
1) The sheets must be as thin and stiff as possible without being brittle and thus
easy to break. Sheets that are no more than 0.5 mm are ideal.<br>
<br>
2) The sheets must not come apart when exposed to humid air.<br>
<br>
3) It must be easy to separate the resulting calcium carbonate from the sheet. This
can be done by making any adhesive dissolvable in water or another easily available
solvent, or the sheet might be entirely made from calcium hydroxide + binder.<br>
<br>
4) Once the calcium carbonate is removed, the sheet material must either be
recyclable, compostable, or otherwise reusable in the process of making more
sheets.<br>
<br>
5) The embodied carbon of the sheets should be as low as possible.<br> In general,
metals, cement, and other materials that require high temperatures for manufacturing
will be high embodied carbon sources.<br>
</ul>
Current Ideas:<br>
<ul>
1) Use a binder to make a thin film of calcium hydroxide.<br>
<br>
2) Adhere calcium hydroxide to a backing board of some material.<br>
<br>
3) Use a thin film of calcium hydroxide to form a sheet.<br>
</ul>
</small>
<hr>
</p>
</section>
</form>
</div>
</div>
</div>
</body>

View File

@ -0,0 +1,3 @@
<!-- google iframe begin - place google form embed link here-->
<!-- google iframe end -->

View File

@ -0,0 +1,4 @@
<figure class="image">
<img src="{{ include.url }}" alt="{{ include.description }}">
<figcaption>{{ include.description }}</figcaption>
</figure>

View File

@ -0,0 +1,14 @@
<div class="recent-articles">
<h2>Recently Published</h2>
{% assign maxposts = 5 %}
<ul class="post-list text-muted list-unstyled">
{% for post in site.posts limit: maxposts %}
<li>
<p>
<a class="article-link" href="">
{{ post.title | escape }}</a>
</p>
</li>
{% endfor %}
</ul>
</div>

View File

@ -0,0 +1 @@
$link-color: $blue-000;

View File

@ -0,0 +1,17 @@
/* * {
color: rgb(72, 6, 252) !important;
} */
/* // Print-only styles.
@media print {
.side-bar,
.page-header {
display: none;
}
.main-content {
max-width: auto;
margin: 1em;
}
} */

View File

@ -0,0 +1,3 @@
---
---
{% include css/just-the-docs.scss.liquid color_scheme="openair" %}

View File

@ -0,0 +1,3 @@
"use strict";
jtd.setTheme("openair");

32
docs/gemfile Normal file
View File

@ -0,0 +1,32 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "~> 3.9.0"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.12"
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", "~> 2.0.4"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
# GitHub page
gem "github-pages", "~> 221", group: :jekyll_plugins

285
docs/gemfile.lock Normal file
View File

@ -0,0 +1,285 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (3.2.22.5)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.17.13)
ruby-enum (~> 0.5)
concurrent-ruby (1.1.10)
dnsruby (1.61.9)
simpleidn (~> 0.1)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.15.0)
ffi (>= 1.15.0)
eventmachine (1.2.7-x64-mingw32)
execjs (2.8.1)
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.3)
multipart-post (>= 1.2, < 3)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
ffi (1.15.5-x64-mingw32)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (221)
github-pages-health-check (= 1.17.9)
jekyll (= 3.9.0)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.1.6)
jekyll-default-layout (= 0.1.4)
jekyll-feed (= 0.15.1)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.13.0)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.6.1)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.7.1)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.1)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.12.5, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.9)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (~> 4.0)
public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.1)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.1.1)
coffee-script (~> 2.2)
coffee-script-source (~> 1.11.1)
jekyll-commonmark (1.3.1)
commonmarker (~> 0.14)
jekyll (>= 3.7, < 5.0)
jekyll-commonmark-ghpages (0.1.6)
commonmarker (~> 0.17.6)
jekyll-commonmark (~> 1.2)
rouge (>= 2.0, < 4.0)
jekyll-default-layout (0.1.4)
jekyll (~> 3.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.13.0)
jekyll (>= 3.4, < 5.0)
octokit (~> 4.0, != 4.4.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.6.1)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.7.1)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.12.0)
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.1)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.3)
listen (3.7.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
multi_json (1.15.0)
multipart-post (2.1.1)
nokogiri (1.13.4-x64-mingw32)
racc (~> 1.4)
octokit (4.22.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.7)
racc (1.6.0)
rb-fsevent (0.11.1)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.5)
rouge (3.26.0)
ruby-enum (0.9.0)
i18n
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
simpleidn (0.2.1)
unf (~> 0.1.4)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
typhoeus (1.4.0)
ethon (>= 0.9.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2022.1)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.1-x64-mingw32)
unicode-display_width (1.8.0)
wdm (0.1.1)
PLATFORMS
x64-mingw32
DEPENDENCIES
github-pages (~> 221)
jekyll (~> 3.9.0)
jekyll-feed (~> 0.12)
minima
tzinfo (~> 2.0.4)
tzinfo-data
wdm (~> 0.1.1)
BUNDLED WITH
2.2.29

8
docs/help-child.md Normal file
View File

@ -0,0 +1,8 @@
---
layout: default
title: Comments and Suggestions
nav_order: 4
has_children: false
---
{% include comments.html url=page.url %}

8
docs/help.md Normal file
View File

@ -0,0 +1,8 @@
---
layout: default
title: HELP! Ideas Needed
nav_order: 4
has_children: true
---
{% include googleform.html %}