Introduction
This report details my COMP 4911 capstone project. I’m a fourth-year Computer Science student attending TRU’s OL program. I work full time as a software engineer at a video game studio – working in technology and on content that is far different than what was completed in this project.
My client is a Twitch (https://www.twitch.tv/) streamer who participates in a yearly charity stream for the non-profit organization Extra-Life (https://www.extra-life.org/) where she collects donations from viewers for BC Children’s Hospital. In mid-November, the client runs a stream where viewers can donate to extend the time of the stream. Oftentimes the stream ends up surpassing 24-hours (and often extends into the 30+ hour mark).
Currently, the client doesn’t have a good way to automatically track donations from both Extra-Life and Twitch and have these update the remaining stream time. This means that the streamer must manually add time to the stream timer whenever donations of certain types occur. This is challenging to keep track of and can detract from the quality of the stream. The goal of this project was to build a Twitch plug-in that would be able to collect donation data from both Twitch and Extra-Life and then apply it to several viewer-facing stream widgets.
Specifically, the client needed a solution that would:
- Track subscriptions, follows, and cheers (bits) from Twitch
- Track donations through Extra-Life
- Display a stream countdown timer to viewers
- Display a donation stats tracker that showed recent and top donations
- Display a video notification with dynamic donation text
- Automatically send a message to Twitch chat with donation information
A stretch-goal was also defined at the beginning of the project that involved a Twitch integrated game with the purpose of helping drive donations. This was not completed during this project due to timing (further details in the remainder of the report). This was a secondary priority and will likely be completed in the future for next year’s (2024) stream.
Installation and User Guide
The following details how to install and launch the local server, perform Twitch authentication, and access the front-end pages.
In general, the steps users will need to take are:
- One-time download of the project source code
- One-time server prerequisite install
- Launch the local server
- Launch the config page and authenticate with Twitch
- Launch the front-end pages
Download Source Code
To download the source code, navigate to https://github.com/athiessen-TRU/el-streamtools-ATTRU, click on ‘Code’ and click ‘Download ZIP’. Extract this ZIP folder to a convenient location and open it to the root folder.
Install Server Prerequisites
On Windows, you can simply run the Install.bat file located in the source code’s root folder. This will automatically install all of the required NodeJs modules required to run the server.
If you are on a Mac/Unix OS (not officially supported) or the above batch file doesn’t work, open a CLI in the root project folder and run the following commands to install prerequisites:
- winget install OpenJS.NodeJS
- npm install express
- npm install ws
- npm install uuidv4
Launch The Server
On Windows, you can simply run the Launch.bat file located in the source code’s root folder. This will automatically launch the local server.
If you are on a Mac/Unix OS (not officially supported) or the above batch file doesn’t work, open a CLI in the Server folder and run the following commands to launch the server:
- node configServer.js
Your local server should now be launched and running. If you used the batch file, the config page will also be opened by default.
Launch Config and Authenticate with Twitch
All front-end pages, including the config, are hosted at http://localhost:8080/ by default. The address and port can be adjusted in code if you wish.
If you launched the local server with the Launch.bat file, the config page should already be open. To reach the config page manually, navigate to http://localhost:8080/config.html in any browser.
We will discuss what each section of the config page does in a later section. For now, you will need to click the ‘Authenticate with Twitch’ link at the top of the page. This link will take you through the standard Twitch authentication flow and will need to be performed at the start of each session.
If you aren’t logged into Twitch, you will be prompted to log in. Once you are logged in, a Twitch prompt will ask you to accept the permission requests required for the application. You must accept if you wish to use the application with Twitch. Once you have accepted these permission requests once, you will not need to do it during future authentications. For more information on account permissions and how to revoke them, visit Twitch’s documentation here: https://help.twitch.tv/s/article/twitch-account-settings.
After authentication is completed, you will be redirected to the config page.
Front-end Pages
The front-end pages are what you will interact with (in the case of the config page) and what will be displayed on your stream (in the case of the other pages). Each page is rooted at http://localhost:8080/ by default.
These pages can be navigated to in a browser or can be added to a stream software of your choice as a browser source (such as OBS).
Config Page
The config page can be accessed at http://localhost:8080/config.html by default (after the server is launched). This page performs a few functions. First, it provides a location for the user to easily authenticate with Twitch at the beginning of the session (as detailed above). Second, it allows the user to configure values in seconds that each donation type will add to the timer and the remaining timer value. Lastly, it allows the user to test donations to verify all of the components are working as they would expect.
Timer Duration
The timer duration section of the config page allows the user to manually set a remaining time on the timer and also allows them to start and stop the timer.
Donation Timer Impacts
This section allows the user to set times (in seconds) that each of the donation types will add to the stream time (per unit).
Donation Testing
This section allows the user to trigger fake donations in order to test things such as stream layout ahead of time. Triggering one of these donations will perform all of the same actions a normal donation would, including increasing time remaining.
Donation Notifications
This section contains the message that will display in Twitch chat following the standard message announcing donor and time added to stream.
Timer Page
The timer page can be accessed at http://localhost:8080/timer.html by default (after the server is launched). This page displays the stream countdown timer. If added as a browser source to a stream tool such as OBS, it should be added as the size 300×190 and then adjusted in the view window to the desired size on stream.
Donation Stats Page
The donation stats page can be accessed at http://localhost:8080/stats.html by default (after the server is launched). This page displays the most recent donation as well as the top three donations in order (regardless of timing). If added as a browser source to a stream tool such as OBS, it should be added as the size 300×500 and then adjusted in the view window to the desired size on stream.
Notifications Page
The notifications page can be accessed at http://localhost:8080/notifications.html by default (after the server is launched). This page is fully transparent until a donation is made at which time the streamer’s donation notification video will play. If added as a browser source to a stream tool such as OBS, it should be added as the size 480×275 and then adjusted in the view window to the desired size on stream.
Enabling Twitch Event Sub Debug Mode
By default, the server is configured to connect to Twitch’s live event sub server. If, however you wish to test the event sub service locally using the Twitch CLI, you can do so by setting the kUsingDebug to true within the Server/serverTwitchHelpers.js file. This assumes the Twitch CLI socket server is launched at port 8000 (to not conflict with the plug-in local server at 8080). The usage of the Twitch CLI is beyond the scope of this document but information about how to use it can be found here: https://dev.twitch.tv/docs/cli/.
Development Model
In addition to providing its core functionality, the plug-in needs to ‘feel good’ to the client while using it. This is an extremely subjective measure, so it will be important to get something into the client’s hands quickly in order to get feedback and course correct if necessary.
Given this, I will be using an iterative development/agile approach to this project, with an emphasis on early tracer code. Tracer code in this context is an activity similar to prototyping, but with the goal of building a ‘placeholder’ plug-in as quickly as possible. When writing tracer code, the code demonstrates minimal (and placeholder in some cases) functionality to the user but is built using the paradigms and quality expected in final code. As a result, the tracer code isn’t discarded at the end of the prototyping phase. Given the relatively short timeline for this project, I’ve chosen this method to maximize the value of my time spent.
A high-level requirement gathering activity will be done upfront in order to identify the client’s primary needs. This will inform research into applicable APIs as well as what will need to be included in the tracer prototype. From this requirements list, a prioritized backlog of epics will be created and estimate point sizes will be assigned to each epic. These estimates are likely better described as ‘guesstimates’ at this phase as they are not intended to be highly accurate or precise but are instead to indicate a guess of relative levels of effort between each item for the client to review. At the start of each sprint (see more below), items will be pulled from the backlog and broken down into more granular pieces.
I will be using sprints to organize work and set immediate goals. Sprints will be in two-week intervals and will begin with the aforementioned process of breaking down the highest priority items in the backlog. These items will then be pulled into the sprint based on what I think I can accomplish in this two-week period. At the end of each sprint, I will perform a review of progress with the client as well as a brief backlog grooming activity to ensure current backlog priorities are still accurate.
I will also be adding two hardening weeks into the project. The purpose of these hardening weeks is to focus on any known outstanding bugs or overhang from previous sprints (if any). Further details on the timing of these weeks are noted in the project timeline section below.
Why this model?
I have chosen this model due to the need to put something into the client’s hands quickly to elicit feedback. Throughout the project I want to make sure that I am prioritizing the most important items to the client. The reality is that they may realize they need changes after seeing an initial prototype, or unanticipated discoveries could be made during development that will require a rapid pivot. By taking an agile approach, we aren’t throwing away our documentation and plans every time this happens.
In addition, the tracer code prototype model will support the goal of getting a minimum product to the client early in order to better align my work to the client’s needs and expectations. The tracer code prototype will be considered the first major iteration.
Weaknesses
Approaching iterative and agile development in this way makes measuring progress difficult. Even when items are broken down to more granular levels, estimates won’t be perfect. In addition, I will be using relative point sizes instead of by-day or by-hour estimates, so measuring how much remaining work is left in the project is unintuitive.
To combat this weakness, each sprint will end with a short velocity analysis to determine the average number of points completed per sprint so far. I will use this number to determine how many points to pull into each sprint and to provide a rough measurement of remaining project time. Obviously because I have no historicals for this project, the number of points I pull into the first sprint will be a guess.
It is worth noting that I have limited experience with the technologies required for this project, namely web languages such as JavaScript (I am typically a desktop application developer). I also have no experience with the Twitch or Extra-Life APIs. A more waterfall-oriented approach would prioritize reducing this risk through upfront research and design, whereas I’ll be carrying this risk through the project.
Planned Project Timeline
Before discussing the project timeline, it is important to note that this plan only reflects the creation of the donation tracker and Twitch integration. The stretch goal game will be built if the plug-in project ends up being far more condensed than anticipated. However, the requirements gathering, analysis, and design will still cover the game so that this work is already done in the event it gets built.
My goal is to complete the project within twelve weeks, dividing it into two milestones of four and eight weeks respectively. The first milestone will be the completion of planning documentation (this document and the requirements, analysis, and design documents), as well as completion of the plug-in tracer prototype. This milestone’s four weeks will be divided into two sprints.
The second milestone will encompass ‘production’ work which will be taking the placeholder features of the prototype to a final state. This time period will also include adding features that may have been missed in the prototype or added after the fact. The eight weeks of this milestone will be divided into three sprints and two hardening weeks. The first hardening week will take place after two sprints, with the second hardening week being the last week of the project.
Project Requirements
Requirements for this project are placed into functional and non-functional groupings.
Functional requirements are first presented in their epic format and have been prioritized by the client. Each epic then has a list of requirements to fulfill its deliverables. The combination of these epics and requirements will inform individual tasks that are broken out on a per-sprint basis.
For this initial requirement gathering activity, I met with the client and discussed the high-level features she would like to see in the extension and game. From these features, we created epics and prioritized them. Epics with a priority of 1 or 2 are considered must-have. The listed requirements are to be treated as deliverables required for successful completion of each epic. If a must-have epic cannot be completed, or the requirements for a given epic cannot all be met, a discussion will need to be had with the client about next steps.
The tracer code prototype mentioned in the development model document will implement the first iteration of priority 1 and 2 epics. Given this, there is a likelihood that this document will evolve significantly at the end of the prototyping phase.
Plug-in Functional Requirements
The following lists detail the requirements for the Twitch donation tracker plug-in.
Epics
This list represents the high-level feature backlog, prioritized by the client.
Epic | Epic Priority |
Stream countdown timer | 1 |
Donation timer impacts | 1 |
Donations config | 1 |
Donation stats tracker | 2 |
Donation announcements | 2 |
Basic donation effects | 3 |
Requirements
This list represents the requirements per epic, to be treated as the epic deliverables.
1 | Stream countdown timer |
1.1 | On-screen widget that is hide-able by viewers
This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
1.2 | Displays Hours, minutes, seconds left in stream |
1.3 | Updatable in real-time (see donation timer impacts) |
1.4 | Timer is pause-able by streamer |
2 | Donation timer impacts |
2.1 | Donations to twitch in the form of subscriptions, bits, follows increase remaining time of stream |
2.2 | Donations to extra-life site increase remaining time of stream |
2.3 | Timer is updated within 1 minute of donation being processed |
3 | Donations config |
3.1 | Streamer can access configuration window outside of stream |
3.2 | Streamer can set stream time increases by donation type – Dollars for extra-life donations – Per Subscription – Per bit – Per follow |
3.3 | Donation configs are entered in minutes seconds
After testing the interface with the user, it was determined that these numbers should be in seconds instead of minutes |
3.4 | Streamer can enter time remaining manually |
4 | Donation stats tracker |
4.1 | Displays as a dropdown within timer widget (hidden by default)
This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
4.2 | Viewers can press show/hide button within widget to hide stats while still displaying timer
This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
4.3 | Displays the most recent donation, who donated, the amount (and type) of donation, and time added |
4.4 | Displays the top 3 donations since streamer-defined date from the streams where this plug-in was used
After testing with the user, they decided they would like the top 3 donations to always persist for any streams that this plug-in is run, regardless of date. |
5 | Donation Announcements |
5.1 | Post chat message when donations occur (who, type, amount, time added) |
5.2 | Streamer can configure custom message to follow the above information in chat |
6 | Basic donation effects |
6.1 | Display an on-screen video using ‘Pingu Mozart meme’ – Displays amount donated in ‘happy’ part of video – Displays amount of time added in ‘terror’ part of video |
Game Functional Requirements
The following lists detail the requirements for the Twitch-integrated stream game.
Epics
This list represents the high-level feature backlog, prioritized by the client.
Epic | Epic Priority |
Foundation | 3 |
Game Boot | 4 |
Gameplay – Boss | 4 |
Gameplay – Player Actions | 3 |
Gameplay – Prompts | 4 |
Game Exit | 5 |
Requirements
This list represents the requirements per epic, to be treated as the epic deliverables.
1 | Foundation |
1.1 | Twitch full-screen plug-in or desktop app that can be shared in OBS (depending on twitch constraints) |
1.2 | Integrated with donation tracker plug-in so that the game is aware of incoming donations |
1.3 | Has a random (r) chance of triggering when x number of donations occur within y minutes – r, x, and y need to be configurable by the streamer |
1.4 | Integrated with twitch chat to take viewer commands and to post messages |
2 | Game Boot |
2.1 | Chat message will fire, warning chat that something approaches – default non-configurable message |
2.2 | Music should play on game launch |
2.3 | Boss’ image should fade in to screen over the course of ~5 seconds |
2.4 | An event timer of 2 minutes will display and begin counting down once boss image is fully on screen |
2.5 | Game ends when boss health reaches zero, or timer fully counts down, or all players have died (see boss requirements) |
3 | Gameplay – Boss |
3.1 | Boss will have a health bar that appears overhead |
3.2 | Boss will move in and out of 3 phases throughout fight – Each phase is 20 seconds in length – Strong phase – Focused phase – Attack phase |
3.3 | When in attack phase, all players not defending by the end of this phase (see player actions) will die and be removed from this fight |
3.4 | After each boss attack, a chat message will display how many players died from the attack |
3.5 | When in strong phase, takes 2x damage from magic attacks (see player actions) |
3.6 | When in focused phase, takes 2x damage from melee attacks (see player actions) |
4 | Gameplay – Player Actions |
4.1 | Players can take actions in chat that reduce the boss’ health – attack melee – attack magic |
4.2 | Players can take the defend action in order to not die during boss attack |
4.3 | Donations (Extra-Life, bits, subscriptions, or follows) will do additional damage – this will be configurable by the streamer |
5 | Gameplay – Prompts |
5.1 | Text will display in the middle of the screen, notifying players of the current boss phase – “Defend yourself! It attacks!” – “He is strong! Use magic attacks!” – “He is focused! Use melee attacks!” |
5.2 | Text will display when time is running out (<30 seconds remain) |
5.3 | Text will display upon defeat or victory over the boss |
6 | Game Exit |
6.1 | In either defeat or victory, music will stop playing |
6.2 | In either defeat or victory, boss image will fade out of screen |
6.3 | In the case of a defeat, a sound of the boss laughing will play |
6.4 | In the case of victory, a chat message will note that time has been added to the stream (configurable by the streamer) |
General Non-Functional Requirements
These requirements detail requirements not tied to specific features or functionality of the plug-in or game. Instead, they detail general requirements that need to be followed during the project.
1 | Technology |
1.1 | Must abide by allowed Twitch technologies – HTML, CSS, JS for extension code – Provided twitch API This is no longer a requirement, as the client and I opted for a local plug-in solution instead of an integrated extension |
1.2 | Must abide by API limits put in place by Extra-Life and Twitch (ie. Num calls/minute) |
1.3 | Must abide by Twitch extension policies listed here https://dev.twitch.tv/docs/extensions/guidelines-and-policies/
This is no longer a requirement, as the client and I opted for a local plug-in solution instead of an integrated extension |
2 | Security |
2.1 | Must not expose any sensitive information of streamer within extensions (IP address, name, etc) |
3 | Timeline |
3.1 | Must be delivered no later than the beginning of October, but preferably by beginning of September |
Analysis
There are many ways to implement Twitch compatible stream plug-ins. Below I look at the approach for the two main components of this project: the Twitch plug-in and the stretch-goal game.
Potential Approaches
Although there are many different approaches to creating a Twitch plug-in, defined here as something that interacts with Twitch’s event system and APIs, I’ll be looking at three common approaches. These approaches are a desktop application, an ‘external’ website that can be used as a browser source within the streamer’s broadcast application, or a Twitch-integrated extension.
Desktop Application
The desktop application option is exactly as it sounds: an application that would run on the streamer’s PC. The streamer would launch an application executable and integrate it into their stream as a separate video source.
The application would need to be built with an ‘application development’ language. Ideally the language would have built-in support for HTML calls (to easily access the APIs), web sockets (for the Twitch event system), and a GUI system that makes iteration fast. Given these requirements, C# seems like the best candidate language for this solution.
Benefits of this solution
- No need to construct a local or hosted server for data storage. Anywhere in the application is able to write directly to disk. This gets around having to write a layer between the presentation and application layers of the program that would be required in a web-based solution.
- A more comprehensive IDE experience with Visual Studio.
- Built around object-oriented and composition designs as core paradigms.
- More familiarity on my part: C# is a language that I have experience with.
- No Twitch approval process aside from obeying their API guidelines.
Negatives of this solution
- If the streamer wanted to move this plug-in to a Twitch-integrated extension in the future, the application would need to be redesigned into a client/server architecture.
- Users can’t interact with this element in the stream at all (versus a Twitch-integrated extension where they can see additional info and minimize it).
- Because I am more familiar with this method of development, I won’t be learning as much while working on the project.
- Requires the streamer to launch a separate application.
- Only applicable to the stretch-goal game: C# doesn’t have a comprehensive game development framework out of the box. I’d likely need to use a game engine such as Unity (based on C#). Using an engine like this is likely overkill and adds additional complexity.
External Webpage
The external webpage option involves building a web application that just runs locally on the streamer’s PC. They will be responsible for launching the local web server but once they do that, they will be able to add browser sources to their stream manager. This is well supported functionality within the streamer’s broadcast software (OBS).
This solution would need to be built as a client/server architecture with a locally hosted backend server. For the frontend, HTML and CSS will be required and JavaScript will be used to add scripts. For the backend server language, I’d want something that I can learn fairly quickly with strong support for web sockets and HTML calls. There are a ton of languages available for this purpose, but after some research I boiled it down to two options: C# or NodeJS. NodeJS has the benefit of keeping the codebase within one scripting language (JS), so this is the option I will opt to go with for this solution.
Benefits of this solution
- No web-hosting solution required which means no additional costs to the streamer to pay for web services.
- JS and NodeJS are extremely forgiving scripting languages and make it very easy to prototype and iterate quickly.
- Streamer already uses browser sources within OBS, so this is a well-understood workflow for them.
- This would be easily ported to a Twitch-integrated extension in the future if the streamer wished to.
- No Twitch approval process aside from obeying their API guidelines.
- A more involved learning experience for me personally.
- Only applicable to the stretch-goal game: Has well understood game development framework called Phaser that is built with JS.
Negatives of this solution
- Users can’t interact with this element in the stream at all (versus a Twitch-integrated extension where they can see additional info and minimize it).
- This is a type of development I have very little experience with, so this may slow down my development time.
- Requires the streamer to launch a local server.
Twitch Extension
This option involves going through Twitch’s extension building workflow to make something that lives within the stream on Twitch’s side as opposed to the streamer’s machine. In order to have persistent data, a web server would be required. This can be a local server while testing but would require a hosted web server for the final production-ready implementation.
Twitch-integrated extensions are essentially just webpages overlayed on the stream, so I’d use the same languages and tools discussed in the external webpage section above.
Benefits of this solution
- Twitch hosts the frontend on their server, so web hosting would only be required for the backend server.
- Users can interact directly with the plug-in while watching the stream (view additional information, hide the overlay, etc.)
- Setup is ‘set and forget’. After the streamer does the initial setup of the plug-in with their twitch stream, there is nothing else they need to do for future streams.
Negatives of this solution
- Hosted backend server is required which means the streamer will have to maintain (or pay someone to maintain) a web-hosted server. This also brings new security concerns and requirements into play that wouldn’t be a problem for a locally hosted server.
- Plug-in must pass Twitch’s certification process which may be lengthy, and the plug-in could be rejected on non-functional grounds such as wording or coding methods.
Chosen Solution
I discussed the benefits and negatives with the client and overall the best solution for client-ease as well as my personal learning is to use an external website for the Twitch plug-in, the donation notifications, and the stretch-goal game.
The benefits of this approach such as avoiding additional costs, ongoing web hosting concerns, and not having to wait on Twitch’s approval process, outweighed the negatives of losing user overlay interactivity and the ‘set and forget’ nature of the Twitch-integrated extension.
Given this, the languages I’ll be using are JavaScript, HTML, and CSS for the frontend, and JavaScript/NodeJS for the backend server. If I end up getting to the stretch-goal portion of this project, I’ll be using the JavaScript-based game library called Phaser.
As a result of this decision, the client and I have slightly revised the requirements document to fit any new constraints. I have also informed the client that I will write some simple batch scripts to help make installing prerequisites and launching the local server as simple as possible.
Design
The decision to build the Twitch plug-in and game around a local server largely informs their design. The following design was written during tracer prototyping of the Twitch plug-in and was refined as I moved through that process. I anticipate that things will still end up deviating from this design to some degree during production as unforeseen problems arise. I am not considering these deviations failures during this project as the intent is to develop this as an agile project, not a waterfall one.
On the note of this being an agile project (see the development methodology document), this design is not meant to be fully comprehensive, listing every function, object, etc. Instead, it’s focused on defining the major components of the project, their purpose, and how they interact with each other.
Note that the section of this document dedicated to the game will be brief as this is a stretch-goal. The design of the plug-in has been prioritized first.
Twitch Plug-in
As mentioned in the analysis document, the plug-in will utilize a local NodeJS server. The plug-in will be designed around a client-server model with distinct separation between the client and server. The reason for this separation is twofold:
First, it’s to facilitate encapsulation of functionality to make extending this plug-in easier in the future, to make the code more approachable, and to promote reusability.
Second, it’s due to the technical constraints of a browser. Outside of cookies, browsers do not write data to a local storage device which makes guaranteeing persistent data more challenging. We also require the ability to refresh browser pages without losing data integrity, and to enable different pages to communicate between one another. This is all handled by our authoritative server.
The Twitch plug-in is separated into five distinct modules and some helpers. The modules are the server, the configuration page, the timer page, the donation stats page, and the donation notification page.
Server
The server is meant to act as an authoritative mechanism for handling storage and consistency of data. It acts as the source of truth for all client-side modules. This allows client-side modules to be destroyed and instantiated without affecting the current state.
To facilitate this data consistency, the server saves and retrieves data to and from the disk. By writing to disk, the user can be sure that data will last between sessions, even in the event of an unexpected server shutdown. In order to limit the amount of disk reads used to retrieve data, all known state is pulled from disk into memory upon server initialization.
Another important function of the server is to handle incoming data from active clients and push out relevant data to clients that want to see it. This is handled through a persistent web socket connection between the server and various clients.
Functionality
The server is created as a websocket/Express server hybrid. Express manages serving our ‘static’ pages that form the pages the streamer can then access at a local address. This includes images, client-side JS code, html docs, and CSS docs.
The websocket server manages new and existing client socket connections. Clients establish a connection with the server on a specific local port. The server also manages client ‘heartbeats’ which checks if clients are still active using ping/pong messages. Typically, the client will notify the server that the connection is being closed, but in the event this doesn’t happen (a common occurrence with browsers), the server will automatically close the connection if a heartbeat fails. At the time of this writing, heartbeats occur once every 30 seconds.
The server acts as a message handler and sender. Clients send specific messages to the server, and the server can expect certain data based on the message type. These messages are a custom struct I have defined and fall under the following types:
- Timer config updates: changes the remaining time on the timer
- Donation config updates: changes to donation timer values
- Timer start/stop requests
- Donation events: events that are triggered when a donation occurs
- Debug donation events: events that trigger a false donation so that the streamer and I can test functionality without being live
- Subscription events: requests from clients to be added to the subscription lists for specific events, allowing them to be notified when these events are fired
- Twitch authorization URL request events: requests from a client to get a valid Twitch oAuth redirect URL
- Twitch authentication events: a message containing Twitch authentication request parameters to be used to authenticate with Twitch event servers
It’s also the server’s job to manage event subscriber lists. As mentioned, clients can send a subscribe request to the server along with event types. When this happens, the server records the client’s unique socket UUID to a dynamic list for the requested event type and sends the current state relevant to the event back to the client. Then, when the server receives messages that need to be broadcast, or decides to broadcast one itself, it will notify all clients contained within the relevant subscriber list. The subscription system’s purpose is to abstract the concept of specific client ‘types’ so that the server doesn’t need to care what a specific client’s purpose is, only that it wants to know about specific events. Clients can then manipulate the data (or ignore it) as they wish.
As I mentioned earlier, the server is also responsible for file IO. Upon initialization, the server will check all known data files to see if information exists within them. It accesses each file with a unique file key string defined in a common helper. If a file exists, it will pull the current data into memory in order to limit the number of disk reads that occur. On the other hand, data updates are always written to both memory and disk. While not ideal, this is done to cover the event that the server fails or is accidentally closed by the streamer. Unfortunately, server destruction events aren’t extremely reliable in NodeJS servers, so we can’t depend on them to ensure data is written in the event of a server closure. Luckily, at most we are writing a few small structs of data each second, so it’s not extremely strenuous.
Lastly, the server handles the APIs related to Twitch and Extra-Life. For Twitch, the server handles authentication using a registered application ID (already generated). Twitch also uses a subscription socket-based system to subscribe to events. The server subscribes to events relevant to donation tracking (subscriptions, cheers (bits), and follows) as well as Twitch’s IRC chat event server. Extra-Life on the other hand doesn’t have an event-based subscription system, so instead the server will perform manual calls every 5 seconds to the API to check if the state has changed since our last check. First, it looks at the total donation amount and compares it to the last known. If the amount has changed, the donor list is pulled and recent donations are broadcast to subscribers.
Organization
The majority of core server functionality is implemented in Server/configServer.js. This file contains the aforementioned server setup, socket connections, subscription management, and event management functionality.
The server also relies on several helpers which include:
- file IO helpers, contained within Server/serverFileHelpers.js
- a common interface helper containing message type definitions and data structure definitions, located in Interface/configInterface.js
- donation helpers that assist with donation message generation and sending donation messages to the Twitch chat server, located in Helpers/donationHelpers.js
- Twitch authentication helpers that help facilitate proper oAuth connections to Twitch event servers, located in Server/serverTwitchHelpers.js
- Twitch eventsub server event helpers that perform connections to the Twitch eventsub server and handle incoming messages, located in Server/twitchEventSub.js
- Twitch chat server event helpers that perform connections to the Twitch chat server and handle incoming and outgoing IRC messages, located in Server/twitchChat.js. These helpers also depend on the twitch provided IRC parser, located in Server/twitchIRCParser.js.
- Extra-Life API helpers that help facilitate calls to the Extra-Life API endpoints, located in Server/extraLifeHelpers.js
- User config helpers that retrieve information that is manually entered by the user upon application setup, located in Server/userConfigHelpers.js
All aspects of the project are organized into modules to allow for more granular import and exports. The server is no exception to this rule, living within its own module and importing helper functionality as needed.
External Packages
The server relies on several open source NodeJS compatible packages:
- Express: for serving client-side files
- WS for websocket server and connections
- UUIDv4 to assign unique ids to client sockets to enable subscriber registration and management
- FS for file system management
Interface
The application contains a common interface layer that both the client and server use.
Functionality
It provides functionality and definitions that both the server and client require. This includes message and configuration data structure definitions, and a base interface class definition. The base interface class (IConfig) can be inherited to provide child objects with the ability to connect to the server, subscribe to events, and send messages.
All socket connections are managed through built-in websocket functionality found in most modern browsers (Firefox, Chrome, Edge, and the built-in browser of the streamer’s stream tool).
Organization
The common interface is all contained within a single file: Interface/configInterface.js. This file is set up as a module within the build so that it can export its data definitions to be imported by other modules.
Client
The client-side portion of the Twitch plug-in is separated into four parts: the timer page, the configuration page, the donation stats page, and the donation notifications page. Each of these components are represented by their own CSS-formatted HTML pages whose functionality are driven by JS modules instantiated with each page instance.
Functionality
Each page serves a specific purpose and can have a mix of taking input from the user and displaying output. Specifically, the config page takes inputs from the user to affect the timer and donation configurations. The timer page is purely visual, displaying the current timer state. The donation stats page also just displays data, showing the most recent donation as well as the top 3 donations. Lastly, the donation notification page is an event-driven page that only displays content when certain donation events trigger. Otherwise, it is completely transparent. These visual pages are all intended to be used as browser sources within the streamer’s stream tool.
The JS modules are subclasses of the IConfig interface class and, using the helper functions provided by the IConfig class, handle the socket connection and sending of messages for their page. They also use these helpers to handle notifying the server of their desire to be subscribed to certain event types and handle incoming messages that are sent by the server for those events. There is no obligation for the client to handle an incoming message from the server.
Organization
All of the client-side files are stored within the project’s Frontend folder and are further divided based on their file types (css, html, img, js). As mentioned, each client page has its own JavaScript, HTML, and CSS pages associated with it. Images can be shared between pages if necessary.
Game
As stated at the beginning of this design writeup, the following game design will be extremely brief given that this is a stretch-goal. This is being done to ensure time is being spent on the primary goal of this project. The project’s client agrees that time is better spent prototyping and implementing the plug-in rather than designing the game. If the game is pursued later in this project, additional design can be fleshed out if necessary.
Mechanics
The game will have very simple mechanics. The idea is that when a hype-train event occurs in chat, the game will fade into its associated browser source, music will play, and characters representing the users in chat will appear beneath a static image of a ‘boss’. The players will use chat commands to attack the boss in different ways, trying to defeat it before the time runs out. For more specifics on game mechanics, see the requirements document.
Architecture
The game will be set up in a very similar way to the Twitch plug-in in that it will use a server-authoritative system, with the browser front-end performing simulation and display depending on what the server has provided it for current state. In fact, the game server will likely just be an additional module attached to the plug-in server. The idea behind this is making it so the user only needs to launch one server and that we can piggyback on existing server functionality with web sockets. Technically, for the game on its own, a server isn’t required. The game library, Phaser, lives completely within the browser. That said, it will be easier to use existing server functionality including connections with twitch, processing donations, and managing users than it would be recreating this functionality in the browser just for the game.
Server
The server will perform several jobs for the game including viewer interaction and boss simulation.
First, it will establish an additional connection with the Twitch event server to monitor chat actions. It will parse the chat and look for any commands that start with ‘!’ (the standard Twitch command symbol). If it finds commands relevant to the game, it will record the user’s name and action type. The server will then process this information and deliver it to the client in order to display on-screen text showing the action.
Second, the server will manage the boss’s state change between different ‘modes’. These modes will determine what actions the viewers should take in chat. Each state will have a percentage chance associated with it. Using these chances, the game will pick the next state at random with the only caveat that it must be a different state than the current one. This will help prevent situations where the boss stays in one state for a very long time due to the nature of randomness. The server will also manage the boss’s health, adjusting it for chat actions or donations that happen during gameplay. Management of the boss’s attacks and viewers that are killed by them will also be done server-side.
Lastly, it will push the current state to the front-end browser source so that it can update the current display shown in stream. This will include the boss’s health, the users that are still alive, the time remaining, and any events such as user commands and donations that are happening.
Client
The client will implement the ‘actual’ game excluding the state data handled on the server. This involves displaying the active viewers based on the list sent by the server, showing the boss image, updating the health bar display, and updating the timer display.
Viewers will be represented at the base of the screen by a random assortment of 2d avatars. Each avatar will be associated with a single viewer, displaying their name. The avatars will move around the bottom of the screen at random intervals to give the game a greater sense of movement. When a viewer enters a command, their avatar will jump and a symbol representing their action will appear above their head. As players die, they will play a quick death animation and disappear from the view.
The timer will be a simple text timer at the top-right corner of the screen and the health bar will be a simple filled rectangle at the top left.
Phaser
The client will use Phaser to manage the front-end side of gameplay. This includes animation, drawing 2d images to screen, and any physics simulation if required. Phaser is an HTML5 based library, meaning that it lives completely within the browser and doesn’t require any server-side functionality aside from what I have determined will be processed on the server.
Implementation
As detailed in the development model document, this project was initially divided into seven sprints, spanning a total of twelve weeks. It was divided into two milestones of four and eight weeks respectively.
The first milestone was divided into two two-week sprints and had a goal of completing planning documentation as well as the plug-in tracer prototype. This milestone was moderately successful, with some prototype work overhanging into the production milestone. This overhang continued to have an impact to the project timeline all the way until the final sprint. The client reviewed the prototype once completed and was happy with the general user interface and approach to that point.
The second milestone spanned 8 weeks and was divided into three two-week production sprints and two one-week hardening sprints. The goal of this milestone was to take the Twitch plug-in from prototype to completion while also assessing the viability of the Twitch game stretch goal. Unfortunately, by the time the Twitch plug-in development was completed, there was no remaining time for the stretch-goal. The client and I may still agree to work on this in the future, but it will be excluded from the scope of this specific project.
It is important to note what the ‘original estimate’ timeline represents in these sprint reports. Although the actual project planned completion date was September 9th, this ‘original estimate’ timeline was based on my initial velocity estimates compared to my initial high-level estimates. Based on these estimates, my goal was to complete the project on August 23rd. Essentially this line is just a data point to learn from and improve my estimation abilities, not actually a well-informed timeline to measure against.
Each of the following sprint reports was completed within a day or two of a sprint ending. The goal of these reports was to analyze progress so far, measure velocity, and roughly predict when I would complete the project.
Each report contains the following information:
- The Epics that were pulled in, including their initial high-level estimates (noted as HLE going forward), a post-task breakdown revised estimate, and how much overhang was remaining at the end of the sprint.
- The sprint’s actual velocity in points.
- A timeline predicting the project completion date based on updated estimates and velocity, compared to the original planned completion date.
- A summary of what happened in the sprint, the client’s review feedback, the remaining overhang items and impacts to the project.
Sprint 1 (Prototyping): (June 18 – July 1)
This is the first prototype sprint of the project. Given that this was the first sprint of the project, I just pulled in the number of tasks I thought I could get through in a two-week period. My estimates were fairly accurate with only a small amount of overhang (detailed below).
Two epics were tackled in this sprint: the donations config (which includes set up of a lot of foundational server-side logic) and the donation timer impacts, which is one of the systems that relies on the configuration page being done.
Start of sprint task breakdowns kept overall points in line with original HLEs. The donations config epic tasks exceeded the original epic’s HLE by 2 points, but the tasks came in slightly under for the donation timer impacts epic.
Between overhang and remaining high-level estimates, there is 29 points remaining in the prototype. My current velocity is 18 points per sprint, so I expect the prototype will carry into the third sprint. Prototyping was intended to be completed during the first two sprints of the project, so this is slightly later than originally anticipated and will delay production. Overall, I am trending about two weeks behind where I wanted to be.
There wasn’t much to review with the client this sprint, but we discussed progress and reviewed upcoming priorities and challenges.
Epics in Sprint and Task Breakdowns
Epic: Donations config (prototype) | HLE | ||||||
Pre-sprint HLE | 13 | ||||||
Start of sprint HLE (post-task breakdown) | 15 | ||||||
End of sprint remaining HLE | 2 | ||||||
Task Breakdown | Plan Estimate | Overhang | |||||
Server: Setup socket server | 5 | – | |||||
Server: Setup message system | 3 | – | |||||
Server: Setup file IO | 2 | – | |||||
Server: Setup socket subscription management | 3 | 2 | |||||
Front-end: Setup configuration page HTML form and CSS | 1 | – | |||||
Front-end: Define IConfig class with server helpers | 1 | – | |||||
Epic: Donation timer impacts (prototype) | HLE | ||||||
Pre-sprint HLE | 8 | ||||||
Start of sprint HLE (post-task breakdown) | 6 | ||||||
End of sprint remaining HLE | 1 | ||||||
Task Breakdown | Plan Estimate | Overhang | |||||
Server: Setup timer and donation config data management | 3 | – | |||||
Front-end: Create config class with form submit handlers for donation and timer fields | 2 | – | |||||
Front-end: Add fake donation debug buttons to config | 1 | 1 | |||||
Overhang
A total of 3 points of overhang will need to be carried over into next sprint.
- Server: Setup socket subscription management (2): The broadcasting system that the server uses to send events to clients needs to be finished.
- Front-end: Add fake donation debug buttons to config (1): this work hasn’t been started yet.
Velocity
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
Avg (non-hardening): | 18 |
Remaining Timeline
Sprint 2 (Prototyping): (July 2 – July 15)
This is the second prototype sprint of the project. When pulling tasks into the sprint, I still based this on what I thought I could accomplish, to see how close my velocity would land to last sprint. I was able to complete slightly more than last sprint but was clearly too aggressive with what I brought into the sprint given the amount of overhang.
Four epics were tackled in this sprint. The overhang from the donations config and the donation timer impacts was completed. The countdown timer and donation stats tracker were also worked on – meaning all prototype-related epics are now complete or in progress.
Start of sprint task breakdowns decreased the overall point estimates slightly. The stream countdown timer epic tasks ended up being one point less than the original epic’s HLE, while the donation stats tracker estimates stayed the same.
Due to overhang, there is 8 points remaining in the prototype. My velocity for this sprint was 20, making my average velocity 19 points per sprint. This means I should easily be able to complete the remaining prototype work next sprint but will end up pushing out production work by an equal amount. Overall however, I was able to pull in the estimated final date by a few days due to the higher velocity this sprint.
Excluding the remaining overhang, I was able to review most of the prototype features with the client during this sprint. There were a few suggestions and clarifications for front-end visuals and how we will polish things as we bring them across the finish line. No major changes were required.
Epics in Sprint and Task Breakdowns
Epic: Donations config (prototype) | HLE | |
Pre-sprint HLE | 2 | |
Start of sprint HLE (post-task breakdown) | 2 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Server: Setup socket subscription management | 2 | – |
Epic: Donation timer impacts (prototype) | HLE | |
Pre-sprint HLE | 1 | |
Start of sprint HLE (post-task breakdown) | 1 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Front-end: Add fake donation debug buttons to config | 1 | – |
Epic: Stream countdown timer (prototype) | HLE | |
Pre-sprint HLE | 13 | |
Start of sprint HLE (post-task breakdown) | 12 | |
End of sprint remaining HLE | 5 | |
Task Breakdown | Plan Estimate | Overhang |
Server: Handle timer update messages | 4 | – |
Server: Handle timer start/stop messages | 3 | 3 |
Front-end: Setup timer page HTML and CSS | 1 | – |
Front-end: Create timer class with countdown logic and start/stop functions | 3 | 1 |
Front-end: Add timer start/stop buttons to config page and hook-up | 1 | 1 |
Epic: Donation stats tracker (prototype) | HLE | |||
Pre-sprint HLE | 13 | |||
Start of sprint HLE (post-task breakdown) | 13 | |||
End of sprint remaining HLE | 3 | |||
Task Breakdown | Plan Estimate | Overhang | ||
Server: Handle donation update messages | 5 | 1 | ||
Server: Setup donation message creator | 2 | 2 | ||
Server: Setup server-side donation handlers | 3 | – | ||
Front-end: Setup tracker page HTML and CSS | 1 | – | ||
Front-end: Create tracker class with logic to display proper text based on donation type | 2 | – | ||
Overhang
A total of 8 points of overhang will need to be carried over into next sprint.
- Server: Handle timer start/stop messages (3): This work hasn’t been started yet.
- Front-end: Create timer class with countdown logic and start/stop functions (1): didn’t finish the start/stop timer portion of this yet
- Front-end: Add timer start/stop buttons to config page and hook-up (1): This work hasn’t been started yet.
- Server: Handle donation update messages (1): Still have a bit of cleanup to do for these messages
- Server: Setup donation message creator (2): This work hasn’t been started yet.
Velocity
Velocity | Points Completed |
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
2: Prototyping (July 2 – July 15) | 20 |
Avg (non-hardening): | 19 |
Remaining Timeline
Sprint 3 (Production): (July 16 – July 29)
This is the first production sprint of the project. However, the first portion of this sprint was still dedicated to wrapping up prototype work. When pulling tasks into the sprint, I based the point target on my average so far (19 points). However, I was able to wrap up my all 19 points of sprint items before the end of sprint, so I ended up pulling in one more item from the donation config epic.
Six epics were worked on in this sprint. The overhang from the prototyping work was all completed. The production tasks for the stream countdown timer, donation timer impacts, and donation stats tracker epics were all completed. The donation config epic still has tasks remaining (more info below).
Start of sprint task breakdowns increased the overall point estimates. The donation config epic originally had an estimated 5 points of work, however once I performed the task breakdown it was much higher (14 points). Of those 14 points, I was able to complete 6 this sprint (including the extra tasks I pulled in), so 8 will be remaining for next sprint. The remaining epic estimates were accurate after task breakdowns. This was unsurprising as they were mostly small epics or overhang.
There is no overhang from this sprint. My velocity for this sprint was 20, meaning my average velocity remains at 19 points per sprint. Although I was able to work ahead this sprint, this was largely offset by the increase in points for the donation config epic. As a result, the estimated project completion date has now been pushed out to September 18th. The reason this is such a large date increase for a small number of points is because we are now carrying production work through the second hardening sprint, which originally would have had 0 planned burndown.
Early in the sprint, the client and I performed the final review of the prototype and agreed that I could formally proceed into production work. We reviewed the production priorities for this sprint and next sprint. Some tasks were moved around but without any material impact.
Epics in Sprint and Task Breakdowns
Epic: Stream countdown timer (prototype) | HLE | |||
Pre-sprint HLE | 5 | |||
Start of sprint HLE (post-task breakdown) | 5 | |||
End of sprint remaining HLE | 0 | |||
Task Breakdown | Plan Estimate | Overhang | ||
Server: Handle timer start/stop messages | 3 | – | ||
Front-end: Create timer class with countdown logic and start/stop functions | 1 | – | ||
Front-end: Add timer start/stop buttons to config page and hook-up | 1 | – | ||
Epic: Donation stats tracker (prototype) | HLE | |
Pre-sprint HLE | 3 | |
Start of sprint HLE (post-task breakdown) | 3 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Server: Handle donation update messages | 1 | – |
Server: Setup donation message creator | 2 | – |
Epic: Stream countdown timer (production) | HLE | |
Pre-sprint HLE | 2 | |
Start of sprint HLE (post-task breakdown) | 2 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Front-end: Apply Extra-Life branding and fonts to timer | 1 | – |
Front-end: Review Look with user and sign-off | 1 | – |
Epic: Donation timer impacts (production) | HLE | |
Pre-sprint HLE | 2 | |
Start of sprint HLE (post-task breakdown) | 2 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Server: Setup message parsing from Twitch and Extra-Life events to determine amount of time added | 2 | – |
Epic: Donations config (production) | HLE | |
Pre-sprint HLE | 5 | |
Start of sprint HLE (post-task breakdown) | 6 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Front-end: Handle Twitch oAuth redirect and send data to server | 2 | – |
Server: Handle Twitch oAuth code and token requests | 3 | – |
Server: Handle Twitch oAuth messages, reconnects and keep-alives | 1 | – |
Epic: Donation stats tracker (production) | HLE | |
Pre-sprint HLE | 2 | |
Start of sprint HLE (post-task breakdown) | 2 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Front-end: Apply Extra-Life branding and fonts to timer | 1 | – |
Front-end: Review Look with user and sign-off | 1 | – |
Overhang
No overhang will be carried into next sprint.
Velocity
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
2: Prototyping (July 2 – July 15) | 20 |
3: Production (July 16 – July 29) | 20 |
Avg (non-hardening): | 19 |
Remaining Timeline
Sprint 4 (Production): (July 30 – Aug 12)
This is the second production sprint of the project. When pulling tasks into the sprint, I based the point target on my average so far (19 points). This was accurate to the amount of work I was able to complete during this sprint.
Two epics were worked on in this sprint. The remaining tasks for the donations config production work were completed, and work was started on the donation announcements epic.
Start of sprint task breakdowns decreased the overall point estimates. The donation announcements epic ended up being smaller (16 points from 21) after task breakdown. 11 of these points were completed this sprint, and 5 are scheduled for the next sprint.
There is no overhang from this sprint. My velocity for this sprint was 19, meaning my average velocity remains at 19 points per sprint. Due to the decrease in points for the donation announcements epic, the estimated project completion date has now been pulled in to September 14th.
The next sprint is one of two hardening sprints scheduled for the project. During this hardening time, I will be aiming to address the following:
- Complete the donation announcements tasks
- Perform another user review on functionality so far (including the donation announcements functionality completed above)
- Address the following known bugs:
- Issue with socket server disconnecting from Twitch event sub server due to thinking the keep-alive messages have stopped (when they haven’t)
- Issue with timer automatically starting when timer page is loaded
- Lastly, I will aim to update existing documentation so far, and complete a first pass on the test plan for what has been implemented
The client and I reviewed progress so far, with only a couple small notes from the client to clarify typical Twitch authentication flows they have experienced with other applications. We also discussed my current concerns with the projected timeline landing mid-September. The client is ok with this new timeline, but if it ends up extending beyond October 1st, we will need to look at cutting some scope to have it done before then. We reviewed the goals for the upcoming hardening sprint and agreed to perform another user review during that time.
Epics in Sprint and Task Breakdowns
Epic: Donations config (production) | HLE | |
Pre-sprint HLE | 8 | |
Start of sprint HLE (post-task breakdown) | 8 | |
End of sprint remaining HLE | 0 | |
Task Breakdown | Plan Estimate | Overhang |
Server: Store user information in an input file instead of hardcoded (app client id, client secret, broadcaster id) | 2 | – |
Sever: Handle Event Sub notification subscriptions and message handling | 3 | – |
Server: Handle Extra-Life API calls and data processing | 2 | – |
Server: Connect Twitch Event Sub and Extra-Life API events with existing server infrastructure to properly trigger timer and donation config updates | 1 | – |
Epic: Donation announcements (production) | HLE | |||
Pre-sprint HLE | 16 | |||
Start of sprint HLE (post-task breakdown) | 11 | |||
End of sprint remaining HLE | 0 | |||
Task Breakdown | Plan Estimate | Overhang | ||
Server: repurpose Twitch event sub oAuth token for Twitch IRC chat server | 2 | – | ||
Server: handle mandatory chat server messages that need to be sent to server (custom pong, commands, nickname, join requests) | 5 | – | ||
Server: handle incoming chat server IRC messages | 3 | – | ||
Server: integrate Twitch-provided IRC message parser | 1 | – | ||
Overhang
No overhang will be carried into next sprint.
Velocity
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
2: Prototyping (July 2 – July 15) | 20 |
3: Production (July 16 – July 29) | 20 |
4: Production (July 30 – Aug 12) | 19 |
Avg (non-hardening): | 19 |
Remaining Timeline
Sprint 5 (Hardening): (Aug 13 – Aug 19)
This is the first hardening sprint of the project. This sprint isn’t concerned with velocity, but is instead used to address bugs, check-in with the user, update documentation, and complete tasks if there is time remaining.
Specifically, the goals of this hardening sprint were to:
- Complete the donation announcements tasks.
- Perform another user review on functionality so far (including the donation announcements functionality completed above).
- Address the following known bugs:
- Issue with socket server disconnecting from Twitch event sub server due to thinking the keep-alive messages have stopped (when they haven’t).
- Issue with timer automatically starting when timer page is loaded.
- Lastly, I will aim to update existing documentation so far, and complete a first pass on the test plan for what has been implemented so far.
All of the above items were accomplished during this sprint. Hardening sprints aren’t added to overall velocity, so the project velocity remains at 19. Due to being able to burn down some tasks in this hardening sprint, I was also able to pull in the dates for the plug-in to September 3rd. Again, the reason why burning down these points had such a big impact is due to now landing production work before the second hardening sprint.
The client and I did another full walkthrough of all the completed features so far. They sat down at the development computer to use the plug-in as they would expect it to work (with obvious caveats where functionality doesn’t fully exist yet). No major changes came out of this, and the client and I feel we are on the same page with where the next couple of weeks will proceed. We discussed my current concerns about the complexity of the donation effects feature and re-iterated that if the timeline stretches beyond October 1st, we will need to cut scope.
Epics in Sprint and Task Breakdowns
Epic: Donation announcements (production) | HLE | |||
Pre-sprint HLE | 5 | |||
Start of sprint HLE (post-task breakdown) | 5 | |||
End of sprint remaining HLE | 0 | |||
Task Breakdown | Plan Estimate | Overhang | ||
Server: hook donation message generator into chat message sender | 5 | – | ||
Overhang
No overhang will be carried into next sprint.
Velocity
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
2: Prototyping (July 2 – July 15) | 20 |
3: Production (July 16 – July 29) | 20 |
4: Production (July 30 – Aug 12) | 19 |
5: Hardening (Aug 13 – Aug 19) | 5 |
Avg (non-hardening): | 19 |
Remaining Timeline
Sprint 6 (Production): (Aug 20 – Sept 2*)
This is the last planned production sprint of the project. Initially my plan was to pull in 19 points of work, given my average velocity up to this point, meaning that approximately 2 points of work would carry over into the final hardening sprint. However, the basic donation effects epic ended up being far less work than anticipated (see below). As a result, I was able to complete this production work and my planned hardening tasks within the first week of this sprint. This makes the effective end date of this sprint (and project) August 26th.
One epic, the basic donation effects, was worked on in this sprint and all tasks were completed.
Start of sprint task breakdowns significantly reduced the overall point estimates. The basic donation effects epic ended up being much smaller (6 points from 21) after task breakdown.
As I was able to complete the production work quickly, I was also able to complete my final hardening sprint items:
- Perform another user review on final functionality (including the donation announcements functionality completed above)
- Perform a ‘dry-run’ stream with the user in order to confirm things are working as expected in a live setting
- Complete project documentation (final updates to design and implementation docs), as well as a full test-plan review
- Lastly, I was able to address the following known bugs:
- Notifications override each other when multiple donations occur during the notification playtime
A note regarding the game stretch-goal: Although the plug-in has been completed ‘earlier’ than the original estimated final project date, the remaining two weeks of project time will not be enough to implement the game. Based on a high-level estimation of the game, it will take about as long as the plug-in. This may be something the client and I explore at a later time, but for now we have agreed to defer this part of the project.
The client was very happy that the donation effects/notifications feature was easier than expected and that I was able to complete the plug-in before the beginning of September.
We sat down together and worked through the requirements checklist and test plan to verify that everything was working as expected. I informed her of the results of the longevity stress test, and we also had a chance to perform a developer-local dry run stream where she streamed and I ran the plug-in on my developer computer. A couple of donations came in during this stream, and everything appeared to work as expected.
The client also expressed that they would like to perform the live test a bit later than originally planned in order to line up with her Extra-Life campaigning a bit better. We agreed that, given the success of the developer-local test, deferring this to a later date would be low risk.
Lastly, we also discussed the game stretch-goal and my high-level estimates. Given how large the project would likely be, we agreed this would be deferred to when we both have time again to collaborate on it.
Epics in Sprint and Task Breakdowns
Epic: Basic Donation Effects (production) | HLE | |||
Pre-sprint HLE | 21 | |||
Start of sprint HLE (post-task breakdown) | 6 | |||
End of sprint remaining HLE | 0 | |||
Task Breakdown | Plan Estimate | Overhang | ||
Front-end: Setup notifications page HTML and CSS | 1 | – | ||
Front-end: Create notifications class with movie player logic | 2 | – | ||
Front-end: Setup transitions logic to display text at different video locations | 2 | – | ||
Server: Edit donation notifications to include donation message | 1 | – | ||
Overhang
No overhang will be carried into next sprint.
Velocity
Sprint | Points Completed |
1: Prototyping (June 18 – July 1) | 18 |
2: Prototyping (July 2 – July 15) | 20 |
3: Production (July 16 – July 29) | 20 |
4: Production (July 30 – Aug 12) | 19 |
5: Hardening (Aug 13 – Aug 19) | 5 |
6: Production (Aug 20 – Sept 2*) | 6 |
Avg (non-hardening): | 19 |
Test Plan
Testing of the Twitch Plug-in is divided into four parts. First, a requirements testing checklist which is detailed in this document. Second, a longevity stress test where the plug-in is run for a long period of time. Third, a ‘developer-local’ dry run where the plug-in is used with live data but not displayed to viewers. Lastly, a live test that will occur prior to the official charity stream date.
Requirements Testing Checklist
This checklist defines tests to verify that all user and technical requirements have been met. The test cases listed per requirement were created as a collaboration between myself and the client. Test plans were run periodically throughout the project, but a full pass was run during the first hardening sprint and again at the end of the project. In addition to running the checklist on my own, I sat down with the client and ran through the user requirements test list with them to confirm everything was working as they expected.
A few requirements changed during the project (reflected in the updated requirements document). These adjustments have also been noted in the test plan.
User Requirements
ReqId | Requirements | Test Actions | Status | Notes |
1 | Stream countdown timer | |||
1.1 | On-screen widget that is hideable by viewers | N/A | N/A | This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
1.2 | Displays Hours, minutes, seconds left in stream | – Verify time is shown in hours, minutes, seconds – Verify that when timer is counting down, it counts down in seconds – Verify that minutes and hours are decremented at appropriate times as timer updates |
Success | |
1.3 | Updatable in real-time (see donation timer impacts) | – Verify that timer is updated for each donation type: – Twitch subscription – Twitch follow – Twitch cheer (bits) – Extra-life donation – Verify that in each of the above cases, the timer is updated by the amount of time the user has input into the config page |
Success | |
1.4 | Timer is pauseable by streamer | – Verify that the timer pauses and starts when the pause and start timer buttons are pressed on the config page – Verify that pressing the pause button while paused, or the start button while the timer is running doesn’t affect the timer |
Success | |
2 | Donation timer impacts | |||
2.1 | Donations to twitch in the form of subscriptions, bits, follows increase remaining time of stream | – Verify that timer is updated for each donation type: – Twitch subscription – Twitch follow – Twitch cheer (bits) – Verify that in each of the above cases, the timer is updated by the amount of time the user has input into the config page |
Success | |
2.2 | Donations to extra-life site increase remaining time of stream | – Verify that timer is updated for each donation type: – Extra-life donation – Verify that in each of the above cases, the timer is updated by the amount of time the user has input into the config page |
Success | |
2.3 | Timer is updated within 1 minute of donation being processed | – Verify that the time between a donation being triggered, being processed by the server, and reflected in timer is less than 1 minute | Success | Testing showed that the update occurs between 1 – 2 seconds in the case of Twitch events, and up to 20 seconds in the case of Extra-Life events |
3 | Donations config | |||
3.1 | Streamer can access configuration window outside of stream | – Verify that config page can be accessed outside of OBS within browser of choice | Success | |
3.2 | Streamer can set stream time increases by donation type – Dollars for extra-life donations – Per Subscription – Per bit – Per follow |
– Verify config page form contains fields for all donation types: – Twitch subscription – Twitch follow – Twitch cheer (bits) – Extra-life donation – Verify that these numbers can be saved to config and are reflected in the timer when new donations occur |
Success | |
3.3 | Donation configs are entered in minutes seconds | – Verify donation form fields treat inputs as seconds and are reflected as such when donations occur | Success | After testing the interface with the user, it was determined that these numbers should be in seconds instead of minutes |
3.4 | Streamer can enter time remaining manually | – Verify there are fields for hours, minutes, and seconds on the config page form – Verify that these fields are reflected in the timer after the user clicks ‘update config’ while timer is paused and while timer is running |
Success | |
4 | Donation stats tracker | |||
4.1 | Displays as a dropdown within timer widget (hidden by default) | N/A | N/A | This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
4.2 | Viewers can press show/hide button within widget to hide stats while still displaying timer | N/A | N/A | This is not possible without a Twitch-integrated extension, which was determined not to be the ideal approach for this project |
4.3 | Displays the most recent donation, who donated, the amount (and type) of donation, and time added | – Verify most recent donation is reflected for all donation types – Verify the amounts and types reflect the donations that occur – Verify that the list shows the top 3 donors – Verify the top donor list updates as new donations come in – List should reorganize properly based on where the donation exists within the leaderboard – List shouldn’t change if the recent donation is less than the top 3 |
Success | |
4.4 | Displays the top 3 donations since streamer-defined date from the streams where this plug-in was used | – Verify that the top 3 donations from all active streams that this plug-in is used are shown | Success | After testing with the user, they decided they would like the top 3 donations to always persist for any streams that this plug-in is run, regardless of date. |
5 | Donation Announcements | |||
5.1 | Post chat message when donations occur (who, type, amount, time added) | – Verify a message is posted to Twitch chat using the streamer’s username – Verify message includes: – Who donated – Donation amount – Donation type – Time added to stream |
Success | |
5.2 | Streamer can configure custom message to follow the above information in chat | – Verify message that user’s custom message on the config page is displayed in chat message following the donation information. | Success | |
6 | Basic donation effects | |||
6.1 | Display an on-screen video using ‘Pingu mozart meme’ – Displays amount donated in ‘happy’ part of video – Displays amount of time added in ‘terror’ part of video |
– Verify video isn’t shown while notification is inactive – Verify video plays from start when a new notification occurs – Verify video disappears after notification ends – Verify that donation text displays in first part of video – Verify that time added text dispalys in second part of video |
Success | |
7 | User Donation Debug Tools | This was an additional request from the user after initial testing. The purpose of this feature is to test how everything interacts with the streamer’s stream layout prior to going live. | ||
7.1 | User can trigger ‘fake’ donations to see notification and verify timer is working correctly | – Verify config page has fields and buttons that allow user to trigger fake donations | Success | |
7.2 | Donations should be of any valid type with customizable amounts in the cases of cheers (bits) and extra-life donations (dollars) | – Verify there are amount fields for bits and extra-life donations and these numbers are reflected when donations are triggered – Verify that there is a button for follows and subscriptions without amount fields |
Success | |
7.3 | User should be able to enter a fake donor name | – Verify donor field name exists and that this is represented in any fake donations that trigger | Success |
Technical Requirements
ReqId | Requirements | Test Actions | Status | Notes |
1 | Config Page | |||
1.1 | Save/Load | – Validate donationConfigStore.json and timerConfigStore.json are updated when ‘update config’ button is pressed – donationConfigStore.json should contain all time values set per donation types – timerConfigStore.json should contain the remaining stream time |
Success | |
1.2 | Event subscriptions | – Validate config page receives timer config and donation config update messages – this should be reflected after initially launching the page as all existing values should populate |
Success | |
1.3 | Visuals | – Page is not viewer-facing, so this should value functionality over aesthetics – Validate simple page with clear form and buttons |
Success | |
1.4 | oAuth redirect | – Page should contain a link for user to validate with Twitch – This should redirect to twitch oauth page if user hasn’t already validated – After authenticating, should redirect back to config page |
Success | |
2 | Timer Page | |||
2.1 | Save/Load | – Validate timerConfigStore.json is updated as timer ticks | Success | |
2.2 | Event subscriptions | – Validate that timer receives pause/start events | Success | |
2.3 | Visuals | – Validate that timer uses official Extra-Life branding and design is signed off by user | Success | |
3 | Stats Page | |||
3.1 | Save/Load | – Validate donationStatsStore.json is updated with recent donor and top 3 donors as donations occur | Success | |
3.2 | Event subscriptions | – Validate stats page receives all donation stats update events | Success | |
3.3 | Visuals | – Validate that stats page uses official Extra-Life branding and design is signed off by user | Success | |
4 | Notification Page | |||
4.1 | Save/Load | N/A | N/A | Notifications require no save/load functionality |
4.4 | Event subscriptions | – Validate notification page receives all donation events | Success | |
4.5 | Visuals | – Validate that stats page uses official Extra-Life branding and design is signed off by user | Success | |
5 | Server | |||
5.1 | Twitch Event Sub connections | – Validate app secret is input in user config file and not stored in source code – Validate server uses proper Twitch-approved oauth techniques to authenticate with event sub server – Validate that connection is successfully established between event sub and server. – Validate that server connection is kept alive and maintained for at least 24 hours – Validate that server handles reconnection requests – Validate that follow, subscribe, subscription.message, and cheer events are all received from event sub server |
Success | A 48-hour test was run, connection was maintained during this time. Reconnection and re-auth attempts were successful during this time. |
5.2 | Twitch Chat connections | – Validate broadcaster information is contained in input file and not stored in source code – Validate server uses proper Twitch-approved oauth techniques to authenticate with chat server – Validate that connection is successfully established between chat server and server. – Validate that server connection is kept alive and maintained for at least 24 hours – Validate that server handles reconnection requests |
Success | A 48-hour test was run, connection was maintained during this time. Reconnection and re-auth attempts were successful during this time. |
5.3 | Extra-life API calls | – Validate that extra-life API is polled every 5 seconds – Validate that donation information is retrieved and parsed correctly, identifying new extra-life donations |
Success | |
5.4 | Subscription maintenance and notifications | – Validate server handles incoming notification subscription requests from client-side pages – Validate server stores these subscriptions – Validate subscriptions are removed when a client socket connection is closed – Validate that current known information is broadcasted to new subscribers – Validate Notifications are broadcasted to all applicable subscribing clients |
Success | |
5.5 | Client connection management | – Validate that clients are able to establish a socket connection with server within 1 second of launching – Validate a unique UUID is assigned to each client socket connection |
Success | |
5.6 | Save/Load | – Validate that server is able to write to and retrieve data from all storage files – donationConfigStore.json – timerConfigStore.json – userConfig.json – Validate that data is corrected stringified and parsed by JSON upon storage and retrieval – Validate that server precaches current data stored in JSON files (if existing) upon server launch |
Success | |
5.7 | Message handling | – Validate that server handles the following client message types: – updateTimerConfig – postTimerUpdate – updateDonationConfig – subscribe – startTimer, pauseTimer – twitchSub, twitchFollow, twitchCheer, elDonation – requestTwitchAuthUrl – authenticateTwitch |
Success | |
5.8 | Debug options for Twitch | – Validate that a debug flag is available within serverTwitchHelpers.js that will connect to Twitch CLI test servers instead of prod servers – Validate that messages can be properly sent and received from Twitch CLI test server |
Success | |
6 | Technology – General | |||
6.1 | Must abide by allowed Twitch technologies – HTML, CSS, JS for extension code – Provided twitch API |
N/A | N/A | This is no longer a requirement, as the client and I opted for a local plug-in solution instead of an integrated extension |
6.2 | Must abide by API limits put in place by Extra-Life and Twitch (ie. Num calls/minute) | – Validate we only call the extra-life API a maximum of once every 15 seconds, with an additional call during that time if changes are detected – Validate there is a maximum of 3 socket connections with the Twitch event sub server, with a maximum of 100 subscriptions per socket |
Success | These limits are based on the DonorDrive API guidelines for Extra-Life (https://github.com/DonorDrive/PublicAPI) and the Twitch Event Sub guidelines (https://dev.twitch.tv/docs/eventsub/handling-websocket-events/#subscription-limits) |
6.3 | Must abide by Twitch extension policies listed here https://dev.twitch.tv/docs/extensions/guidelines-and-policies/ | N/A | N/A | This is no longer a requirement, as the client and I opted for a local plug-in solution instead of an integrated extension |
7 | Security | |||
7.1 | Must not expose any sensitive information of streamer within extensions (IP address, name, etc.) | – Validate that app client-id and secret are stored in a user-input file instead of in code – Validate that no broadcaster or streamer information is hardcoded |
Success |
Longevity Stress Test
I ran the server along with the front-end pages for 48-hours (a period typically longer than the charity stream). During this time, I verified that all oAuth token refresh requests, server connections, and APIs remained stable and connected. This test was successful.
Developer-local Dry Run
The purpose of this test was to run the plug-in within a production environment without exposing the plug-in functionality to viewers. To do this, the streamer authenticated the plug-in with their Twitch account on a development PC. They then streamed from their normal PC while I monitored the development PC, verifying that the server and front-end pages all ran correctly during this stream. We ran the stream for about 5 hours (enough time to allow the oAuth token to need to be refreshed). This test succeeded.
Live Test
This test has yet to happen but will involve running the stream with the plug-in enabled and viewer-facing prior to the actual charity stream. The streamer preferred to delay this test to a more strategic time for donations. Given the delay we discussed the risks of deferring this test and determined that, after the success of the other tests, this would be low risk and was acceptable to sign off on the project without this being complete.
Project Postmortem
Difficulties and Challenges
The biggest difficulties I experienced with this project were things I had anticipated early in the planning process, namely my lack of experience in the required languages and tech stack. I found a lot of my time was consumed by ramp-up and dealing with unexpected ‘consequences’ of using JavaScript based languages. To a degree, working with the Twitch server and APIs caused challenges as well due to some documentation being out of date.
Learnings
Although there were definitely some frustrating moments during the project, overall I am quite happy with what was achieved. Obviously, I learned a great deal about Twitch APIs, JavaScript, and NodeJS, but what I think was most valuable was my learnings regarding setting up an, albeit simple, client/server web architecture and learning how to use web sockets. I think that these architectural learnings will help me even in my application development career going forward.
Project Presentation
A video covering much of the information in this document as well as a live demo was recorded and can be viewed here: https://youtu.be/TbAxasI2DWI