Skip to content

Latest commit

 

History

History

README

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
<!DOCTYPE html>
<html>
<head>
<title>README.md</title>
    <link rel="icon" type="image/x-icon" href="/pho-2-icon">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">

<style>
/* https://github.com/microsoft/vscode/blob/master/extensions/markdown-language-features/media/markdown.css */
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

body {
	font-family: var(--vscode-markdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif);
	font-size: var(--vscode-markdown-font-size, 14px);
	padding: 0 26px;
	line-height: var(--vscode-markdown-line-height, 22px);
	word-wrap: break-word;
}

#code-csp-warning {
	position: fixed;
	top: 0;
	right: 0;
	color: white;
	margin: 16px;
	text-align: center;
	font-size: 12px;
	font-family: sans-serif;
	background-color:#444444;
	cursor: pointer;
	padding: 6px;
	box-shadow: 1px 1px 1px rgba(0,0,0,.25);
}

#code-csp-warning:hover {
	text-decoration: none;
	background-color:#007acc;
	box-shadow: 2px 2px 2px rgba(0,0,0,.25);
}

body.scrollBeyondLastLine {
	margin-bottom: calc(100vh - 22px);
}

body.showEditorSelection .code-line {
	position: relative;
}

body.showEditorSelection .code-active-line:before,
body.showEditorSelection .code-line:hover:before {
	content: "";
	display: block;
	position: absolute;
	top: 0;
	left: -12px;
	height: 100%;
}

body.showEditorSelection li.code-active-line:before,
body.showEditorSelection li.code-line:hover:before {
	left: -30px;
}

.vscode-light.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(0, 0, 0, 0.15);
}

.vscode-light.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(0, 0, 0, 0.40);
}

.vscode-light.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

.vscode-dark.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(255, 255, 255, 0.4);
}

.vscode-dark.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(255, 255, 255, 0.60);
}

.vscode-dark.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

.vscode-high-contrast.showEditorSelection .code-active-line:before {
	border-left: 3px solid rgba(255, 160, 0, 0.7);
}

.vscode-high-contrast.showEditorSelection .code-line:hover:before {
	border-left: 3px solid rgba(255, 160, 0, 1);
}

.vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before {
	border-left: none;
}

img {
	max-width: 100%;
	max-height: 100%;
}

a {
	text-decoration: none;
}

a:hover {
	text-decoration: underline;
}

a:focus,
input:focus,
select:focus,
textarea:focus {
	outline: 1px solid -webkit-focus-ring-color;
	outline-offset: -1px;
}

hr {
	border: 0;
	height: 2px;
	border-bottom: 2px solid;
}

h1 {
	padding-bottom: 0.3em;
	line-height: 1.2;
	border-bottom-width: 1px;
	border-bottom-style: solid;
}

h1, h2, h3 {
	font-weight: normal;
}

table {
	border-collapse: collapse;
}

table > thead > tr > th {
	text-align: left;
	border-bottom: 1px solid;
}

table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
	padding: 5px 10px;
}

table > tbody > tr + tr > td {
	border-top: 1px solid;
}

blockquote {
	margin: 0 7px 0 5px;
	padding: 0 16px 0 10px;
	border-left-width: 5px;
	border-left-style: solid;
}

code {
	font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
	font-size: 1em;
	line-height: 1.357em;
}

body.wordWrap pre {
	white-space: pre-wrap;
}

pre:not(.hljs),
pre.hljs code > div {
	padding: 16px;
	border-radius: 3px;
	overflow: auto;
}

pre code {
	color: var(--vscode-editor-foreground);
	tab-size: 4;
}

/** Theming */

.vscode-light pre {
	background-color: rgba(220, 220, 220, 0.4);
}

.vscode-dark pre {
	background-color: rgba(10, 10, 10, 0.4);
}

.vscode-high-contrast pre {
	background-color: rgb(0, 0, 0);
}

.vscode-high-contrast h1 {
	border-color: rgb(0, 0, 0);
}

.vscode-light table > thead > tr > th {
	border-color: rgba(0, 0, 0, 0.69);
}

.vscode-dark table > thead > tr > th {
	border-color: rgba(255, 255, 255, 0.69);
}

.vscode-light h1,
.vscode-light hr,
.vscode-light table > tbody > tr + tr > td {
	border-color: rgba(0, 0, 0, 0.18);
}

.vscode-dark h1,
.vscode-dark hr,
.vscode-dark table > tbody > tr + tr > td {
	border-color: rgba(255, 255, 255, 0.18);
}

</style>

<style>
/* Tomorrow Theme */
/* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */

/* Tomorrow Comment */
.hljs-comment,
.hljs-quote {
	color: #8e908c;
}

/* Tomorrow Red */
.hljs-variable,
.hljs-template-variable,
.hljs-tag,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-regexp,
.hljs-deletion {
	color: #c82829;
}

/* Tomorrow Orange */
.hljs-number,
.hljs-built_in,
.hljs-builtin-name,
.hljs-literal,
.hljs-type,
.hljs-params,
.hljs-meta,
.hljs-link {
	color: #f5871f;
}

/* Tomorrow Yellow */
.hljs-attribute {
	color: #eab700;
}

/* Tomorrow Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet,
.hljs-addition {
	color: #718c00;
}

/* Tomorrow Blue */
.hljs-title,
.hljs-section {
	color: #4271ae;
}

/* Tomorrow Purple */
.hljs-keyword,
.hljs-selector-tag {
	color: #8959a8;
}

.hljs {
	display: block;
	overflow-x: auto;
	color: #4d4d4c;
	padding: 0.5em;
}

.hljs-emphasis {
	font-style: italic;
}

.hljs-strong {
	font-weight: bold;
}
</style>

<style>
/*
 * Markdown PDF CSS
 */

 body {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif, "Meiryo";
	padding: 0 12px;
}

pre {
	background-color: #f8f8f8;
	border: 1px solid #cccccc;
	border-radius: 3px;
	overflow-x: auto;
	white-space: pre-wrap;
	overflow-wrap: break-word;
}

pre:not(.hljs) {
	padding: 23px;
	line-height: 19px;
}

blockquote {
	background: rgba(127, 127, 127, 0.1);
	border-color: rgba(0, 122, 204, 0.5);
}

.emoji {
	height: 1.4em;
}

code {
	font-size: 14px;
	line-height: 19px;
}

/* for inline code */
:not(pre):not(.hljs) > code {
	color: #C9AE75; /* Change the old color so it seems less like an error */
	font-size: inherit;
}

/* Page Break : use <div class="page"/> to insert page break
-------------------------------------------------------- */
.page {
	page-break-after: always;
}

</style>

<script src="https://unpkg.com/mermaid/dist/mermaid.min.js"></script>
</head>
<body>
  <script>
    mermaid.initialize({
      startOnLoad: true,
      theme: document.body.classList.contains('vscode-dark') || document.body.classList.contains('vscode-high-contrast')
          ? 'dark'
          : 'default'
    });
  </script>
<h1 id="pho2-official-content-management-site">(PhO)^2 Official Content Management Site</h1>
<blockquote>
<p>Version 2.0</p>
</blockquote>
<div style="text-align: center; overflow-x: hidden;">
<pre style="display: inline-block margin-left: -100%; margin-right: -100%; text-align: left;">
<pre><code>									    ..           ,,              ..      /\         
									  pd'`7MM&quot;&quot;&quot;Mq.`7MM               `bq   //\\        
									 6P    MM   `MM. MM                 YA //  \\       
									6M'    MM   ,M9  MMpMMMb.  ,pW&quot;Wq.  `Mb     pd*&quot;*b.
									MN     MMmmdM9   MM    MM 6W'   `Wb  8M    (O)   j8
									MN     MM        MM    MM 8M     M8  8M        ,;j9 
									YM.    MM        MM    MM YA.   ,A9 ,M9     ,-='    
									 Mb  .JMML.    .JMML  JMML.`Ybmd9'  dM     Ammmmmmm 
									  Yq.                             .pY               
										  ``                           ''                 
</code></pre>
</pre>
</div>
<p>The Philippine Online Physics Olympiad is an annual contest held by the Physics Youth Honor Society of the PSHS-Main Campus devoted to promoting a shared interest in the field of physics while offering high school students the opportunity to express their skills and competence through an online collaborative battle of the smarts. This repository represents the development resources behind its content management system (CMS).</p>
<br>
<div style="text-align: center; overflow-x: hidden;">
<pre style="display: inline-block margin-left: -100%; margin-right: -100%; text-align: left;">
<pre><code>                                                    |\      _,,,---,,_
                                             ZZZzz /,`.-'`'    -.  ;-;;,_
                                                  |,4-  ) )-,_. ,\ (  `'-'
                                                 '---''(_/--'  `-'\_)


																				[Mo David @2022-@2023]
</code></pre>
</pre>
</div>
<hr>
<h1 id="table-of-contents">Table of Contents</h1>
<h2 id="1-project-file-structure">1 Project File Structure</h2>
<pre class="hljs"><code><div>📦pho2-2.0-official
 ┣ 📂middleware
 ┃ ┣ 📜auth.js
 ┃ ┣ 📜check.js
 ┃ ┗ 📜identify.js
 ┣ 📂models
 ┃ ┣ 📜problem.js
 ┃ ┣ 📜score.js
 ┃ ┣ 📜submission.js
 ┃ ┗ 📜user.js
 ┣ 📂public
 ┃ ┣ 📂admin
 ┃ ┃ ┣ 📜dashboard.html
 ┃ ┃ ┣ 📜dashboard.js
 ┃ ┃ ┗ 📜navbar.js
 ┃ ┣ 📂resources
 ┃ ┃ ┣ 📂icons
 ┃ ┃ ┃ ┣ 📜search-icon.png
 ┃ ┃ ┃ ┗ 📜trash-icon.png
 ┃ ┃ ┗ 📂images
 ┃ ┃ ┃ ┗ 📜pyhs-banner.png
 ┃ ┣ 📂user
 ┃ ┃ ┣ 📜dashboard.html
 ┃ ┃ ┣ 📜dashboard.js
 ┃ ┃ ┗ 📜navbar.js
 ┃ ┣ 📂utils
 ┃ ┃ ┣ 📜answer.js
 ┃ ┃ ┣ 📜header.js
 ┃ ┃ ┣ 📜regex.js
 ┃ ┃ ┗ 📜xhr.js
 ┃ ┣ 📜fb-embed-pyhs.html
 ┃ ┣ 📜fb-embed-ymsat.html
 ┃ ┣ 📜home-redirect.html
 ┃ ┣ 📜home.html
 ┃ ┣ 📜leaderboard.html
 ┃ ┣ 📜pho-2-official-logo.png
 ┃ ┗ 📜problems.html
 ┣ 📂routes
 ┃ ┣ 📜adminroutes.js
 ┃ ┣ 📜authroutes.js
 ┃ ┗ 📜userroutes.js
 ┣ 📜README.md
 ┣ 📜package-lock.json
 ┣ 📜package.json
 ┗ 📜server.js
</div></code></pre>
<h3 id="11-serverjs-file">1.1 <code>server.js</code> File</h3>
<p>This file represents the entry point into running the website. It is the main file of the server of the CMS.</p>
<h3 id="12-middleware-folder">1.2 <code>/middleware</code> Folder</h3>
<p>Contains middleware (basically utility functions and services) that aids with executing some processes on the website. The three main services implemented here are for authorization, answer checking, and user identification. In hindsight, this folder would've better been named &quot;services&quot;, as middleware is a more technical term that usually refers to processes that execute between client requests and server jobs. You can check out the <a href="#3-source-code-components">Source Code Components</a> section for more detailed information on the individual files.</p>
<h3 id="13-models-folder">1.3 <code>/models</code> Folder</h3>
<p>These js files represent the structure of the information stored by the database. The four primary objects are the following: problems (the contest problems), scores (stores information on individual user scores, alongside their submission statuses), submissions (stores submissions parameters such as the final verdict and what not), and users (some simple user account data). Again, you can check out the <a href="#3-source-code-components">Source Code Components</a> section for more detailed information on the individual files.</p>
<h3 id="14-public-folder">1.4 <code>/public</code> Folder</h3>
<p>The public folder represents all the files and assets visible to the clients. There are two separate implementations of the UI: one for regular user clients and another for admin clients. The differences are purely aesthetic and do not offer users the capability to elevate permissions by hijacking (or running) the admin html code (if they somehow found it).</p>
<p>The utils folder contained herein offers some IO handling functionalities, since we can't trust users to input the right things, although admin inputs are no longer format checked. Other utilities for things like internal HTTP requests are also implemented. The files are explained in more detail in <a href="#3-source-code-components">Source Code Components</a>.</p>
<hr>
<h2 id="2-aws-management">2 AWS Management</h2>
<p align="center">
	<img src="./images/AWS/AWS Logo.jpg">
</p>
<p>In the case of this CMS, we will be using Amazon Web Services (AWS) to host all its features.</p>
<p>If you are a member of the Philippine Youth Honor Society (PYHS) and wish to contribute as a developer of (PhO)^2, send an email to <code>modavid.1964@gmail.com</code> with the subject line <code>(PhO)^2 Developer Request</code>. Only users provided with access to the AWS account can contribute to the development of the (PhO)^2 CMS.</p>
<h3 id="21-aws-navigation-guide">2.1 AWS Navigation Guide</h3>
<p>If this is your first time using AWS to help manage (PhO)^2, it might be best to read this section thoroughly. For any questions, please do not hesitate to contact the head developer.</p>
<p>Developers will be given access to the (PhO)^2 website through an invitation sent to their inboxes. This invitation will prompt them to register under the (PhO)^2 organization in AWS and will give them developer permissions to manage the resources of the (PhO)^2 CMS. After following the instructions highlighted by the email, they should be greeted by the access portal (the link is also provided in the email in case this does not happen automatically). Clicking on the <code>AWS Account</code> icon will show the <code>(PhO)^2 Organization</code> account; clicking this will then enumerate the different permissions available to a user. For developers, the two default permissions available are the <code>DatabaseAdministrator</code> and <code>NetworkAdministrator</code> permissions. The <code>Management console</code> button to the right of these will open options to manage the pertinent resources.</p>
<blockquote>
<p><strong>NOTE:</strong> <code>AdministratorAccess</code> will be restricted to the head developer to ensure the security of the CMS.</p>
</blockquote>
<p align="center">
	<img src="./images/AWS/AWS Access Portal.jpg">
</p>
<h3 id="22-managing-the-database">2.2 Managing the Database</h3>
<h3 id="23-managing-the-server">2.3 Managing the Server</h3>
<h3 id="24-the-env-file">2.4 The <code>.env</code> File</h3>
<!-- ! WHERE TO LOCATE THE ENV FILE -->
<p>The <code>.env</code> file contains a number of parameters, each explained in the table below. These parameters must be configured before the website can run properly. The default values must be replaced as these are only there for development purposes.</p>
<table>
<thead>
<tr>
<th>Environment Variable</th>
<th>Purpose</th>
<th>Default Value</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DATABASE_URL</code></td>
<td>Points to the location of the database and allows the server to access the database and make requests to it.</td>
<td><code>mongodb://localhost:27017/pho-2</code></td>
</tr>
<tr>
<td><code>ACCESS_TOKEN_SECRET</code></td>
<td>A secret string used to encrypt JWT access tokens given to users. You can keep the value as is, so long as it has not been made public. If the value is compromised (for some reason someone else has access to the string), replace it immediately with any sufficiently long string.</td>
<td><code>&lt;SECRET&gt;</code></td>
</tr>
<tr>
<td><code>REFRESH_TOKEN_SECRET</code></td>
<td>As opposed to access tokens, refresh tokens allow user sessions to occur. Nonetheless, they serve the same purpose of encrypting data and must not be made public. Again, replace this string if it becomes compromised in any way.</td>
<td><code>&lt;SECRET&gt;</code></td>
</tr>
<tr>
<td><code>SUBMISSION_COOLDOWN</code></td>
<td>The minimum length of time in seconds between two valid submissions from a given user account. In other words, a user cannot submit more than once before this cooldown has expired.</td>
<td><code>300</code></td>
</tr>
<tr>
<td><code>CONTEST_START</code></td>
<td>Refers to the Unix timestamp (in milliseconds) that indicates the exact start of the contest.</td>
<td><code>0</code></td>
</tr>
<tr>
<td><code>CONTEST_END</code></td>
<td>Refers to the Unix timestamp (in milliseconds) that indicates the exact end of the contest.</td>
<td><code>259200000</code></td>
</tr>
</tbody>
</table>
<h3 id="25">2.5</h3>
<p>To begin the code</p>
<h3 id="26-running-on-aws">2.6 Running on AWS</h3>
<pre class="hljs"><code><div># Windows
&gt; main.exe full
</div></code></pre>
<pre class="hljs"><code><div># Unix
&gt; main.exe full
</div></code></pre>
<hr>
<h2 id="3-source-code-components">3 Source Code Components</h2>
<p>This section outlines the composition of the code of the game. All files and folders mentioned here are under the <code>/src</code> folder described in <a href="#1-project-file-structure">Project File Structure</a>.</p>
<h3 id="31-gamec-file">3.1 <code>game.c</code> File</h3>
<p>Think of <code>game.c</code> as nothing more than a main file that handles the configuration of all the other game components.</p>
<h3 id="32-game-folder">3.2 <code>/game</code> Folder</h3>
<p>All the actual game components (such as game class, game state management, game data and assets, and game mode implementations) are contained in this folder. The different subfolders are also outlined below.</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>game.assets.h</code></td>
<td>The file stores the ASCII art required by the full mode of the game. It also holds a bit of the dialogue printed out by the game, although the rest of these seem to be scattered across both the <code>game.manager.h</code> and <code>game.manager.min.h</code> files.</td>
</tr>
<tr>
<td><code>game.catalogue.h</code></td>
<td>The file stores the information regarding the different crops available in the game. Initially, another crop (the apple) was available, although the course specifications seem to disallow the inclusion of additional crops.</td>
</tr>
<tr>
<td><code>game.manager.h</code></td>
<td>This file manages the flow of the full mode of the game. Interestingly, it is not the longest file within the game.</td>
</tr>
<tr>
<td><code>game.manager.min.h</code></td>
<td>The file manages the flow of the default mode of the game.</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>NOTE:</strong> The reason <code>game.manager.min.h</code> has <code>.min</code> appended to it is because the initial version of Harvest Sun <em>was the full mode</em> of the game. Eventually, however, a reexamination of the course specifications prompted the author to reconsider what the &quot;default&quot; mode of the game should be.</p>
</blockquote>
<h4 id="321-gameclasses-folder">3.2.1 <code>/game/classes</code> Folder</h4>
<p>The different instantiable classes of the game are implemented in this folder.</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>game.class.plot.h</code></td>
<td>The class refers to the individual plots stored within the grid layout of the farm. An instance of this class stores information on the state of the plot (for example, whether or not it is tilled) and holds an instance of the <code>game.class.product.h</code> class if something has been planted on it.</td>
</tr>
<tr>
<td><code>game.class.product.h</code></td>
<td>An instance of this class represents a &quot;plant&quot; of sorts. The instance keeps track of the growth state of the crop alongside its other parameters.</td>
</tr>
<tr>
<td><code>game.class.stock.h</code></td>
<td>This class acts like a container which helps store an amount of crops. It is used by both the <code>game.obj.player.h</code> and <code>game.obj.shop.h</code> to store the amount of seeds or crops they have in their respective inventories. The prices associated with buying or selling a crop type may also be computed through the methods provided by this class.</td>
</tr>
</tbody>
</table>
<h4 id="322-gameenums-folder">3.2.2 <code>/game/enums</code> Folder</h4>
<p>Enums were used primarily to store the state of different elements of the game. The actual enum items were prefaced by the type they belong to; this avoided the possibility of name clashes while the developing the game.</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>game.enums.farm.h</code></td>
<td>Enums for plot states and farm actions are stored here. Farm action enums allow the use of switch statements to handle different farm actions.</td>
</tr>
<tr>
<td><code>game.enums.shop</code></td>
<td>Enums for shop actions are stored here. Again, this helps with implementing switch statements.</td>
</tr>
<tr>
<td><code>game.enums.state</code></td>
<td>Enums for game states are stored here. Two different enums are implemented (<code>GameState</code> and <code>PlayState</code>), although one would've worked perfectly fine if only the author had thought about that sooner. Enums for handling dialog boxes are also present.</td>
</tr>
</tbody>
</table>
<h4 id="333-gameobjects-folder">3.3.3 <code>/game/objects</code> Folder</h4>
<p>A distinction between objects and classes must be made here. The author takes it that classes are meant to be instantiable. Objects, on the other hand, are often singletons within a code framework.</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>game.obj.farm.h</code></td>
<td>This object handles the management of the farm and deals with the primary UI and IO functionalities associated with the farm. The farm is visually represented by a grid array, although under the hood it is actually stored as a single-dimensional array.</td>
</tr>
<tr>
<td><code>game.obj.player.h</code></td>
<td>The player object manages the state of the player and abstracts the actions the user can perform within the game.</td>
</tr>
<tr>
<td><code>game.obj.shop.h</code></td>
<td>The shop object allows the player to acquire seeds throughout the game. It also allows the player to sell their crops following a harvest.</td>
</tr>
</tbody>
</table>
<h3 id="33-utils-folder">3.3 <code>/utils</code> Folder</h3>
<p>The utils folder handles most of the low-level functionality not necessarily associated with the game. Things related to input, output, and console handling are placed here. The following are the files contained within the folder:</p>
<table>
<thead>
<tr>
<th>File</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>utils.io.h</code></td>
<td>Unifies the differences in C implementation of Windows and Unix systems by creating common functions that help handle IO functionality. Most importantly, it handles the behaviour and properties of the console itself.</td>
</tr>
<tr>
<td><code>utils.key.h</code></td>
<td>Contains functions that read user input and perform actions based on those. The main implementations in here are read/write polls with callbacks; in other words, functions that repeatedly read the input buffer and execute a &quot;before&quot; and &quot;after&quot; callback for each keystroke. The function also provides utilities for evaluating character values.</td>
</tr>
<tr>
<td><code>utils.selector.h</code></td>
<td>A utility class (yes, it's a struct, but it behaves almost like an instantiable class) that makes it much more convenient to code a selection of items. It has methods (yes, they're not really methods but they behave pretty much like methods) that help the user to interact with the class.</td>
</tr>
<tr>
<td><code>utils.text.h</code></td>
<td>Another utility class that makes it easier to create blocks of text that will be displayed later to the console. Instances of the class basically act as output buffers that store content before it is outputed to the screen.</td>
</tr>
<tr>
<td><code>utils.ui.h</code></td>
<td>Handles functionality associated with printing to the console. It also contains implementations of functions that directly interact with instances of the <code>utils.text.h</code> class. These functions allow the possibility to format content (for instance, centering text or adding a constant footer).</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>NOTE:</strong> Prematurely exiting the program in a Unix environment may prevent the program from reverting the terminal settings to their configuration prior to the execution of the program. In other words, if it ever happens you hit <code>Ctrl+C</code> while running the program in Unix, you may have to restart the terminal.</p>
</blockquote>
<hr>
<h2 id="6-contacts-and-other-info">6 Contacts and Other Info</h2>
<div style="text-align: center; overflow-x: hidden;">
<pre style="display: inline-block margin-left: -100%; margin-right: -100%; text-align: left;">
<pre><code>                                                    |\      _,,,---,,_
                                             ZZZzz /,`.-'`'    -.  ;-;;,_
                                                  |,4-  ) )-,_. ,\ (  `'-'
                                                 '---''(_/--'  `-'\_)
</code></pre>
</pre>
</div>

</body>
</html>