A user-generated text-adventure
Choose Your Own Adventure Game, or CYOAG for short, is an idea Steven Kitzes came up with, based on the choose-your- own-adventure books he grew up with. The basic idea behind these books was that the reader would be presented with very short chapters for context; then get to pick from a handful of options leading to different page numbers, ultimately resulting in different paths through a story that always started the same but had many possible endings. Steven enjoyed reading, and was thrilled to discover books with variable outcomes.
Now, later in life, Steven has come to love writing as much as he loves reading. Having grown into a career in software development, and remembering his love of choose-your-own-adventure books, he decided it would be a great potential side project to build a website that combines all of these loves into one. The CYOAG is, thus, a web app that proposes to let users read and/or create content for a choose-your- own-adventure game online. This broad-strokes definition will be described in much greater detail throughout this document.
Changes made to this document are as follows (click to expand/collapse):
Author | Date | Version | Changes |
Steven Kitzes | 2016.11.13 | 1.3.0 | Updated to clean up documentation so it matches changes necessitated during implementation. Includes specifying change from Handlebars to React, and some database design changes, as well as adding new stretch goals. |
Steven Kitzes | 2016.10.06 | 1.2.10 | Updated column name in votes table from author_uid to voter_uid for clarity. |
Steven Kitzes | 2016.10.05 | 1.2.9 | Data Model updated to use VARCHAR instead of CHAR everywhere since using CHAR in just a few places adds no benefit. Also changed an INT to TINYINT, for what it's worth. |
Steven Kitzes | 2016.10.04 | 1.2.8 | Data Model updated to include user account type (e.g. moderator vs user). |
Steven Kitzes | 2016.08.20 | 1.2.7 | Data Model updated to remove circular dependency in users and nodes tables. Updated all UID fields from length 32 to 40. |
Steven Kitzes | 2016.08.15 | 1.2.6 | Updated Data Model to reflect a need to store session IDs and current page locations for users; updated hashed and uid lengths to 32. |
Steven Kitzes | 2016.08.13 | 1.2.5 | Updated maximum node snippet length to 2,000. |
Steven Kitzes | 2016.08.07 | 1.2.4 | Tweaked database design and added table diagrams. |
Steven Kitzes | 2016.08.06 | 1.2.3 | Stretch Goals main section removed, multi-root stretch goal moved to User Stories main section. |
Steven Kitzes | 2016.08.01 | 1.2.2 | Added stretch goals to User Stories. |
Steven Kitzes | 2016.08.01 | 1.2.1 | Corrected erroneous formatting and list ordering. |
Steven Kitzes | 2016.08.01 | 1.2.0 | Added last user stories for the first pass of this document, first pass now complete. Let's get to developing this thing! |
Steven Kitzes | 2016.07.31 | 1.1.1 | Added more user stories, particularly to the User Accounts and Continuation sections. |
Steven Kitzes | 2016.07.31 | 1.1.0 | Added details to user account under basic feature families. Added user stories and made it collapsable due to its size. |
Steven Kitzes | 2016.07.31 | 1.0.3 | Made iterations and definitions tables collapsible to reduce clutter. |
Steven Kitzes | 2016.07.31 | 1.0.2 | Removed a link that had been included for testing. |
Steven Kitzes | 2016.07.30 | 1.0.1 | Colors and styling updated, no content updates or additions. |
Steven Kitzes | 2016.07.28 | 1.0.0 | First draft, design complete until development, consultation, and discovery necessitate changes. Separated CSS into two files, one for general documentation use, the other one specific to our functional-requirements.html file. Refactored HTML and CSS for much cleaner, safer, maintainable, expandable project. |
Steven Kitzes | 2016.07.27 | 0.2.1 | Beginning HTML refactor; no content change, just separating CSS to dedicated file, and beginning effort to improve HTML-correctness. |
Steven Kitzes | 2016.07.24 | 0.2.0 | Migrating to HTML since my MS Office license was revoked and I'm bitter about it, and HTML is a better format for versioning anyway. Detailed Votification Rules main section fleshed out. Stretch Goals main section added. |
Steven Kitzes | 2016.07.24 | 0.1.2 | First documented update; includes Document iteration main section; new Definitions entries for downvote, moderator, RDBMS, UID, upvote, and votification; new Basic Feature Family entry for Moderator intervention; new Explicit Restriction entry for Path snippet content; new main section for Detailed Votification Rules; and content for the Architecture and Technology Stack, and Data Model main sections. |
The following terms used throughout this document warrant further explanation (click to expand/collapse):
Term | Definition |
account | Unless otherwise specified, a CYOAG account. Not to be confused with a linked social media account, which in this document shall be referred to as such to prevent confusion. |
accounted user | A user with an account registered and linked to social media on CYOAG. Typically, it is implied that this user is logged in when referred to in this document unless otherwise specified. Note that moderators are counted among accounted users. |
AMI | Amazon Machine Image - a virtual machine image provided by Amazon AWS for hosting web services. |
child | Any node, reachable via a path, that follows immediately after the current node. |
CYOAG | Create Your Own Adventure Game - the name of this web application. |
downvote | A vote by a user against a specific node, indicating negative sentiment. |
moderator | A user with a CYOAG account linked to a social media account, and who has special privileges granted for purposes of editing or removing content that violates site usage guidelines (e.g. a story snippet containing spam, or other abusive site usage). Note that moderators are counted among accounted (registered) users. |
node | A collection of all data representing a particular point in the story. This includes snippet and ID data for the current part of the story, the current node's parent, and zero or more paths. |
node ID | The UID of the current node. |
node snippet | The main story content (prose) at the current node. |
parent | The node immediately preceding the current node; in other words, the current node is reachable via a path from the parent. |
path | One option (usually of several) for story progression, leading away from the current node toward another, subsequent node. |
path snippet | A short piece of text describing one of a reader's potential choices for progressing the story past the current node. Note that a given node's path snippet is displayed with that node's parent, to provide an option for progression that leads from said parent to the current node. |
RDBMS | Relational database management system - a technology for defining and constructing a database, and maintaining data therein; e.g. MySQL. |
registered | A user is registered if they have associated a social account for the purposes of logging in to save progress, apply sentiment, etc. |
root node | The very first node of the story, provided free of charge by Steven Kitzes, from which all paths and subsequent nodes follow. |
terminal [node] | Any node with no paths yet defined leading out from it. A node that terminates a story trajectory. |
trajectory | A complete series of paths leading from the root node all the way to the current node. |
UID | Unique identifier - a randomly generated string with astronomically small odds of a collision. |
unaccounted user | Also called a 'visitor,' a user with no registered account on CYOAG, or an accounted user or moderator who is not currently logged in. |
upvote | A vote by a user in favor of a specific node, indicating positive sentiment. |
user ID | A user's UID. |
visitor | Any person using the CYOAG site while not logged in. |
votify, votified, votification | A promoted node state that ensures the path to said node will be visible as a primary choice from that node's parent; this promotion occurs when user votes raise a node's vote count higher than its siblings, and can be a default state in the case that a node has few or no siblings. |
welcome page | The first page displayed to any user when visiting the CYOAG site if cookies are not enabled, if the user is not logged in, or if the user is starting from scratch with a new trajectory. |
Observing this application at a high level, the following basic features are proposed (with further details provided later in this document):
Any user visiting the site shall be able to read the story, making path selections to progress as far through the story as desired without needing an account.
Any user shall be able to register and log into a CYOAG account by associating a social media account, and shall be able to "delete" their account (dissociate social media accounts from CYOAG). Posts under that account shall thenceforth be permanent, only able to be deleted by a moderator (if they can be deleted at all).
Any user with cookies enabled shall be able to pick up where the story left off if they stop reading in the middle of a trajectory.
Any registered user who is logged in shall be able to create new paths, leading to new story nodes from existing nodes.
Any registered user who is logged in shall be able to apply positive or negative sentiment to any node to which they have navigated, a decision which they shall be able to cancel or reverse at any time.
A moderator shall have special privileges granted for the purposes of improving quality (e.g. correcting typos) and enforcing CYOAG rules and guidelines (e.g. removing spam or other abusive content). This includes modifying content posted by users, deleting content, and blocking users from posting new content, but does not include the ability to override content contribution rules (e.g. a moderator may not contribute multiple paths to a node or contribute consecutive nodes).
Subject to the explicit restrictions listed in following sections, the following specific use cases elaborate and expand on the Basic Feature Families described above (click to expand/collapse):
The following user stories relate to the basic feature family of viewing content on CYOAG.
A visitor shall be able to recursively read the node snippet at the current node, and see and select from votified and randomized path snippets at that node. Upon initial page load, visitors shall be shown the first story node by default, except as specified below under the Continuation feature family. Visitors shall be able to follow an entire story trajectory from the welcome page through any terminal node.
Registered users shall be able to recursively read the node snippet at the current node, and see and select from available path snippets leading out from that node. Registered users shall have the option to expand, view, and select from a list of non-votified paths if desired. Upon initial page load, registered users shall be shown the first story node by default, except as specified below under the Continuation feature family. Registered users shall be able to follow an entire story trajectory from the root story node through any terminal node.
Any user shall have the option to return to the node previous to the current node, up to the root node.
Any user shall have the option to return to the root node to start a new trajectory. In this case, any information linking the user's session and/or account to a stored node for continuation shall be lost; therefore, the user shall be notified of this danger and required to confirm before proceeding.
The following user stories relate to user account management.
When any user visits any CYOAG page unaccounted, all features reliant upon user account association shall display instead as an invitation log in or sign up via social media.
When any user visits any CYOAG story page unaccounted, user interface elements shall be presented to allow that user to log in. If credentials are validated, the user shall be presented with a page update showing all features available as appropriate for that user's account type (i.e. registered user or moderator). If the user rejects social authentication, the existing session for that user shall be restored and the user shall be able to continue as a visitor.
When a visitor views any CYOAG story page, user interface elements shall be presented to allow that user to create an account by logging in through social media. These elements shall include Facebook and Twitter, and may in the future include Google+, user name and password, and other authentication methods.
A moderator shall be able to terminate/ban any user, excluding other moderators. Each node generated by the terminated account shall be retained, but shall be modified so that its author is listed as banned.
The following user stories describe how CYOAG pages should behave when a user leaves, and later returns.
CYOAG shall track user progress through story trajectories using cookies. If a user is logged in via social media, this progress shall be recorded on the CYOAG cloud, as well.
If a visitor returns to CYOAG after leaving, with cookies enabled, then the cookie shall restore the most recently visited node.
There is no way to track an unaccounted user across devices, so in this situation the visitor will necessarily be treated as a brand new, unaccounted user.
Story trajectory progress of registered users shall be tracked on the cloud so that registered users can maintain their position across devices.
Cookies shall help CYOAG to remember that a given social media account was logged in by associating a GUID with that social media account and storing that in a cookie. CYOAG shall preserve that account's login status until the user logs out or the cookie expires.
The following user story describes how registered users can contribute new nodes and paths to CYOAG.
When viewing any node as a registered user, user interface elements shall be displayed below the list of expanded/collapsed paths out from the current node that allow the user to fill in the details for a new node, and the path from the current node to the new child node being created. A button shall be included for submission, and appropriate validation shall occur when this button is pressed, both in the client and the on the server. SQL injection attack protection shall also be implemented on the server side.
The following user stories describe the ways in which users can participate in CYOAG's votification system.
Users that do not have accounts or are not logged in shall not be able to upvote or downvote nodes.
Users that are logged into CYOAG accounts through social media shall be presented with user interface elements allowing them to upvote or downvote the current node. In the event a registered user has already voted on the current node, the UI shall reflect this automatically, and shall allow the user to change their vote from among the three distinct state possibilities for node votification: upvote, downvote, or no vote.
For example, the user may always select either the upvote or downvote button; if the user selects an unselected button, that button becomes selected, and the previously selected button, if any, becomes unselected; if the user selects an already selected button, that button becomes unselected and the no-vote state is entered.
For more details on votification, see Detailed Votification Rules below.
The following user stories detail the ways in which moderators can enforce the spirit and rules of CYOAG.
When viewing any node, a moderator shall be presented with more information on that node than an ordinary user would be, including the node's UID.
When viewing any node, a moderator shall be presented with special management options, including:
User interface elements shall be presented to moderators on every node page, providing the ability for moderators to navigate directly to any other node by UID.
There are certain behaviors we want to disallow to prevent users from abusing the site or acting without the spirit of collaboration in mind. These behaviors are prevented or limited by design.
Edits to a node (including its node snippet and path snippet) shall be allowed only by that node's original creator, and only if that node has zero child nodes. This is to prevent later changes from breaking story continuity or altering the flow of the story as interpreted by subsequent authors. Exception: moderators can always edit any post.
Only a node's creator shall be able to delete it, and only if that node has no child nodes. Exception: moderators can always delete any post; deletions must cascade to child nodes to prevent database pollution.
No user shall be permitted to contribute more than a single path to any node. No exception for moderators.
A user shall not be permitted to contribute a path to a node that was created by that same user. No exception for moderators.
A node snippet shall have a minimum length of 250 characters, and a maximum length of 2,000 characters. A path snippet shall have a minimum length of 4 characters, and a maximum length of 100 characters. No exception for moderators.
A path snippet shall not have the same content as another path snippet at the same node. No exception for moderators.
No user shall be able to vote (either up or down) for their own nodes. No exception for moderators.
Votification is the system by which sibling nodes are promoted to, or demoted from, the status of being a primary path choice from a given parent. Here are detailed the system of rules governing votification promotion, demotion, and the effects this state has on the user experience.
Users without accounts shall not be able to apply positive or negative sentiment to story nodes. Instead of votification controls, these visitors shall instead be shown a call to action for account login or registration through social media (Facebook, Twitter, and possibly others in the future).
Registered users shall have access to votification features. These accounted users shall be shown active votification buttons that both reflect, and allow changes to, the user's votification of the current node.
Moderators shall have access to all of the features available to registered users.
There are a variety of rules for displaying paths based on the number of them that exist leading out from any given node, and the sentiment applied to them by users, in order to display the most popular paths while still giving all other paths a fair chance at being seen by users and not falling into obscurity.
If there are no paths out from the current node, CYOAG shall report that, and display no nodes.
If there is only one path out from the current node, just display it.
If there are two paths out from the current node, the most popular shall be displayed first, with an icon marking it as the most popular. However, if they are tied for popularity, neither shall be marked with a popularity icon.
If there are three paths out from a given node, display all three, ordered by popularity. If one stands out as the most popular, mark it with a popularity icon, but if there is a tie for most popular between two or all three of the paths, mark none.
If there are four paths out from a given node, display all four, ordered by popularity. If one stands out as the most popular, mark it with a popularity icon, but if there is a tie for most popular between two, three, or all four of the paths, mark none.
If there are more than four paths out from a given node, find the two most popular paths from the set, and display them as the first two paths available, with popularity icons accompanying both. If there is a tie of more than two ways for most popular, choose two from among the tied paths at random, and display those as the first two paths, with popularity icons. After the first two paths are selected, then choose two more at random from among the set of all paths not yet selected (including those that lost the aforementioned tie breaker), and display these two as the second pair of available paths, but without popularity icons.
The desire to get the CYOAG project off the ground using the AWS Free Tier services will limit the technologies available. However, with the technologies made available through the AWS Free Tier, all requirements are achievable.
The server shall host a Node.js instance, running on a Linux AMI on Amazon EC2.
The AWS Free Tier provides only relational database technologies, so NoSQL solutions are not available (although, because the relationships between data points are as important as data storage itself for this application, an RDB is likely the best choice to run with regardless). Therefore, data shall be managed using MySQL due to availability and familiarity.
CYOAG static files shall be served from an Amazon S3 bucket.
The CYOAG front end shall be delivered as a mixture of traditional vanilla HTML, CSS, and JavaScript with a templating technology (ReactJS) to limit code duplication. In order to reduce the load on the Amazon S3 bucket (identified as a weak point in the AWS Free Tier service stack), the app shall be designed as a SPA (single page application) to minimize static asset calls, instead carrying out DOM manipulation to display a variety of UI elements.
Since the AWS Free Tier limits database technology options to RDBMS selections only (as of this writing), and since CYOAG has thus been designed to utilize MySQL, data shall be organized into a table structure. Data shall be divided into a number of tables to accommodate the limitations and requirements of relational database schemas, and to facilitate project organization and separation of concerns to the extent possible. (See MySQL's documentation for more details.)
The users table shall contain information defining and pertaining to specific user accounts. The table shall include fields to record a user's chosen name, randomized or formulated unique ID (UID), and current session ID (UID format). In the future, this table may be expanded to contain more data, in the event that CYOAG is modified to allow users to register accounts using user name and password combinations as opposed to social media authenticated accounts.
users | |||
---|---|---|---|
Key | Unique | Column | Type |
PK | yes | uid | varchar(40) |
yes | name | varchar(16) | |
no | acct_type | varchar(16) | |
yes | session_uid | varchar(40) |
The nodes table shall contain information defining a given node, including information defining relationships between nodes, but not defining user sentiment toward a node. In other words, this table shall contain a node's UID, the UID of its parent, the node's snippet, and its path snippet; but it shall not contain information on the node's children, or any upvotes, or downvotes cast on the node.
nodes | |||
---|---|---|---|
Key | Unique | Column | Type |
PK | yes | uid | varchar(40) |
no | parent_uid | varchar(40) | |
FK | no | author_uid | varchar(40) |
no | path_snippet | varchar(100) | |
no | node_snippet | varchar(2000) |
The positions table shall contain information on the current position of a user in the story tree, including the user's UID and the node's UID.
positions | |||
---|---|---|---|
Key | Unique | Column | Type |
PK + FK | yes | user_uid | varchar(40) |
PK + FK | yes | node_uid | varchar(40) |
Note: the original Data Model design called for the users table to provide a column indicating the current node position of each user. However, this would have caused the users table to contain a foreign key from the nodes table (current node), and the nodes table to contain a foreign key from the users table (author ID). This type of circular dependency is poor practice (and not supported by MySQL in any case).
The votes table shall contain data relating user sentiment to the nodes for which that sentiment is expressed. Each row shall contain as a compound primary key a user UID and a node UID, so that each such combination is unique, preventing a user from casting multiple votes on the same node. Each row shall contain as a third datum a flag defining the user's sentiment as positive or negative. This flag can be switched in order to reflect a change in sentiment, or an entire row can be deleted to reflect a user's desire to express no sentiment on a node.
votes | |||
---|---|---|---|
Key | Unique | Column | Type |
PK + FK | yes | node_uid | varchar(40) |
PK + FK | yes | voter_uid | varchar(40) |
no | sentiment | tinyint |
Following are a short list of features to be added as a low priority. These are features that are considered nice-to-have's, or stretch goals, but without which we feel this project can still be a success.
A moderator shall be able to suspend a registered user account, allowing that user to continue logging in as a registered user but withholding rights to add new content, to make or change votes, or to otherwise participate on the site until suspension is lifted. In this case, the user shall be notified of why they were suspended via a message displayed upon login attempts.
Any user shall be able to download an entire trajectory from the root node through their current position in the story. If possible, we shall make it possible to select either raw text, or ebook formats.
Moderators shall be able to click an author's name on a node, and be presented with a list of all paths by that author, including UID, and those paths shall be clickable so that the moderator can navigate straight to any path by the aforementioned author.
Any user visiting CYOAG shall have the option of beginning a trajectory from one of several root nodes, to enjoy stories of diverse tone, direction, setting, etc. Depending on the balance between user interest and moderator availability, and complexity of implementation, user submissions for new root nodes shall be accepted.