diff --git a/docs/VnVPlan/VnVPlan.tex b/docs/VnVPlan/VnVPlan.tex index 98b51c8..3c6994f 100644 --- a/docs/VnVPlan/VnVPlan.tex +++ b/docs/VnVPlan/VnVPlan.tex @@ -62,22 +62,22 @@ \subsection{Symbols} \centering \begin{tabular}{L{0.25\linewidth}L{0.8\linewidth}} \toprule \textbf{Symbol} & \textbf{Description} \\ \midrule - Tai Chi & A classical Chinese martial art system practiced for health promotion and rehabilitation. \\ Instructor & A person who teaches a Tai Chi class through an online conference system. \\ - Practitioner & A person who learns Tai Chi through an online conference system. \\ + Performance test & Testing the performance(includes different metrics) of a system. \\ Pipeline & A sequence of processing elements connected in series, which are responsible for generating annotations. \\ - UI & User Interface. \\ - TA & Teaching Assistant. \\ - SRS & The Software Requirements Specification document. \\ POC & proof of concept. \\ + Practitioner & A person who learns Tai Chi through an online conference system. \\ SFU & Selective Forwarding Unit, a component in real-time communication systems like WebRTC that routes and selectively forwards audio and video streams from one participant to others. \\ - V\&V Plan & The verification and validation plan document(this document). \\ + SRS & The Software Requirements Specification document. \\ + Stress test & Testing the limits (often the amount of data) of a system. \\ + TA & Teaching Assistant. \\ + Tai Chi & A classical Chinese martial art system practiced for health promotion and rehabilitation. \\ Type: Functional & Functional test: An input/output blackbox type test. \\ Type: Dynamic & Dynamic test: Test type that requires code/program to be executed. \\ Type: Manual & Manual test: Test type that requires the user to do the test without using automated tools. \\ Type: Automated & Automated test: Test type containing code/program that can be executed. \\ - Stress test & Testing the limits (often the amount of data) of a system. \\ - Performance test & Testing the performance(includes different metrics) of a system. \\ \bottomrule + UI & User Interface. \\ + V\&V Plan & The verification and validation plan document(this document). \\ \bottomrule \end{tabular} \caption{List of symbols, abbreviations, and acronyms} \label{tab:abbrv} diff --git a/docs/VnVReport/VnVReport.pdf b/docs/VnVReport/VnVReport.pdf index fab9044..689e768 100644 Binary files a/docs/VnVReport/VnVReport.pdf and b/docs/VnVReport/VnVReport.pdf differ diff --git a/docs/VnVReport/VnVReport.tex b/docs/VnVReport/VnVReport.tex index 7bba6f0..955751b 100644 --- a/docs/VnVReport/VnVReport.tex +++ b/docs/VnVReport/VnVReport.tex @@ -19,6 +19,11 @@ \usepackage{pdflscape} \usepackage{siunitx} \usepackage{graphicx} +\usepackage{placeins} +\usepackage[normalem]{ulem} + +\newcommand{\rt}[1]{\textcolor{red}{#1}} + \input{../Comments} \input{../Common} @@ -38,7 +43,8 @@ \section{Revision History} \begin{tabularx}{\textwidth}{llX} \toprule {\bf Date} & {\bf Developer(s)} & {\bf Change} \\ \midrule -Mar 6 & AJ, QS, KH, XY, QC & Initial draft \\ + Mar 6 & AJ, QS, KH, XY, QC & Initial draft \\ + Apr 2 & AJ, QS, KH, XY, QC & Rev 1 \\ \bottomrule \end{tabularx} @@ -52,19 +58,18 @@ \section{Symbols, Abbreviations and Acronyms} \begin{table}[H] \centering \begin{tabular}{L{0.25\linewidth}L{0.8\linewidth}} \toprule - \textbf{Symbol} & \textbf{Description} \\ \midrule - Tai Chi & A classical Chinese martial art system practiced for health promotion and rehabilitation. \\ + \textbf{Symbol} & \textbf{Description} \\ \midrule Instructor & A person who teaches a Tai Chi class through an online conference system. \\ - Practitioner & A person who learns Tai Chi through an online conference system. \\ Pipeline & A sequence of processing elements connected in series, which are responsible for generating annotations. \\ - UI & User Interface. \\ - TA & Teaching Assistant. \\ - SRS & The Software Requirements Specification document. \\ POC & proof of concept. \\ + Performance test & Testing the performance (includes different metrics) of a system. \\ + Practitioner & A person who learns Tai Chi through an online conference system. \\ SFU & Selective Forwarding Unit, a component in real-time communication systems like WebRTC that routes and selectively forwards audio and video streams from one participant to others. \\ + SRS & The Software Requirements Specification document. \\ + TA & Teaching Assistant. \\ + Tai Chi & A classical Chinese martial art system practiced for health promotion and rehabilitation. \\ + UI & User Interface. \\ V\&V Plan & The verification and validation plan document. \\ - Stress test & Testing the limits (often the amount of data) of a system. \\ - Performance test & Testing the performance(includes different metrics) of a system. \\ MIN\_RES \label{const:res} & 720p \\ \bottomrule \end{tabular} \caption{List of symbols, abbreviations, and acronyms} @@ -89,489 +94,566 @@ \section{Symbols, Abbreviations and Acronyms} \section{Functional Requirements Evaluation} \begin{enumerate}[FR-T1] - \item \label{FRT1} - \begin{description} - \item[Initial State] Client application is running on the user's device, but - the user didn’t do any operations yet. - \item[Input/Condition] User clicks on the applicable - identity(instructor/practitioner) button - \item[Expected Output] The live stream video window pops out on the user's - screen. - \item[Actual Output] The live stream video window shows on the instructor's - screen, it doesn't show on the practitioner's screen. - \item[Result] Pass - \end{description} - \item \label{FRT2} - \begin{description} - \item[Initial State] Application running on user’s computer, and the user has - clicked on “the instructor identity button” to indicate they are a TaiChi - instructor. A window asking for permission to use the camera on the - instructor's device popped out. - \item[Input/Condition] User allow/deny the webcam permission - \item[Expected Output] The webcam on the instructor’s device is turned on - \item[Actual Output] The webcam on the instructor’s device is turned on after - allowing webcam permission, and the webcam is not turned on after denying - permission. - \item[Result] Pass - \end{description} - \item \label{FRT3} - \begin{description} - \item[Initial State] both client applications and the server are running. - \item[Input/Condition] The user clicks on the applicable identity button to - indicate they are an instructor or a practitioner. - \item[Expected Output] A log message indicates connection between the user’s - device and the server has been established. - \item[Actual Output] Log message confirms a successful connection between the - user’s device and the server for both instructor and practitioner. - \item[Result] Pass - \end{description} - \item \label{FRT4} - \begin{description} - \item[Type] Functional, Dynamic, Automated - \item[Initial State] The live stream Window for practitioners. - \item[Input/Condition] The user’s device has established a connection with the - server as a practitioner device. - \item[Expected Output] A request from the client device to the server for - accessing the list of available annotation configuration. - \item[Actual Output] The client device sends a request to the server for the - list of available annotation configurations. - \item[Result] Pass - \end{description} - \item \label{FRT5} - \begin{description} - \item[Initial State] The selectable list of the type of annotations is - rendered on the user's screen. - \item[Input/Condition] Practitioner’s selection on the list of types of - annotations. - \item[Expected Output] A request(that reflects user’s annotation selection) - from the client device to the server for updating the annotation - configuration, with a log indicating the request is sent. - \item[Actual Output] The client device sends the selected annotation - configuration update to the server, and a log entry confirms the request - was sent. - \item[Result] Pass - \end{description} - \item \label{FRT6} - \begin{description} - \item[Initial State] The system is running and actively connected to - practitioners. - \item[Input/Condition] Practitioners initiate updates to annotation - configurations. - \item[Expected Output] The system receives and processes the updated annotation - configurations. - \item[Actual Output] The server gets the request and user sees the annotation - they selected. - \item[Result] Pass - \end{description} - \item \label{FRT7} - \begin{description} - \item[Initial State] The server is running and actively receiving annotation - configuration updates. - \item[Input/Condition] In a controlled test environment, the +\item \label{FRT1} + \begin{description} + \item[\sout{Initial State}] \sout{Client application is running on the user's + device, but the user didn’t do any operations yet.} + \item[\sout{Input/Condition}] \sout{User clicks on the applicable + identity(instructor/practitioner) button} + \item[\sout{Expected Output}] \sout{The live stream video window pops out on + the user's screen.} + \item[Actual Output] The live stream video window shows on the instructor's + screen, it doesn't show on the practitioner's screen. + \item[Result] Pass + \end{description} +\item \label{FRT2} + \begin{description} + \item[\sout{Initial State}] \sout{Application running on user’s computer, and + the user has clicked on “the instructor identity button” to indicate + they are a TaiChi instructor. A window asking for permission to use the + camera on the instructor's device popped out.} + \item[\sout{Input/Condition}] \sout{User allow/deny the webcam permission} + \item[\sout{Expected Output}] \sout{The webcam on the instructor’s device is + turned on} + \item[Actual Output] The webcam on the instructor’s device is turned on after + allowing webcam permission, and the webcam is not turned on after denying + permission. + \item[Result] Pass + \end{description} +\item \label{FRT3} + \begin{description} + \item[\sout{Initial State}] \sout{both client applications and the server are + running.} + \item[\sout{Input/Condition}] \sout{The user clicks on the applicable identity + button to indicate they are an instructor or a practitioner.} + \item[\sout{Expected Output}] \sout{A log message indicates connection between + the user’s device and the server has been established.} + \item[Actual Output] Log message confirms a successful connection between the + user’s device and the server for both instructor and practitioner. + \item[Result] Pass + \end{description} +\item \label{FRT4} + \begin{description} + \item[Type] Functional, Dynamic, Automated + \item[\sout{Initial State}] \sout{The live stream Window for practitioners.} + \item[\sout{Input/Condition}] \sout{The user’s device has established a + connection with the server as a practitioner device.} + \item[\sout{Expected Output}] \sout{A request from the client device to the server for + accessing the list of available annotation configuration.} + \item[Actual Output] The client device sends a request to the server for the + list of available annotation configurations. + \item[Result] Pass + \end{description} +\item \label{FRT5} + \begin{description} + \item[\sout{Initial State}] \sout{The selectable list of the type of + annotations is rendered on the user's screen.} + \item[\sout{Input/Condition}] \sout{Practitioner’s selection on the list of + types of annotations.} + \item[\sout{Expected Output}] \sout{A request(that reflects user’s annotation + selection) from the client device to the server for updating the + annotation configuration, with a log indicating the request is sent.} + \item[Actual Output] The client device sends the selected annotation + configuration update to the server, and a log entry confirms the request + was sent. + \item[Result] Pass + \end{description} +\item \label{FRT6} + \begin{description} + \item[\sout{Initial State}] \sout{The system is running and actively connected + to practitioners.} + \item[\sout{Input/Condition}] \sout{Practitioners initiate updates to + annotation configurations.} + \item[\sout{Expected Output}] \sout{The system receives and processes the + updated annotation configurations.} + \item[Actual Output] The server gets the request and user sees the annotation + they selected. + \item[Result] Pass + \end{description} +\item \label{FRT7} + \begin{description} + \item[\sout{Initial State}] \sout{The server is running and actively receiving + annotation configuration updates.} + \item[\sout{Input/Condition}] \sout{In a controlled test environment, the practitioner-client initiates the update of an annotation configuration. - The update is sent to the server for processing. - \item[Expected Output] The expected result is that the server correctly - processes the received annotation configuration from the - practitioner-client. - \item[Actual Output] The server is not able to receive annotation configuration - updates while the connection has been established. - \item[Result] Fail - \end{description} - \item \label{FRT8} - \begin{description} - \item[Initial State] The server has received and processed the annotation - configuration. - \item[Input/Condition] The server uses the received annotation configuration to - configure machine learning pipelines. - \item[Expected Output] The machine learning pipelines are arranged and - configured based on the annotation configuration. - \item[Actual Output] The server successfully arranges and configures machine - learning pipelines according to the received annotation configuration. - \item[Result] Pass - \end{description} - \item \label{FRT9} - \begin{description} - \item[Initial State] The machine learning pipelines are configured and active. - \item[Input/Condition] The instructor's video stream is processed with the - annotation configuration. - \item[Expected Output] The instructor's video stream is rendered with - annotations. - \item[Actual Output] The instructor's video stream is processed with the - annotations. - \item[Result] Pass - \end{description} - \item \label{FRT10} - \begin{description} - \item[Initial State] The server is actively connected to practitioner clients. - \item[Input/Condition] The annotated video stream is generated and ready for - transmission. - \item[Expected Output] The annotated video stream is transmitted to each - practitioner-client through their established connections. - \item[Actual Output] The annotated video stream is transmitted to practitioner - clients. - \item[Result] Pass - \end{description} - \item \label{FRT11} - \begin{description} - \item[Initial State] The signaling server is running. - \item[Input/Condition] Signaling requests for WebRTC connections are initiated. - \item[Expected Output] The signaling server consistently responds to requests - and establishes WebRTC connections. - \item[Actual Output] The signaling server responds to most requests and - establishes WebRTC connections - \item[Result] Pass - \end{description} - \item \label{FRT12} - \begin{description} - \item[Initial State] The client application is running, but the user didn’t do - any operations yet - \item[Input/Condition] The user joining video stream session. - \item[Expected Output] A button to identify if a user is an instructor or a - practitioner is rendered. - \item[Actual Output] The button to identify a user as an instructor or a - practitioner is rendered without issues - \item[Result] Pass - \end{description} - \end{enumerate} + The update is sent to the server for processing.} + \item[\sout{Expected Output}] \sout{The expected result is that the server + correctly processes the received annotation configuration from the + practitioner-client.} + \item[Actual Output] The server is not able to receive annotation configuration + updates while the connection has been established. + \item[Result] Fail + \end{description} +\item \label{FRT8} + \begin{description} + \item[\sout{Initial State}] \sout{The server has received and processed the + annotation configuration.} + \item[\sout{Input/Condition}] \sout{The server uses the received annotation + configuration to configure machine learning pipelines.} + \item[\sout{Expected Output}] \sout{The machine learning pipelines are arranged + and configured based on the annotation configuration.} + \item[Actual Output] The server successfully arranges and configures machine + learning pipelines according to the received annotation configuration. + \item[Result] Pass + \end{description} +\item \label{FRT9} + \begin{description} + \item[\sout{Initial State}] \sout{The machine learning pipelines are configured + and active.} + \item[\sout{Input/Condition}] \sout{The instructor's video stream is processed + with the annotation configuration.} + \item[\sout{Expected Output}] \sout{The instructor's video stream is rendered + with annotations.} + \item[Actual Output] The instructor's video stream is processed with the + annotations. + \item[Result] Pass + \end{description} +\item \label{FRT10} + \begin{description} + \item[\sout{Initial State}] \sout{The server is actively connected to + practitioner clients.} + \item[\sout{Input/Condition}] \sout{The annotated video stream is generated and + ready for transmission.} + \item[\sout{Expected Output}] \sout{The annotated video stream is transmitted + to each practitioner-client through their established connections.} + \item[Actual Output] The annotated video stream is transmitted to practitioner + clients. + \item[Result] Pass + \end{description} +\item \label{FRT11} + \begin{description} + \item[\sout{Initial State}] \sout{The signaling server is running.} + \item[\sout{Input/Condition}] \sout{Signaling requests for WebRTC connections + are initiated.} + \item[\sout{Expected Output}] \sout{The signaling server consistently responds + to requests and establishes WebRTC connections.} + \item[Actual Output] The signaling server responds to most requests and + establishes WebRTC connections + \item[Result] Pass + \end{description} +\item \label{FRT12} + \begin{description} + \item[\sout{Initial State}] \sout{The client application is running, but the + user didn’t do any operations yet} + \item[\sout{Input/Condition}] \sout{The user joining video stream session.} + \item[\sout{Expected Output}] \sout{A button to identify if a user is an + instructor or a practitioner is rendered.} + \item[Actual Output] The button to identify a user as an instructor or a + practitioner is rendered without issues + \item[Result] Pass + \end{description} +\end{enumerate} \section{Nonfunctional Requirements Evaluation} +\rt{\subsection{Look and Feel Requirements}} \begin{enumerate}[NFR-T1] - \item \label{NFRT1} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running, including the user interface. - \item[Input/Condition] User interactions such as button clicks and menu - selections. - \item[Expected Output] The user is able to interact with the client application - and understand the response from and results yielded by the system. - \item[Actual Output] All 5 users are able to successfully interact with the - application with understandable responses and results from the system. - \item[Result] Pass - \end{description} - \item \label{NFRT2} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running, including the user interface. - \item[Input/Condition] User interactions such as button clicks and menu - selections. - \item[Expected Output] System response to user interactions. - \item[Actual Output] The system responds to user interactions promptly and - correctly. - \item[Result] Pass - \end{description} - \item \label{NFRT3} - \begin{description} - \item[Initial State] The system is in a stable operational state with necessary - services and components active. No users are currently logged in. - \item[Input/Condition] 5 test accounts (or more) for users. Predefined user - actions/scripts (relevant to normal system interactions during peak - periods). - \item[Expected Output] The system remains stable and responsive. All user - transactions are processed successfully. - \item[Actual Output] The system remains stable and responsive with all user - transactions processed successfully. This is evident in the survey result - part 3 in figure \ref{fig:surveyp3}. - \item[Result] Pass - \end{description} - \item \label{NFRT4} - \begin{description} - \item[Initial State] The system is operational, with all services and - components running. User accounts for test are set up, and no tasks are - being performed. - \item[Input/Condition] Erroneous user input data. Improper user actions. - \item[Expected Output] The system detects and rejects invalid inputs or - actions, providing clear and helpful error messages to the user. - Transactions or actions are either rolled back safely or do not proceed - until valid input is provided. - \item[Actual Output] No invalid inputs can be made within the system. - \item[Result] Pass - \end{description} +\item \label{NFRT1} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running, including the user + interface.} + \item[\sout{Input/Condition}] \sout{User interactions such as button clicks + and menu selections.} + \item[\sout{Expected Output}] \sout{The user is able to interact with the + client application and understand the response from and results + yielded by the system.} + \item[Actual Output] All users are able to successfully interact with the + application with understandable responses and results from the system. + \item[Result] Pass \\ + \rt{Evidence to support this result is in Survey Result part listed in Figure \ref{fig:surveyp1}, + 7 out of 10 users rated the experience in reading the in-app + instructions and navigating through are beyond expectation.} + \end{description} +\end{enumerate} + +\rt{\subsection{Usability and Humanity Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT2} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running, including the user + interface.} + \item[\sout{Input/Condition}] \sout{User interactions such as button clicks + and menu selections.} + \item[\sout{Expected Output}] \sout{System response to user interactions.} + \item[Actual Output] The system responds to user interactions promptly and + correctly. + \item[Result] Pass + \end{description} +\item \label{NFRT3} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a stable operational state + with necessary services and components active. No users are currently + logged in.} + \item[\sout{Input/Condition}] \sout{5 test accounts (or more) for users. + Predefined user actions/scripts (relevant to normal system + interactions during peak periods).} + \item[\sout{Expected Output}] \sout{The system remains stable and responsive. + All user transactions are processed successfully.} + \item[Actual Output] The system remains stable and responsive with all user + transactions processed successfully. This is evident in the survey result + part 3 in figure \ref{fig:surveyp3}. + \item[Result] Pass + \end{description} +\end{enumerate} + +\rt{\subsection{Performance Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT4} + \begin{description} + \item[\sout{Initial State}] \sout{The system is operational, with all + services and components running. User accounts for test are set up, + and no tasks are being performed.} + \item[\sout{Input/Condition}] \sout{Erroneous user input data. Improper user + actions.} + \item[\sout{Expected Output}] \sout{The system detects and rejects invalid + inputs or actions, providing clear and helpful error messages to the + user. Transactions or actions are either rolled back safely or do not + proceed until valid input is provided.} + \item[Actual Output] No invalid inputs can be made within the system. + \item[Result] Pass + \end{description} \stepcounter{enumi} - \item \label{NFRT6} - \begin{description} - \item[Initial State] The system, with the SFU component, is in a stable, - operational state. Initially, there is a base number of video streams - being processed, which is within the SFU's current capacity. - \item[Input/Condition] A load testing tool or custom script capable of - simulating multiple, simultaneous video streams. - \item[Expected Output] The SFU successfully processes an increasing number of - video streams. - \item[Actual Output] The SFU processes an increased number of video streams, - which was up to 5 users without significant issues. - \item[Result] Pass - \end{description} - \item \label{NFRT7} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running, the user is in a live session. - \item[Input/Condition] Network Interruption/Network Resumption - \item[Expected Output] The system attempts to resume the previous session. - \item[Actual Output] The system did not resume to the previous session. - \item[Result] Fail - \end{description} - \item \label{NFRT8} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running, the user is in a live session. - \item[Input/Condition] Network instability - \item[Expected Output] A pop up window for network instability warning. - \item[Actual Output] There was no pop up window for network instability - warning. - \item[Result] Fail - \end{description} - \item \label{NFRT9} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running. - \item[Input/Condition] Turn down the primary signaling server. - \item[Expected Output] The redundant server takes over until the primary server - resumes. - \item[Actual Output] Connections were able to be established without the - primary signaling server. - \item[Result] Pass - \end{description} - \item \label{NFRT10} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. The user is in a live session with a - media capturing device plugged in. - \item[Input/Condition] Disconnect the media capturing device from the user’s - computing device. - \item[Expected Output] A pop up window which warns the user that the client - application has lost connection to the media capturing device and prompts - the user to reconnect the device to resume the live session. - \item[Actual Output] When the media capturing device is disconnected, a pop-up - window alerts the user and prompts for reconnection. - \item[Result] Pass - \end{description} - \item \label{NFRT11} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] Connect a media capturing device to the user’s computing - device. - \item[Expected Output] A pop up window which warns the user that the video - capturing device does not meet required specification if the client - application detects that the video input stream has a resolution lower - than \hyperref[const:res]{MIN\_RES}. - \item[Actual Output] The system was not able to check the specification of the - capturing device - \item[Result] Fail - \end{description} - \item \label{NFRT12} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] the user starts a live session and begins streaming. - \item[Expected Output] Accurate instructional annotations are rendered and - overlaid on the instructor’s video stream. - \item[Actual Output] The system renders accurate instructional annotations on - the instructor’s video stream. - \item[Result] Pass - \end{description} - \item \label{NFRT13} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] Connect more than one media capturing device to the - user’s computing device. - \item[Expected Output] A dialog listing all the detected capturing devices is - displayed to prompt the user for selecting a device to use. - \item[Actual Output] Feature handled by external API. - \item[Result] Pass - \end{description} - \item \label{NFRT14} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running, with a live session created. - \item[Input/Condition] The live video and audio stream from instructor client - application. - \item[Expected Output] Audio stream and video stream with annotations on - practitioner client application. - \item[Actual Output] The practitioner client application receives only video - streams with annotations. - \item[Result] Fail - \end{description} - \item \label{NFRT15} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] The user starts the client application for instructors. - \item[Expected Output] A message with detailed instruction to set up a media - capturing device and a list of cautions is displayed. - \item[Actual Output] No message was displayed. - \item[Result] Fail - \end{description} - \item \label{NFRT16} - \begin{description} - \item[Initial State] The software system is fully developed, stable, and ready - for testing. The different test environments for the latest versions of - Windows, Linux, and macOS are set up, each with default settings. - \item[Input/Condition] The latest stable versions of Windows, Linux, and - macOS. Test cases designed to cover all the main functionalities of the - system. - \item[Expected Output] The system functions correctly on all mentioned - operating systems without crashes, unexpected behaviour, or significant - performance issues. - \item[Actual Output] The system functions correctly on all mentioned operating - systems without any significant issues. - \item[Result] Pass - \end{description} - \item \label{NFRT17} - \begin{description} - \item[Initial State] The system is fully developed, with all features - operational, and is hosted in a stable environment accessible via the web. - Test environments with the latest versions of Chrome, Firefox, Safari, and - Edge are established, each configured with default browser settings. - \item[Input/Condition] Latest stable versions of Chrome, Firefox, Safari, and - Edge. A series of test cases designed to fully evaluate the - functionalities and features of the system. - \item[Expected Output] The system operates as intended on all tested web - browsers without significant functionality issues, crashes, or severe - performance degradation. Features and visual elements are consistent across - all browsers. - \item[Actual Output] The system operates as intended across all tested web - browsers with consistent features and visual elements. - \item[Result] Pass - \end{description} - \item \label{NFRT18} - \begin{description} - \item[Initial State] The system is fully developed and operational. The testing - environments represent a range of standard personal computer and laptop - configurations (covering various manufacturers, system specifications, and - age of devices) equipped with cameras and, where applicable, microphones. - The devices are running compatible operating systems with the necessary - drivers installed. - \item[Input/Condition] Range of standard computers or laptops with various - specifications, but all within the commonly accepted 'standard' range for - current users. Devices have functional cameras and optional microphones. - Test script detailing system operation tasks. - \item[Expected Output] The system operates without significant delays, errors, - or crashes. - \item[Actual Output] The system operates without significant delays, errors, or - crashes across a range of standard computers and laptops. - \item[Result] Pass - \end{description} - \item \label{NFRT19} - \begin{description} - \item[Initial State] The system is fully developed, with comprehensive - documentation on its architecture, codebase, dependencies, and update - procedures. The development environment is available for testing - maintenance procedures, including tools for version control, testing, and - deployment. - \item[Expected Output] Successful completion of maintenance tasks without - introducing significant issues or disruptions to the system's operation. - \item[Actual Output] It is impossible to perform maintenance without - interrupting live users. - \item[Result] Fail - \end{description} +\item \label{NFRT6} + \begin{description} + \item[\sout{Initial State}] \sout{The system, with the SFU component, is in a + stable, operational state. Initially, there is a base number of video + streams being processed, which is within the SFU's current capacity.} + \item[\sout{Input/Condition}] \sout{A load testing tool or custom script + capable of simulating multiple, simultaneous video streams.} + \item[\sout{Expected Output}] \sout{The SFU successfully processes an + increasing number of video streams.} + \item[Actual Output] The SFU processes an increased number of video streams, + which was up to 5 users without significant issues. + \item[Result] Pass \\ + \rt{Evidence to support this result is in the Performance Test Result listed in Figure \ref{fig:performance}, + all the testers rated the system delay mets the delay expectation with up to 5 practitioners (6 users including the instructor).} + \end{description} +\item \label{NFRT7} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running, the user is in a live + session.} + \item[\sout{Input/Condition}] \sout{Network Interruption/Network Resumption} + \item[\sout{Expected Output}] \sout{The system attempts to resume the + previous session.} + \item[Actual Output] The system did not resume to the previous session. + \item[Result] Fail + \end{description} +\item \label{NFRT8} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running, the user is in a live + session.} + \item[\sout{Input/Condition}] \sout{Network instability} + \item[\sout{Expected Output}] \sout{A pop up window for network instability + warning.} + \item[Actual Output] There was no pop up window for network instability + warning. + \item[Result] Fail + \end{description} +\item \label{NFRT9} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{Turn down the primary signaling server.} + \item[\sout{Expected Output}] \sout{The redundant server takes over until the + primary server resumes.} + \item[Actual Output] Connections were able to be established without the + primary signaling server. + \item[Result] Pass + \end{description} +\item \label{NFRT10} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running. The user is in a live + session with a media capturing device plugged in.} + \item[\sout{Input/Condition}] \sout{Disconnect the media capturing device + from the user’s computing device.} + \item[\sout{Expected Output}] \sout{A pop up window which warns the user that + the client application has lost connection to the media capturing + device and prompts the user to reconnect the device to resume the live + session.} + \item[Actual Output] When the media capturing device is disconnected, a pop-up + window alerts the user and prompts for reconnection. + \item[Result] Pass + \end{description} +\item \label{NFRT11} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{Connect a media capturing device to the + user’s computing device.} + \item[\sout{Expected Output}] \sout{A pop up window which warns the user that + the video capturing device does not meet required specification if the + client application detects that the video input stream has a + resolution lower than \hyperref[const:res]{MIN\_RES}.} + \item[Actual Output] The system was not able to check the specification of the + capturing device + \item[Result] Fail + \end{description} +\item \label{NFRT12} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{the user starts a live session and begins + streaming.} + \item[\sout{Expected Output}] \sout{Accurate instructional annotations are + rendered and overlaid on the instructor’s video stream.} + \item[Actual Output] The system renders accurate instructional annotations on + the instructor’s video stream. + \item[Result] Pass + \end{description} +\item \label{NFRT13} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{Connect more than one media capturing + device to the user’s computing device.} + \item[\sout{Expected Output}] \sout{A dialog listing all the detected + capturing devices is displayed to prompt the user for selecting a + device to use.} + \item[Actual Output] Feature handled by external API. + \item[Result] Pass + \end{description} +\item \label{NFRT14} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running, with a live session + created.} + \item[\sout{Input/Condition}] \sout{The live video and audio stream from + instructor client application.} + \item[\sout{Expected Output}] \sout{Audio stream and video stream with + annotations on practitioner client application.} + \item[Actual Output] The practitioner client application receives only video + streams with annotations. + \item[Result] Fail + \end{description} +\item \label{NFRT15} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{The user starts the client application + for instructors.} + \item[\sout{Expected Output}] \sout{A message with detailed instruction to + set up a media capturing device and a list of cautions is displayed.} + \item[Actual Output] No message was displayed. + \item[Result] Fail + \end{description} +\end{enumerate} + +\rt{\subsection{Operational and Environmental Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT16} + \begin{description} + \item[\sout{Initial State}] \sout{The software system is fully developed, + stable, and ready for testing. The different test environments for the + latest versions of Windows, Linux, and macOS are set up, each with + default settings.} + \item[\sout{Input/Condition}] \sout{The latest stable versions of Windows, + Linux, and macOS. Test cases designed to cover all the main + functionalities of the system.} + \item[\sout{Expected Output}] \sout{The system functions correctly on all + mentioned operating systems without crashes, unexpected behaviour, or + significant performance issues.} + \item[Actual Output] The system functions correctly on all mentioned operating + systems without any significant issues. + \item[Result] Pass \\ + \rt{Evidence to support this result is in Survey Result part listed in Figure + \ref{fig:surveyp3}, 7 out of 10 users rated the speed and + responsiveness are 5.} + \end{description} +\item \label{NFRT17} + \begin{description} + \item[\sout{Initial State}] \sout{The system is fully developed, with all + features operational, and is hosted in a stable environment accessible + via the web. Test environments with the latest versions of Chrome, + Firefox, Safari, and Edge are established, each configured with + default browser settings.} + \item[\sout{Input/Condition}] \sout{Latest stable versions of Chrome, + Firefox, Safari, and Edge. A series of test cases designed to fully + evaluate the functionalities and features of the system.} + \item[\sout{Expected Output}] \sout{The system operates as intended on all + tested web browsers without significant functionality issues, crashes, + or severe performance degradation. Features and visual elements are + consistent across all browsers.} + \item[Actual Output] The system operates as intended across all tested web + browsers with consistent features and visual elements. + \item[Result] Pass + \end{description} +\item \label{NFRT18} + \begin{description} + \item[\sout{Initial State}] \sout{The system is fully developed and + operational. The testing environments represent a range of standard + personal computer and laptop configurations (covering various + manufacturers, system specifications, and age of devices) equipped + with cameras and, where applicable, microphones. The devices are + running compatible operating systems with the necessary drivers + installed.} + \item[\sout{Input/Condition}] \sout{Range of standard computers or laptops + with various specifications, but all within the commonly accepted + 'standard' range for current users. Devices have functional cameras + and optional microphones. Test script detailing system operation + tasks.} + \item[\sout{Expected Output}] \sout{The system operates without significant + delays, errors, or crashes.} + \item[Actual Output] The system operates without significant delays, errors, or + crashes across a range of standard computers and laptops. + \item[Result] Pass \\ + \rt{Part of evidence to support this result is in the Performance Test Result listed in Figure \ref{fig:performance}, + all the testers rated the system delay mets the delay expectation with up to 5+ practitioners.} + \end{description} +\end{enumerate} + +\rt{\subsection{Maintainability and Support Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT19} + \begin{description} + \item[\sout{Initial State}] \sout{The system is fully developed, with + comprehensive documentation on its architecture, codebase, + dependencies, and update procedures. The development environment is + available for testing maintenance procedures, including tools for + version control, testing, and deployment.} + \item[\sout{Expected Output}] \sout{Successful completion of maintenance + tasks without introducing significant issues or disruptions to the + system's operation.} + \item[Actual Output] It is impossible to perform maintenance without + interrupting live users. + \item[Result] Fail + \end{description} \addtocounter{enumi}{2} - \item \label{NFRT22} - \begin{description} - \item[Initial State] The system is in a stable state, ready for testing. The - user interface for account creation or any other information input is - accessible, and documentation related to data handling is available. - \item[Input/Condition] Guidelines or criteria specifying what constitutes - "essential" versus "nonessential" information for the system’s purpose. - Access to the system's user interfaces (UI) where data submission forms - are present. - \item[Expected Output] Comparison of requested data against the criteria for - essential information. - \item[Actual Output] The system requests only essential information from users. - \item[Result] Pass - \end{description} - \item \label{NFRT23} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running. - \item[Input/Condition] Attempted unauthorized modifications to the system - including access to system files and modifications to system - configurations. - \item[Expected Output] A determination of whether the system are able to - prevent access or modifications from unauthorized users. - \item[Actual Output] The system prevents all unauthorized access and - modifications during the test. - \item[Result] Pass - \end{description} - \item \label{NFRT24} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] The user starts a live session and begins streaming. - \item[Expected Output] A prompt for granting access to use the media capturing - devices is displayed. - \item[Actual Output] A prompt appears for granting access to media capturing - devices during a live session. This is evident in the survey result - part 4 in figure \ref{fig:surveyp4}. - \item[Result] Pass - \end{description} - \item \label{NFRT25} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] The user starts a live session and begins streaming. - \item[Expected Output] An indicator that the media capturing device is in use - and that the user is being recorded is visible in the client application. - \item[Actual Output] An indicator is visible in the client application when the - media capturing device is in use. - \item[Result] Pass - \end{description} - \item \label{NFRT26} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] The user ends a live session and stops streaming. - \item[Expected Output] The indicator that the media capturing device is in use - disappears. The media stream from the capturing device is no longer - displayed on the screen. - \item[Actual Output] The indicator disappears, and the media stream is no - longer displayed once the session ends. - \item[Result] Pass - \end{description} - \item \label{NFRT27} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running. - \item[Input/Condition] User inputs - \item[Expected Output] System response to user inputs - \item[Actual Output] The system responds effectively to user inputs. - \item[Result] Pass - \end{description} - \item \label{NFRT28} - \begin{description} - \item[Initial State] The system is in a typical operational state with all - components and services running. - \item[Input/Condition] A set of ISO/IEC 12207 standards. - \item[Expected Output] A determination of whether the system and its associated - processes, documentation, and activities comply with the ISO/IEC 12207 - standards. - \item[Actual Output] The system and its processes comply with ISO/IEC 12207 - standards as determined through evaluation. - \item[Result] Pass - \end{description} - \item \label{NFRT29} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running. - \item[Input/Condition] Various user interactions. - \item[Expected Output] The computers continue to function within acceptable - performance parameters throughout the test. - \item[Actual Output] The computer's function is not affected throughout various - user interactions. - \item[Result] Pass - \end{description} - \item \label{NFRT30} - \begin{description} - \item[Initial State] This system is in a typical operational state with all - components and services running. - \item[Input/Condition] User inputs - \item[Expected Output] System response from user inputs - \item[Actual Output] The system responds appropriately and efficiently to user - inputs. - \item[Result] Pass - \end{description} - \end{enumerate} +\end{enumerate} + +\rt{\subsection{Security Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT22} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a stable state, ready for + testing. The user interface for account creation or any other + information input is accessible, and documentation related to data + handling is available.} + \item[\sout{Input/Condition}] \sout{Guidelines or criteria specifying what + constitutes "essential" versus "nonessential" information for the + system’s purpose. Access to the system's user interfaces (UI) where + data submission forms are present.} + \item[\sout{Expected Output}] \sout{Comparison of requested data against the + criteria for essential information.} + \item[Actual Output] The system requests only essential information from users. + \item[Result] Pass + \end{description} +\item \label{NFRT23} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{Attempted unauthorized modifications to + the system including access to system files and modifications to + system configurations.} + \item[\sout{Expected Output}] \sout{A determination of whether the system are + able to prevent access or modifications from unauthorized users.} + \item[Actual Output] The system prevents all unauthorized access and + modifications during the test. + \item[Result] Pass + \end{description} +\item \label{NFRT24} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{The user starts a live session and begins + streaming.} + \item[\sout{Expected Output}] \sout{A prompt for granting access to use the + media capturing devices is displayed.} + \item[Actual Output] A prompt appears for granting access to media capturing + devices during a live session. This is evident in the survey result + part 4 in figure \ref{fig:surveyp4}. + \item[Result] Pass \\ + \rt{Evidence to support this result is in Survey Result part listed in Figure \ref{fig:surveyp4}, prompts + appears for granting access to media captureing devices and when the + instructor stops broadcasting} + \end{description} +\item \label{NFRT25} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{The user starts a live session and begins + streaming.} + \item[\sout{Expected Output}] \sout{An indicator that the media capturing + device is in use and that the user is being recorded is visible in the + client application.} + \item[Actual Output] An indicator is visible in the client application when the + media capturing device is in use. + \item[Result] Pass + \end{description} +\item \label{NFRT26} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{The user ends a live session and stops + streaming.} + \item[\sout{Expected Output}] \sout{The indicator that the media capturing + device is in use disappears. The media stream from the capturing + device is no longer displayed on the screen.} + \item[Actual Output] The indicator disappears, and the media stream is no + longer displayed once the session ends. + \item[Result] Pass + \end{description} +\end{enumerate} + +\rt{\subsection{Cultural Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT27} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{User inputs} + \item[\sout{Expected Output}] \sout{System response to user inputs} + \item[Actual Output] The system responds effectively to user inputs. + \item[Result] Pass + \end{description} +\end{enumerate} + +\rt{\subsection{Legal Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT28} + \begin{description} + \item[\sout{Initial State}] \sout{The system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{A set of ISO/IEC 12207 standards.} + \item[\sout{Expected Output}] \sout{A determination of whether the system and + its associated processes, documentation, and activities comply with + the ISO/IEC 12207 standards.} + \item[Actual Output] The system and its processes comply with ISO/IEC 12207 + standards as determined through evaluation. + \item[Result] Pass + \end{description} +\end{enumerate} + +\rt{\subsection{Health and Safety Requirements}} +\begin{enumerate}[NFR-T1,resume] +\item \label{NFRT29} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{Various user interactions.} + \item[\sout{Expected Output}] \sout{The computers continue to function within + acceptable performance parameters throughout the test.} + \item[Actual Output] The computer's function is not affected throughout various + user interactions. + \item[Result] Pass \\ + \rt{Evidence to support this result is in Survey Result part listed in Figure \ref{fig:surveyp3}, + 7 out of 10 users rated the speed and responsiveness are 5.} + \end{description} +\item \label{NFRT30} + \begin{description} + \item[\sout{Initial State}] \sout{This system is in a typical operational + state with all components and services running.} + \item[\sout{Input/Condition}] \sout{User inputs} + \item[\sout{Expected Output}] \sout{System response from user inputs} + \item[Actual Output] The system responds appropriately and efficiently to user + inputs. + \item[Result] Pass + \end{description} +\end{enumerate} \section{Comparison to Existing Implementation} @@ -603,11 +685,11 @@ \subsection{User Authentication Module} \item \label{UT-UA1} \begin{description} \item[Test Name] test\_renders\_auth\_component - \item[Initial State] The system initializes the Auth component within a mock - routing environment. - \item[Input/Condition] N/A - \item[Expected Output] The component should display the Motion Mingle banner - and a logo image. + \item[\sout{Initial State}] \sout{The system initializes the Auth component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{The component should display the Motion + Mingle banner and a logo image.} \item[Actual Output] The component displayed the Motion Mingle banner and a logo image. \item[Result] Pass @@ -615,32 +697,33 @@ \subsection{User Authentication Module} \item \label{UT-UA2} \begin{description} \item[Test Name] test\_instructor\_button - \item[Initial State] The system initializes the "Auth" component within a mock - routing environment. - \item[Input/Condition] The user clicks on the Instructor button. - \item[Expected Output] The user should be navigated to the '/instructor' path. + \item[\sout{Initial State}] \sout{The system initializes the "Auth" component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{The user clicks on the Instructor button.} + \item[\sout{Expected Output}] \sout{The user should be navigated to the + '/instructor' path.} \item[Actual Output] The user was navigated to the '/instructor' path. \item[Result] Pass \end{description} \item \label{UT-UA3} \begin{description} \item[Test Name] test\_practitioner\_button - \item[Initial State] The system initializes the "Auth" component within a mock - routing environment. - \item[Input/Condition] The user clicks on the Practitioner button. - \item[Expected Output] The user should be navigated to the '/practitioner' - path. + \item[\sout{Initial State}] \sout{The system initializes the "Auth" component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{The user clicks on the Practitioner button.} + \item[\sout{Expected Output}] \sout{The user should be navigated to the + '/practitioner' path.} \item[Actual Output] The user was navigated to the '/practitioner' path. \item[Result] Pass \end{description} \item \label{UT-UA4} \begin{description} \item[Test Name] test\_slogan - \item[Initial State] The system initializes the "Auth" component within a mock - routing environment. - \item[Input/Condition] N/A - \item[Expected Output] The slogan should be visible within the component with - the correct text. + \item[\sout{Initial State}] \sout{The system initializes the "Auth" component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{The slogan should be visible within the + component with the correct text.} \item[Actual Output] The slogan was displayed within the component with the correct text. \item[Result] Pass @@ -652,12 +735,12 @@ \subsection{Instructor View Module} \item \label{UT-M1} \begin{description} \item[Test Name] test\_renders\_instructor\_component - \item[Initial State] The system is initialized with default state settings. - The "Instructor" component is about to be rendered within a mock routing - environment. - \item[Input/Condition] N/A - \item[Expected Output] The "Instructor" component should be rendered with the - title "Motion Mingle". + \item[\sout{Initial State}] \sout{The system is initialized with default state + settings. The "Instructor" component is about to be rendered within a mock + routing environment.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{The "Instructor" component should be rendered + with the title "Motion Mingle".} \item[Actual Output] The "Instructor" component was rendered with the title "Motion Mingle". \item[Result] Pass @@ -665,38 +748,38 @@ \subsection{Instructor View Module} \item \label{UT-M2} \begin{description} \item[Test Name] test\_select\_annotation - \item[Initial State] The system has loaded the Instructor component, and the - "SelectAnnotation" component is ready to receive user input. - \item[Input/Condition] A user selects "Skeleton" annotation from the dropdown - menu. - \item[Expected Output] The dropdown menu should reflect that "Annotation 1" - has been selected. + \item[\sout{Initial State}] \sout{The system has loaded the Instructor component, + and the "SelectAnnotation" component is ready to receive user input.} + \item[\sout{Input/Condition}] \sout{A user selects "Skeleton" annotation from the + dropdown menu.} + \item[\sout{Expected Output}] \sout{The dropdown menu should reflect that + "Annotation 1" has been selected.} \item[Actual Output] "Skeleton" has been selected from the dropdown menu. \item[Result] Pass \end{description} \item \label{UT-M3} \begin{description} \item[Test Name] test\_stop\_broadcast - \item[Initial State] The Instructor component is rendered and operational, - presumed to be in a state where broadcasting is occurring (mocked - condition). - \item[Input/Condition] The user clicks the "Broadcast" button to simulate - starting a broadcast and then clicks "Stop" to simulate ending the - broadcast. - \item[Expected Output] The "MessageModal" mock should be displayed, indicating - that the stopping of the video is to be confirmed. + \item[\sout{Initial State}] \sout{The Instructor component is rendered and + operational, presumed to be in a state where broadcasting is occurring + (mocked condition).} + \item[\sout{Input/Condition}] \sout{The user clicks the "Broadcast" button to + simulate starting a broadcast and then clicks "Stop" to simulate ending + the broadcast.} + \item[\sout{Expected Output}] \sout{The "MessageModal" mock should be displayed, + indicating that the stopping of the video is to be confirmed.} \item[Actual Output] The "MessageModal" mock was displayed. \item[Result] Pass \end{description} \item \label{UT-M4} \begin{description} \item[Test Name] test\_start\_self\_video - \item[Initial State] The Instructor component is rendered and operational. The - self-video is initially off. - \item[Input/Condition] The user clicks "Start self video" to initiate the - video stream. - \item[Expected Output] The system should transition to a state where the - self-video is active. + \item[\sout{Initial State}] \sout{The Instructor component is rendered and + operational. The self-video is initially off.} + \item[\sout{Input/Condition}] \sout{The user clicks "Start self video" to + initiate the video stream.} + \item[\sout{Expected Output}] \sout{The system should transition to a state where + the self-video is active.} \item[Actual Output] The system transitioned to a state where the self-video is active. \item[Result] Pass @@ -704,11 +787,11 @@ \subsection{Instructor View Module} \item \label{UT-M5} \begin{description} \item[Test Name] test\_close\_self\_video - \item[Initial State] The Instructor component is rendered and operational. The - self-video is active. - \item[Input/Condition] The user clicks "Close self video". - \item[Expected Output] The system should transition to a state where the - self-video is inactive. + \item[\sout{Initial State}] \sout{The Instructor component is rendered and + operational. The self-video is active.} + \item[\sout{Input/Condition}] \sout{The user clicks "Close self video".} + \item[\sout{Expected Output}] \sout{The system should transition to a state where + the self-video is inactive.} \item[Actual Output] The system transitioned to a state where the self-video is inactive. \item[Result] Pass @@ -720,13 +803,13 @@ \subsection{Practitioner View Module} \item \label{UT-PV1} \begin{description} \item[Test Name] test\_renders\_practitioner\_component - \item[Initial State] The system is initialized with default state settings. - The "Practitioner" component is about to be rendered within a mock routing - environment. - \item[Input/Condition] N/A - \item[Expected Output] The "Practitioner" component should be rendered with - the title "Motion Mingle", a dropdown for selecting annotations initialized - to "None", and a "Connect" button. + \item[\sout{Initial State}] \sout{The system is initialized with default state + settings. The "Practitioner" component is about to be rendered within a + mock routing environment.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{The "Practitioner" component should be + rendered with the title "Motion Mingle", a dropdown for selecting + annotations initialized to "None", and a "Connect" button.} \item[Actual Output] The "Practitioner" component was rendered with the title "Motion Mingle". \item[Result] Pass @@ -734,12 +817,13 @@ \subsection{Practitioner View Module} \item \label{UT-PV2} \begin{description} \item[Test Name] test\_select\_annotation - \item[Initial State] The "Practitioner" component is rendered and displayed - with the default selected annotation as "None". - \item[Input/Condition] The user changes the annotation selection from "None" - to "Skeleton" using the dropdown. - \item[Expected Output] The dropdown menu for selecting annotations should - reflect the change by displaying "Skeleton" as the current selection. + \item[\sout{Initial State}] \sout{The "Practitioner" component is rendered and + displayed with the default selected annotation as "None".} + \item[\sout{Input/Condition}] \sout{The user changes the annotation selection + from "None" to "Skeleton" using the dropdown.} + \item[\sout{Expected Output}] \sout{The dropdown menu for selecting annotations + should reflect the change by displaying "Skeleton" as the current + selection.} \item[Actual Output] "Skeleton" was displayed as selected in the dropdown menu. \item[Result] Pass @@ -747,22 +831,24 @@ \subsection{Practitioner View Module} \item \label{UT-PV3} \begin{description} \item[Test Name] test\_start\_video\_stream - \item[Initial State] The "Practitioner" component is rendered, displaying the - "Connect" button while the video stream is not connected. - \item[Input/Condition] The "Connect" button was clicked to start the video - stream. - \item[Expected Output] The "Connect" button should change to "Disconnect". + \item[\sout{Initial State}] \sout{The "Practitioner" component is rendered, + displaying the "Connect" button while the video stream is not connected.} + \item[\sout{Input/Condition}] \sout{The "Connect" button was clicked to start the + video stream.} + \item[\sout{Expected Output}] \sout{The "Connect" button should change to + "Disconnect".} \item[Actual Output] The "Connect" button changed to "Disconnect". \item[Result] Pass \end{description} \item \label{UT-PV4} \begin{description} \item[Test Name] test\_stop\_video\_stream - \item[Initial State] The "Practitioner" component is rendered, displaying the - "Disconnect" button while the video stream is connected. - \item[Input/Condition] The "Disconnect" button was clicked to stop the video - stream. - \item[Expected Output] The "Disconnect" button should change to "Connect". + \item[\sout{Initial State}] \sout{The "Practitioner" component is rendered, + displaying the "Disconnect" button while the video stream is connected.} + \item[\sout{Input/Condition}] \sout{The "Disconnect" button was clicked to stop + the video stream.} + \item[\sout{Expected Output}] \sout{The "Disconnect" button should change to + "Connect".} \item[Actual Output] The "Disconnect" button changed to "Connect". \item[Result] Pass \end{description} @@ -773,12 +859,12 @@ \subsection{Annotation Configuration Module} \item \label{UT-AC1} \begin{description} \item[Test Name] test\_render\_select\_annotation\_component - \item[Initial State] The "SelectAnnotation" component is initialized with - default state settings. - \item[Input/Condition] The component is rendered without any preselected - value. - \item[Expected Output] The component should display with the label - "Annotation" and a dropdown button showing the default value "None". + \item[\sout{Initial State}] \sout{The "SelectAnnotation" component is initialized + with default state settings.} + \item[\sout{Input/Condition}] \sout{The component is rendered without any + preselected value.} + \item[\sout{Expected Output}] \sout{The component should display with the label + "Annotation" and a dropdown button showing the default value "None".} \item[Actual Output] The component was rendered with the label "Annotation" and a dropdown button showing the default value "None". \item[Result] Pass @@ -786,12 +872,12 @@ \subsection{Annotation Configuration Module} \item \label{UT-AC2} \begin{description} \item[Test Name] test\_annotation\_options - \item[Initial State] The "SelectAnnotation" component is rendered with default - settings. - \item[Input/Condition] The user clicks on the dropdown menu to view available - options. - \item[Expected Output] The dropdown menu should display four options: "None", - "Skeleton", "Edges", and "Cartoon". + \item[\sout{Initial State}] \sout{The "SelectAnnotation" component is rendered + with default settings.} + \item[\sout{Input/Condition}] \sout{The user clicks on the dropdown menu to view + available options.} + \item[\sout{Expected Output}] \sout{The dropdown menu should display four + options: "None", "Skeleton", "Edges", and "Cartoon".} \item[Actual Output] The dropdown menu displayed four options: "None", "Skeleton", "Edges", and "Cartoon". \item[Result] Pass @@ -803,14 +889,14 @@ \subsection{RTC Control Module} \item \label{UT-RC1} \begin{description} \item[Test Name] test\_create\_peer\_connection - \item[Initial State] Before creating a new "RTCPeerConnection", no connection - exists. - \item[Input/Condition] The "createPeerConnection" function is called without - any specific arguments since it uses predefined settings within its - implementation. - \item[Expected Output] A new "RTCPeerConnection" should be created with the - configuration specified for unified-plan SDP semantics and the Google STUN - server. + \item[\sout{Initial State}] \sout{Before creating a new "RTCPeerConnection", no + connection exists.} + \item[\sout{Input/Condition}] \sout{The "createPeerConnection" function is called + without any specific arguments since it uses predefined settings within + its implementation.} + \item[\sout{Expected Output}] \sout{A new "RTCPeerConnection" should be created + with the configuration specified for unified-plan SDP semantics and the + Google STUN server.} \item[Actual Output] A new "RTCPeerConnection" was created with the configuration specified for unified-plan SDP semantics and the Google STUN server. @@ -819,26 +905,26 @@ \subsection{RTC Control Module} \item \label{UT-RC2} \begin{description} \item[Test Name] test\_connect\_as\_consumer - \item[Initial State] A "RTCPeerConnection" instance exists but has not yet - established a connection nor created any offers. - \item[Input/Condition] The function "connectAsConsumer" is called with the - created peer connection and "annotation" as arguments. - \item[Expected Output] The function should asynchronously create an SDP offer, - set it as the local description, send it to the server, and set the received - SDP answer as the remote description. + \item[\sout{Initial State}] \sout{A "RTCPeerConnection" instance exists but has + not yet established a connection nor created any offers.} + \item[\sout{Input/Condition}] \sout{The function "connectAsConsumer" is called + with the created peer connection and "annotation" as arguments.} + \item[\sout{Expected Output}] \sout{The function should asynchronously create an + SDP offer, set it as the local description, send it to the server, and set + the received SDP answer as the remote description.} \item[Actual Output] Same as expected output. \item[Result] Pass \end{description} \item \label{UT-RC3} \begin{description} \item[Test Name] test\_connect\_as\_broadcaster - \item[Initial State] A "RTCPeerConnection" instance is ready but not yet in a - broadcasting state. - \item[Input/Condition] The function "connectAsBroadcaster" is called with the - peer connection object. - \item[Expected Output] The function should asynchronously create an SDP offer - for broadcasting, set it as the local description, send it to the server, - and set the server's SDP answer as the remote description. + \item[\sout{Initial State}] \sout{A "RTCPeerConnection" instance is ready but not + yet in a broadcasting state.} + \item[\sout{Input/Condition}] \sout{The function "connectAsBroadcaster" is called + with the peer connection object.} + \item[\sout{Expected Output}] \sout{The function should asynchronously create an + SDP offer for broadcasting, set it as the local description, send it to + the server, and set the server's SDP answer as the remote description.} \item[Actual Output] Same as expected. \item[Result] Pass \end{description} @@ -849,65 +935,68 @@ \subsection{Other Modules} \item \label{UT-OT1} \begin{description} \item[Test Name] test\_display\_message - \item[Initial State] The system initializes the "NotFound" component within a - mock routing environment. - \item[Input/Condition] The component is rendered without any user interaction. - \item[Expected Output] The component should display the "Not Found" message. + \item[\sout{Initial State}] \sout{The system initializes the "NotFound" component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{The component is rendered without any user + interaction.} + \item[\sout{Expected Output}] \sout{The component should display the "Not Found" + message.} \item[Actual Output] The component displayed the "Not Found" message. \item[Result] Pass \end{description} \item \label{UT-OT2} \begin{description} \item[Test Name] test\_navigate\_to\_root - \item[Initial State] The system initializes the "NotFound" component within a - mock routing environment. - \item[Input/Condition] The component is rendered, and the existence of a link - is checked. - \item[Expected Output] There should be a link that reads "GO HOME" and - navigates to the root path '/' upon clicking. + \item[\sout{Initial State}] \sout{The system initializes the "NotFound" component + within a mock routing environment.} + \item[\sout{Input/Condition}] \sout{The component is rendered, and the existence + of a link is checked.} + \item[\sout{Expected Output}] \sout{There should be a link that reads "GO HOME" + and navigates to the root path '/' upon clicking.} \item[Actual Output] Same as expected. \item[Result] Pass \end{description} \item \label{UT-OT3} \begin{description} \item[Test Name] test\_close\_message\_modal - \item[Initial State] The "MessageModal" component is rendered with - "isModalOpen" set to true. - \item[Input/Condition] The "Cancel" button was clicked. - \item[Expected Output] The "handleClose" mock function should be called once. + \item[\sout{Initial State}] \sout{The "MessageModal" component is rendered with + "isModalOpen" set to true.} + \item[\sout{Input/Condition}] \sout{The "Cancel" button was clicked.} + \item[\sout{Expected Output}] \sout{The "handleClose" mock function should be + called once.} \item[Actual Output] The "handleClose" mock function was called once. \item[Result] Pass \end{description} \item \label{UT-OT4} \begin{description} \item[Test Name] test\_stop\_video - \item[Initial State] The "MessageModal" component is rendered with - "isModalOpen" set to true. - \item[Input/Condition] The "Stop Video" button was clicked. - \item[Expected Output] The "handelStopVideo" mock function should be called - once. + \item[\sout{Initial State}] \sout{The "MessageModal" component is rendered with + "isModalOpen" set to true.} + \item[\sout{Input/Condition}] \sout{The "Stop Video" button was clicked.} + \item[\sout{Expected Output}] \sout{The "handelStopVideo" mock function should be + called once.} \item[Actual Output] The "handelStopVideo" mock function was called once. \item[Result] Pass \end{description} \item \label{UT-OT5} \begin{description} \item[Test Name] test\_message\_visible - \item[Initial State] The "MessageModal" component is initialized and rendered - with "isModalOpen" set to true. - \item[Input/Condition] N/A - \item[Expected Output] The modal, including the warning message, should be - visible. + \item[\sout{Initial State}] \sout{The "MessageModal" component is initialized and + rendered with "isModalOpen" set to true.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{The modal, including the warning message, + should be visible.} \item[Actual Output] The modal, including the warning message, was visible. \item[Result] Pass \end{description} \item \label{UT-OT6} \begin{description} \item[Test Name] test\_message\_invisible - \item[Initial State] The "MessageModal" component is initialized and rendered - with "isModalOpen" set to false. - \item[Input/Condition] N/A - \item[Expected Output] None of the modal's content should be present in the - document. + \item[\sout{Initial State}] \sout{The "MessageModal" component is initialized and + rendered with "isModalOpen" set to false.} + \item[\sout{Input/Condition}] \sout{N/A} + \item[\sout{Expected Output}] \sout{None of the modal's content should be present + in the document.} \item[Actual Output] None of the modal's content was present in the document. \item[Result] Pass \end{description} @@ -918,10 +1007,10 @@ \subsection{SFU Server Module} \item \label{UT-S1} \begin{description} \item[Test Name] test\_broadcast\_options - \item[Initial State] Server is initialized and running with /broadcast - endpoint available. - \item[Input/Condition] HTTP OPTIONS request to /broadcast. - \item[Expected Output] HTTP status code 200. + \item[\sout{Initial State}] \sout{Server is initialized and running with + /broadcast endpoint available.} + \item[\sout{Input/Condition}] \sout{HTTP OPTIONS request to /broadcast.} + \item[\sout{Expected Output}] \sout{HTTP status code 200.} \item[Actual Output] HTTP status code 200. \item[Result] Pass \end{description} @@ -929,12 +1018,12 @@ \subsection{SFU Server Module} \item \label{UT-S2} \begin{description} \item[Test Name] test\_broadcast\_post - \item[Initial State] Server is initialized with the /broadcast endpoint ready - to accept POST requests. - \item[Input/Condition] POST request to /broadcast with JSON body containing - "sdp" and "type" fields. - \item[Expected Output] HTTP status code 200 and a JSON response containing - "sdp" and "type". + \item[\sout{Initial State}] \sout{Server is initialized with the /broadcast + endpoint ready to accept POST requests.} + \item[\sout{Input/Condition}] \sout{POST request to /broadcast with JSON body + containing "sdp" and "type" fields.} + \item[\sout{Expected Output}] \sout{HTTP status code 200 and a JSON response + containing "sdp" and "type".} \item[Actual Output] HTTP status code 200 and a JSON response containing "sdp" and "type". \item[Result] Pass @@ -943,10 +1032,11 @@ \subsection{SFU Server Module} \item \label{UT-S3} \begin{description} \item[Test Name] test\_broadcast\_empty\_body\_post - \item[Initial State] Server is initialized with the /broadcast endpoint ready - to accept POST requests. - \item[Input/Condition] POST request to /broadcast with an empty JSON body. - \item[Expected Output] HTTP status code 400 + \item[\sout{Initial State}] \sout{Server is initialized with the /broadcast + endpoint ready to accept POST requests.} + \item[\sout{Input/Condition}] \sout{POST request to /broadcast with an empty JSON + body.} + \item[\sout{Expected Output}] \sout{HTTP status code 400} \item[Actual Output] HTTP status code 400 \item[Result] Pass \end{description} @@ -954,10 +1044,11 @@ \subsection{SFU Server Module} \item \label{UT-S4} \begin{description} \item[Test Name] test\_broadcast\_post\_with\_invalid\_data\_types - \item[Initial State] Server is initialized with the /broadcast endpoint ready. - \item[Input/Condition] POST request to /broadcast with invalid data types for - "sdp" and "type". - \item[Expected Output] HTTP status code 400 + \item[\sout{Initial State}] \sout{Server is initialized with the /broadcast + endpoint ready.} + \item[\sout{Input/Condition}] \sout{POST request to /broadcast with invalid data + types for "sdp" and "type".} + \item[\sout{Expected Output}] \sout{HTTP status code 400} \item[Actual Output] HTTP status code 400 \item[Result] Pass \end{description} @@ -965,10 +1056,11 @@ \subsection{SFU Server Module} \item \label{UT-S5} \begin{description} \item[Test Name] test\_broadcast\_post\_missing\_fields - \item[Initial State] Server is initialized with the /broadcast endpoint ready. - \item[Input/Condition] POST request to /broadcast with missing "type" field in - the JSON body. - \item[Expected Output] HTTP status code 400 + \item[\sout{Initial State}] \sout{Server is initialized with the /broadcast + endpoint ready.} + \item[\sout{Input/Condition}] \sout{POST request to /broadcast with missing + "type" field in the JSON body.} + \item[\sout{Expected Output}] \sout{HTTP status code 400} \item[Actual Output] HTTP status code 400 \item[Result] Pass \end{description} @@ -976,10 +1068,11 @@ \subsection{SFU Server Module} \item \label{UT-S6} \begin{description} \item[Test Name] test\_invalid\_content\_type - \item[Initial State] Server is initialized and ready to handle requests. - \item[Input/Condition] POST request to /broadcast with a "Content-Type" of - "text/plain". - \item[Expected Output] HTTP status code 500 + \item[\sout{Initial State}] \sout{Server is initialized and ready to handle + requests.} + \item[\sout{Input/Condition}] \sout{POST request to /broadcast with a + "Content-Type" of "text/plain".} + \item[\sout{Expected Output}] \sout{HTTP status code 500} \item[Actual Output] HTTP status code 500 \item[Result] Pass \end{description} @@ -987,10 +1080,10 @@ \subsection{SFU Server Module} \item \label{UT-S7} \begin{description} \item[Test Name] test\_method\_not\_allowed - \item[Initial State] Server is initialized with the /broadcast endpoint not - configured to accept GET requests. - \item[Input/Condition] GET request to /broadcast. - \item[Expected Output] HTTP status code 405 + \item[\sout{Initial State}] \sout{Server is initialized with the /broadcast + endpoint not configured to accept GET requests.} + \item[\sout{Input/Condition}] \sout{GET request to /broadcast.} + \item[\sout{Expected Output}] \sout{HTTP status code 405} \item[Actual Output] HTTP status code 405 \item[Result] Pass \end{description} @@ -998,10 +1091,10 @@ \subsection{SFU Server Module} \item \label{UT-S8} \begin{description} \item[Test Name] test\_response\_content\_type - \item[Initial State] Server is initialized and ready to respond to POST - requests. - \item[Input/Condition] HTTP status code 200 and the "Content-Type" header is - "application/json; charset=utf-8" + \item[\sout{Initial State}] \sout{Server is initialized and ready to respond to + POST requests.} + \item[\sout{Input/Condition}] \sout{HTTP status code 200 and the "Content-Type" + header is "application/json; charset=utf-8"} \item[Actual Output] HTTP status code 200 and the "Content-Type" header is "application/json; charset=utf-8" \item[Result] Pass @@ -1010,10 +1103,10 @@ \subsection{SFU Server Module} \item \label{UT-S9} \begin{description} \item[Test Name] test\_consume\_options - \item[Initial State] Server is initialized and running with /consumer endpoint - available. - \item[Input/Condition] HTTP OPTIONS request to /consumer. - \item[Expected Output] HTTP status code 200 + \item[\sout{Initial State}] \sout{Server is initialized and running with + /consumer endpoint available.} + \item[\sout{Input/Condition}] \sout{HTTP OPTIONS request to /consumer.} + \item[\sout{Expected Output}] \sout{HTTP status code 200} \item[Actual Output] HTTP status code 200 \item[Result] Pass \end{description} @@ -1021,11 +1114,11 @@ \subsection{SFU Server Module} \item \label{UT-S10} \begin{description} \item[Test Name] test\_consume\_post - \item[Initial State] Server is initialized with the /consumer endpoint ready - to accept POST requests. - \item[Input/Condition] POST request to /consumer with JSON body containing - "sdp", "type", and "video\_transform". - \item[Expected Output] HTTP status code 500 + \item[\sout{Initial State}] \sout{Server is initialized with the /consumer + endpoint ready to accept POST requests.} + \item[\sout{Input/Condition}] \sout{POST request to /consumer with JSON body + containing "sdp", "type", and "video\_transform".} + \item[\sout{Expected Output}] \sout{HTTP status code 500} \item[Actual Output] HTTP status code 500 \item[Result] Pass \end{description} @@ -1033,9 +1126,11 @@ \subsection{SFU Server Module} \item \label{UT-S11} \begin{description} \item[Test Name] test\_consume\_empty\_body\_post - \item[Initial State] Server is initialized with the /consumer endpoint ready. - \item[Input/Condition] POST request to /consumer with an empty JSON body. - \item[Expected Output] HTTP status code 400 + \item[\sout{Initial State}] \sout{Server is initialized with the /consumer + endpoint ready.} + \item[\sout{Input/Condition}] \sout{POST request to /consumer with an empty JSON + body.} + \item[\sout{Expected Output}] \sout{HTTP status code 400} \item[Actual Output] HTTP status code 400 \item[Result] Pass \end{description} @@ -1043,10 +1138,11 @@ \subsection{SFU Server Module} \item \label{UT-S12} \begin{description} \item[Test Name] test\_consume\_post\_unsupported\_video\_transform - \item[Initial State] Server is initialized with the /consumer endpoint ready. - \item[Input/Condition] POST request to /consumer with unsupported - "video\_transform" value. - \item[Expected Output] HTTP status code 400 + \item[\sout{Initial State}] \sout{Server is initialized with the /consumer + endpoint ready.} + \item[\sout{Input/Condition}] \sout{POST request to /consumer with unsupported + "video\_transform" value.} + \item[\sout{Expected Output}] \sout{HTTP status code 400} \item[Actual Output] HTTP status code 400 \item[Result] Pass \end{description} @@ -1098,10 +1194,22 @@ \subsection{Change due to reviewing the question in the usability survey} survey is: “Are there any specific content or learning materials you would like to see added to the application?” Some users state it is not convenient that they need to manually disconnect and reconnect to the server when selecting -different annotations as a practitioner. The team decided to add an -“auto-refresh” functionality to the system when an instructor or a practitioner -changes their selected annotation would make the UI more intuitive and enhance -user experiences. +different annotations as a practitioner. \rt{This is stated in the question in + Survey Result part listed in Figure \ref{fig:surveyp2}: ``Are there any specific issues or + challenges you've encountered while using the application?" The team decided + to add an “auto-refresh” functionality to the system when an instructor or a + practitioner changes their selected annotation. This change would make the UI + more intuitive and enhance user experiences. Another issue we observed but + user didn't state in the survey: some users accidentally clicked the check + annotated video button before starting broadcasting, and it led to their + confusion as the remote video stream did not show. We think having the Check + annotated video button disabled before the instructor starts broadcasting is a + good way to avoid this confusion. To make things more clear, we also plan to + add an instruction for users to navigate. Furthermore, we got some requests to + add an annotation to indicate the instructor's motion on their feet in + Survey Result part listed in Figure \ref{fig:surveyp5}. We decided this is a "good to have" + feature for user experience enhancement, but this is truly something that can + make our product unique. } \subsection{Change due to failed tests} @@ -1159,11 +1267,12 @@ \subsection{Pytest} comprehensive testing with minimal code make it an invaluable tool for automated testing, contributing to faster development cycles and more reliable software. -\section{Trace to Requirements} +\newpage{} \setlength{\tabcolsep}{2pt} \newgeometry{margin=2cm} \begin{landscape} + \section{Trace to Requirements} \begin{table}[h!] \centering \begin{tabular}{|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|c|} \hline @@ -1234,86 +1343,84 @@ \section{Trace to Requirements} \restoregeometry \section{Trace to Modules} -\begin{landscape} - \begin{table}[h!] - \centering - \label{tab:traceability_matrix} - \small - \setlength\tabcolsep{4pt} - \renewcommand{\arraystretch}{1.2} - \begin{tabular}{|c|*{10}{c|}} - \hline - & \rotatebox{90}{User Authentication Module} & \rotatebox{90}{Instructor View Module} & \rotatebox{90}{Practitioner View Module} & \rotatebox{90}{Annotation Configuration Module} & \rotatebox{90}{RTC Control Module} & \rotatebox{90}{STUN Server Module} & \rotatebox{90}{App Module} & \rotatebox{90}{Video Transform Module} & \rotatebox{90}{Human Pose Estimation Module} & \rotatebox{90}{SFU Server Module} \\ \hline - FR-T1 & & X & & & & & X & & & \\ \hline - FR-T2 & X & X & & & & & & & & \\ \hline - FR-T3 & & & & & X & X & & & & \\ \hline - FR-T4 & & & X & X & & & & & & \\ \hline - FR-T5 & & & X & X & & & & & & \\ \hline - FR-T6 & & & X & X & & & & & & \\ \hline - FR-T7 & & & X & X & & & & & & \\ \hline - FR-T8 & & & & X & & & & & X & \\ \hline - FR-T9 & & X & & & & & & X & & \\ \hline - FR-T10 & & & X & & & & & X & & X \\ \hline - FR-T11 & & & & & X & X & & & & \\ \hline - FR-T12 & X & X & X & & & & X & & & \\ \hline - \end{tabular} - \caption{Traceability matrix showing the connections between functional requirement test cases and modules} - \end{table} +\begin{table}[h!] + \centering + \label{tab:traceability_matrix} + \setlength\tabcolsep{4pt} + \renewcommand{\arraystretch}{1.2} + \begin{tabular}{|c|*{10}{c|}} + \hline + & \rotatebox{90}{User Authentication Module} & \rotatebox{90}{Instructor View Module} & \rotatebox{90}{Practitioner View Module} & \rotatebox{90}{Annotation Configuration Module} & \rotatebox{90}{RTC Control Module} & \rotatebox{90}{STUN Server Module} & \rotatebox{90}{App Module} & \rotatebox{90}{Video Transform Module} & \rotatebox{90}{Human Pose Estimation Module} & \rotatebox{90}{SFU Server Module} \\ \hline + \ref{FRT1} & & X & & & & & X & & & \\ \hline + \ref{FRT2} & X & X & & & & & & & & \\ \hline + \ref{FRT3} & & & & & X & X & & & & \\ \hline + \ref{FRT4} & & & X & X & & & & & & \\ \hline + \ref{FRT5} & & & X & X & & & & & & \\ \hline + \ref{FRT6} & & & X & X & & & & & & \\ \hline + \ref{FRT7} & & & X & X & & & & & & \\ \hline + \ref{FRT8} & & & & X & & & & & X & \\ \hline + \ref{FRT9} & & X & & & & & & X & & \\ \hline + \ref{FRT10} & & & X & & & & & X & & X \\ \hline + \ref{FRT11} & & & & & X & X & & & & \\ \hline + \ref{FRT12} & X & X & X & & & & X & & & \\ \hline + \end{tabular} + \caption{Traceability matrix showing the connections between functional requirement test cases and modules} +\end{table} - \begin{table}[ht] - \centering - \label{tab:traceability_nfr} - \begin{tabular}{|l|*{10}{c|}} % Adjust the number of columns as needed +\begin{table}[h!] + \centering + \label{tab:traceability_nfr} + \begin{tabular}{|l|*{10}{c|}} % Adjust the number of columns as needed \hline & \rotatebox{90}{User Authentication Module} & \rotatebox{90}{Instructor View Module} & \rotatebox{90}{Practitioner View Module} & \rotatebox{90}{Annotation Configuration Module} & \rotatebox{90}{RTC Control Module} & \rotatebox{90}{STUN Server Module} & \rotatebox{90}{App Module} & \rotatebox{90}{Video Transform Module} & \rotatebox{90}{Human Pose Estimation Module} & \rotatebox{90}{SFU Server Module} \\ \hline - NFR-T1 & X & X & X & & & & X & & & \\ \hline - NFR-T2 & & & & & X & X & & & & \\ \hline - NFR-T3 & & & & & X & X & & & & X \\ \hline - NFR-T4 & X & X & X & X & X & X & X & X & X & X \\ \hline - NFR-T6 & & & & & & & & & & X \\ \hline - NFR-T7 & & & & & X & X & & & & \\ \hline - NFR-T8 & & & & & X & X & & & & \\ \hline - NFR-T9 & & & & & X & X & & & & \\ \hline - NFR-T10 & & & & & & & X & X & & \\ \hline - NFR-T11 & & & & & & & X & X & & \\ \hline - NFR-T12 & & & & & & & & X & X & \\ \hline - NFR-T13 & & & & & & & X & & & \\ \hline - NFR-T14 & & & & & & & & X & & \\ \hline - NFR-T15 & & & & & & & X & & & \\ \hline - \end{tabular} - \caption{Traceability Matrix showing the connections between Non-Functional Requirements and Modules} - \end{table} - - \begin{table}[ht] - \centering - \label{tab:traceability_nfr} - \begin{tabular}{|l|*{10}{c|}} % Adjust the number of columns as needed + \ref{NFRT1} & X & X & X & & & & X & & & \\ \hline + \ref{NFRT2} & & & & & X & X & & & & \\ \hline + \ref{NFRT3} & & & & & X & X & & & & X \\ \hline + \ref{NFRT4} & X & X & X & X & X & X & X & X & X & X \\ \hline + \ref{NFRT6} & & & & & & & & & & X \\ \hline + \ref{NFRT7} & & & & & X & X & & & & \\ \hline + \ref{NFRT8} & & & & & X & X & & & & \\ \hline + \ref{NFRT9} & & & & & X & X & & & & \\ \hline + \ref{NFRT10} & & & & & & & X & X & & \\ \hline + \ref{NFRT11} & & & & & & & X & X & & \\ \hline + \ref{NFRT12} & & & & & & & & X & X & \\ \hline + \ref{NFRT13} & & & & & & & X & & & \\ \hline + \ref{NFRT14} & & & & & & & & X & & \\ \hline + \ref{NFRT15} & & & & & & & X & & & \\ \hline + \end{tabular} + \caption{Traceability Matrix showing the connections between Non-Functional Requirements and Modules} +\end{table} + +\begin{table}[h!] + \centering + \label{tab:traceability_nfr} + \begin{tabular}{|l|*{10}{c|}} % Adjust the number of columns as needed \hline & \rotatebox{90}{User Authentication Module} & \rotatebox{90}{Instructor View Module} & \rotatebox{90}{Practitioner View Module} & \rotatebox{90}{Annotation Configuration Module} & \rotatebox{90}{RTC Control Module} & \rotatebox{90}{STUN Server Module} & \rotatebox{90}{App Module} & \rotatebox{90}{Video Transform Module} & \rotatebox{90}{Human Pose Estimation Module} & \rotatebox{90}{SFU Server Module} \\ \hline - NFR-T16 & & & & & & & X & & & \\ \hline - NFR-T17 & & & & & & & X & & & \\ \hline - NFR-T18 & & & & & & & X & X & & \\ \hline - NFR-T19 & & & & X & X & X & X & X & X & X \\ \hline - NFR-T22 & & & & & & & X & & & \\ \hline - NFR-T23 & & & & & & & X & & & \\ \hline - NFR-T24 & & & & & & & X & X & & \\ \hline - NFR-T25 & & & & & & & X & X & & \\ \hline - NFR-T26 & & & & & & & X & X & & \\ \hline - NFR-T27 & & X & X & & & & X & & & \\ \hline - NFR-T28 & & & & X & X & X & X & X & X & X \\ \hline - NFR-T29 & & & & & & & & X & & \\ \hline - NFR-T30 & & X & X & & & & X & & & \\ \hline - \end{tabular} - \caption{Traceability Matrix showing the connections between Non-Functional Requirements and Modules} - \end{table} + \ref{NFRT16} & & & & & & & X & & & \\ \hline + \ref{NFRT17} & & & & & & & X & & & \\ \hline + \ref{NFRT18} & & & & & & & X & X & & \\ \hline + \ref{NFRT19} & & & & X & X & X & X & X & X & X \\ \hline + \ref{NFRT22} & & & & & & & X & & & \\ \hline + \ref{NFRT23} & & & & & & & X & & & \\ \hline + \ref{NFRT24} & & & & & & & X & X & & \\ \hline + \ref{NFRT25} & & & & & & & X & X & & \\ \hline + \ref{NFRT26} & & & & & & & X & X & & \\ \hline + \ref{NFRT27} & & X & X & & & & X & & & \\ \hline + \ref{NFRT28} & & & & X & X & X & X & X & X & X \\ \hline + \ref{NFRT29} & & & & & & & & X & & \\ \hline + \ref{NFRT30} & & X & X & & & & X & & & \\ \hline + \end{tabular} + \caption{Traceability Matrix showing the connections between Non-Functional Requirements and Modules} +\end{table} - \end{landscape} +\clearpage{} \section{Code Coverage Metrics} \subsection*{Frontend Code Coverage} \bibliographystyle{plainnat} -\begin{table}[htbp] +\begin{table}[h!] \centering \begin{tabular}{@{}lcccc@{}} \toprule @@ -1333,7 +1440,7 @@ \subsection*{Frontend Code Coverage} \subsection*{Backend Code Coverage} \bibliographystyle{plainnat} -\begin{table}[htbp] +\begin{table}[h!] \centering \begin{tabular}{@{}lcccc@{}} \toprule @@ -1382,8 +1489,8 @@ \section*{Appendix A --- Reflection} users, including those without Tai Chi experience, a PhD student conducting Tai Chi-related research, and senior citizens, to gain insights into the system's user experience. They were also able to provide valuable feedback on the system -user experiences. In the future, we will make sure to conduct sessions to -connect with our target user group early in the development phase. +user experiences. In the future, we will make sure to conduct sessions to connect with our target +user group early in the development phase. (b) Another change we made to the VnV plan was we removed some test cases due to the evolving project changes. The differences between the VnV plan and the test @@ -1392,44 +1499,80 @@ \section*{Appendix A --- Reflection} regular reviews of the VnV plan and update it as needed to reflect changes in the project scope, requirements, and constraints. -\section*{Appendix B --- Usability Survey} +\rt{Reflecting on the changes made during the project, it’s clear that flexibility +and adaptability were key to navigating the challenges that arose. By selecting a +more diverse group for the usability survey, the team likely gained a broader +perspective on the system's usability. This change could have helped the project +by identifying potential issues that a more homogeneous group might have missed, +leading to a more universally user-friendly system. The decision to include seniors +and individuals without prior Tai Chi experience ensured that the system was +intuitive and accessible to users regardless of their background, which is often +a crucial factor in the success of a product.} + +\rt{Removing some test cases from the Verification and Validation (VnV) plan could +also have a significant impact. This decision likely made the testing process more +efficient by focusing on the most impactful tests. It suggests the team became more +pragmatic and learned to prioritize tasks that directly contribute to the project's +goals. By doing so, the team could allocate resources and time more effectively, +improving productivity and potentially enhancing the quality of the work within the +given constraints.} + +\rt{In both instances, the ability to revise the VnV plan in response to the evolving +project scope and constraints demonstrates a mature project management approach. +The changes likely encouraged continuous improvement and learning, making the team +better prepared to deal with uncertainty and change in future projects. This +adaptability is a highly valuable trait that can contribute to the success of any +project, as it allows for the optimization of processes and resources in real-time.} + + + +\section*{Appendix B --- Survey Result} The usability survey to MotionMingle can be found \href{https://docs.google.com/forms/d/e/1FAIpQLSchSdc_kHr98yHP8QPyWItHoP-dj_hJnuEtNByH0V2M_iDjWw/viewform}{here}. -\section*{Appendix C --- Usability Survey Results} -\begin{figure}[h] +\section*{Appendix C --- Survey Result part listed in Figures} +\FloatBarrier +\begin{figure}[h!] \centering \includegraphics[width=1.0\linewidth]{surveyp1.png} \caption{Survey results part 1} \label{fig:surveyp1} \end{figure} -\begin{figure}[h] +\begin{figure}[!] \centering \includegraphics[width=1.0\linewidth]{surveyp2.png} \caption{Survey results part 2} \label{fig:surveyp2} \end{figure} -\begin{figure}[h] +\begin{figure}[!] \centering \includegraphics[width=1.0\linewidth]{surveyp3.png} \caption{Survey results part 3} \label{fig:surveyp3} \end{figure} -\begin{figure}[h] +\begin{figure}[!] \centering \includegraphics[width=1.0\linewidth]{surveyp4.png} \caption{Survey results part 4} \label{fig:surveyp4} \end{figure} -\begin{figure}[h] +\begin{figure}[!] \centering \includegraphics[width=1.0\linewidth]{surveyp5.png} \caption{Survey results part 5} \label{fig:surveyp5} \end{figure} +\FloatBarrier +\section*{Appendix D --- Performance Test Result} +\begin{figure}[h!] + \centering + \includegraphics[width=1.0\linewidth]{performance.png} + \caption{Performance Test Result} + \label{fig:performance} +\end{figure} -\end{document} \ No newline at end of file +\end{document} diff --git a/docs/VnVReport/performance.png b/docs/VnVReport/performance.png new file mode 100644 index 0000000..a4d2c33 Binary files /dev/null and b/docs/VnVReport/performance.png differ diff --git a/docs/VnVReport/surveyp1.png b/docs/VnVReport/surveyp1.png index d83b4a8..584016b 100644 Binary files a/docs/VnVReport/surveyp1.png and b/docs/VnVReport/surveyp1.png differ diff --git a/docs/VnVReport/surveyp3.png b/docs/VnVReport/surveyp3.png index 2af36e2..b114134 100644 Binary files a/docs/VnVReport/surveyp3.png and b/docs/VnVReport/surveyp3.png differ diff --git a/src/back/BSP.py b/src/back/BSP.py new file mode 100644 index 0000000..a526682 --- /dev/null +++ b/src/back/BSP.py @@ -0,0 +1,88 @@ +# Body Segment Partition parameters +# All parameters are from: https://www.sciencedirect.com/science/article/abs/pii/0021929095001786?via%3Dihub +BSP = { + "head": { + "origin": 7, + "other": 8, + "l": 0.5, + "m": (0.0668 + 0.0694) / 2 + }, + "trunk": { + "origin": (11, 12), + "other": (23, 24), + "l": (0.4151 + 0.4486) / 2, + "m": (0.4257 + 0.4346) / 2 + }, + "left_upper_arm": { + "origin": 11, + "other": 13, + "l": (0.5754 + 0.5772) / 2, + "m": (0.0255 + 0.0271) / 2 + }, + "right_upper_arm": { + "origin": 12, + "other": 14, + "l": (0.5754 + 0.5772) / 2, + "m": (0.0255 + 0.0271) / 2 + }, + "left_forearm": { + "origin": 13, + "other": 15, + "l": (0.4559 + 0.4574) / 2, # length (man + woman) + "m": (0.0138 + 0.0162) / 2 + }, + "right_forearm": { + "origin": 14, + "other": 16, + "l": (0.4559 + 0.4574) / 2, + "m": (0.0138 + 0.0162) / 2 + }, + "left_hand": { + "origin": 15, + "other": (17, 19), + "l": (0.7474 + 0.7900) / 2, + "m": (0.0056 + 0.0061) / 2 + }, + "right_hand": { + "origin": 16, + "other": (18, 20), + "l": (0.7474 + 0.7900) / 2, + "m": (0.0056 + 0.0061) / 2 + }, + "left_thigh": { + "origin": 23, + "other": 25, + "l": (0.3612 + 0.4095) / 2, + "m": (0.1478 + 0.1416) / 2 + }, + "right_thigh": { + "origin": 24, + "other": 26, + "l": (0.3612 + 0.4095) / 2, + "m": (0.1478 + 0.1416) / 2 + }, + "left_shank": { + "origin": 25, + "other": 27, + "l": (0.4416 + 0.4459) / 2, + "m": (0.0481 + 0.0433) / 2 + }, + "right_shank": { + "origin": 26, + "other": 28, + "l": (0.4416 + 0.4459) / 2, + "m": (0.0481 + 0.0433) / 2 + }, + "left_foot": { + "origin": 29, + "other": 31, + "l": (0.4014 + 0.4415) / 2, + "m": (0.0129 + 0.0137) / 2 + }, + "right_foot": { + "origin": 30, + "other": 32, + "l": (0.4014 + 0.4415) / 2, + "m": (0.0129 + 0.0137) / 2 + } +} diff --git a/src/back/face.png b/src/back/face.png new file mode 100644 index 0000000..e1a10d5 Binary files /dev/null and b/src/back/face.png differ diff --git a/src/back/left_footprint.png b/src/back/left_footprint.png new file mode 100644 index 0000000..b811dc3 Binary files /dev/null and b/src/back/left_footprint.png differ diff --git a/src/back/pose_landmarker_lite.task b/src/back/pose_landmarker_lite.task new file mode 100644 index 0000000..09576a9 Binary files /dev/null and b/src/back/pose_landmarker_lite.task differ diff --git a/src/back/right_footprint.png b/src/back/right_footprint.png new file mode 100644 index 0000000..a0a230b Binary files /dev/null and b/src/back/right_footprint.png differ diff --git a/src/back/videotransformtrack.py b/src/back/videotransformtrack.py index f7a78f9..3af97f7 100644 --- a/src/back/videotransformtrack.py +++ b/src/back/videotransformtrack.py @@ -1,4 +1,4 @@ -from typing import Dict, Callable +from typing import Dict, Callable, List import cv2 import mediapipe as mp @@ -6,6 +6,12 @@ from av import VideoFrame import numpy as np +from mediapipe.framework.formats import landmark_pb2 +import math +from BSP import BSP + +solutions = mp.solutions + mp_pose = mp.solutions.pose pose = mp_pose.Pose( static_image_mode=False, @@ -17,6 +23,13 @@ segmentation = mp.solutions.selfie_segmentation.SelfieSegmentation(model_selection=0) mp_drawing = mp.solutions.drawing_utils +BaseOptions = mp.tasks.BaseOptions +PoseLandmarker = mp.tasks.vision.PoseLandmarker +PoseLandmarkerOptions = mp.tasks.vision.PoseLandmarkerOptions +PoseLandmarkerResult = mp.tasks.vision.PoseLandmarkerResult +VisionRunningMode = mp.tasks.vision.RunningMode + + class VideoTransformTrack(MediaStreamTrack): """ @@ -32,66 +45,11 @@ def __init__(self, track: MediaStreamTrack, transform: str): self.track = track self.transform = transform + async def recv(self) -> VideoFrame: frame = await self.track.recv() - return VideoTransformTrack.__TRANSFORMERS[self.transform](frame) - - @staticmethod - def _cartoon_transformer(frame: VideoFrame) -> VideoFrame: - img = frame.to_ndarray(format="bgr24") - # prepare color - img_color = cv2.pyrDown(cv2.pyrDown(img)) - for _ in range(6): - img_color = cv2.bilateralFilter(img_color, 9, 9, 7) - img_color = cv2.pyrUp(cv2.pyrUp(img_color)) - - # prepare edges - img_edges = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) - img_edges = cv2.adaptiveThreshold( - cv2.medianBlur(img_edges, 7), - 255, - cv2.ADAPTIVE_THRESH_MEAN_C, - cv2.THRESH_BINARY, - 9, - 2, - ) - img_edges = cv2.cvtColor(img_edges, cv2.COLOR_GRAY2RGB) - - # combine color and edges - img = cv2.bitwise_and(img_color, img_edges) - - # rebuild a VideoFrame, preserving timing information - new_frame = VideoFrame.from_ndarray(img, format="bgr24") - new_frame.pts = frame.pts - new_frame.time_base = frame.time_base - return new_frame - - @staticmethod - def _edges_transformer(frame: VideoFrame) -> VideoFrame: - # perform edge detection - img = frame.to_ndarray(format="bgr24") - img = cv2.cvtColor(cv2.Canny(img, 100, 200), cv2.COLOR_GRAY2BGR) - - # rebuild a VideoFrame, preserving timing information - new_frame = VideoFrame.from_ndarray(img, format="bgr24") - new_frame.pts = frame.pts - new_frame.time_base = frame.time_base - return new_frame - - @staticmethod - def _rotate_transformer(frame: VideoFrame) -> VideoFrame: - # rotate image - img = frame.to_ndarray(format="bgr24") - rows, cols, _ = img.shape - M = cv2.getRotationMatrix2D((cols / 2, rows / 2), frame.time * 45, 1) - img = cv2.warpAffine(img, M, (cols, rows)) - - # rebuild a VideoFrame, preserving timing information - new_frame = VideoFrame.from_ndarray(img, format="bgr24") - new_frame.pts = frame.pts - new_frame.time_base = frame.time_base - return new_frame + return VideoTransformTrack.__TRANSFORMERS[self.transform](frame) @staticmethod def _skeleton_transformer(frame: VideoFrame) -> VideoFrame: @@ -127,8 +85,8 @@ def process_frame_for_segmentation(frame): # Process the frame results = segmentation.process(frame_rgb) - condition = np.stack((results.segmentation_mask,) * 3, axis=-1) > 0.5 - ouput_frame = np.where(condition, frame, frame_rgb * 0.3).astype(np.uint8) + condition = np.stack((results.segmentation_mask,) * 3, axis=-1) > 0.4 + ouput_frame = np.where(condition, frame, frame_rgb * 0.4).astype(np.uint8) return ouput_frame @@ -141,17 +99,276 @@ def process_frame_for_segmentation(frame): new_frame.pts = frame.pts new_frame.time_base = frame.time_base return new_frame + + @staticmethod + def _center_of_mass_transformer(frame: VideoFrame) -> VideoFrame: + VideoTransformTrack.timestamp += 1 + img = frame.to_ndarray(format="bgr24") + + img = mp.Image(image_format=mp.ImageFormat.SRGB, data=img) + + VideoTransformTrack.landmarker.detect_async(img, VideoTransformTrack.timestamp) + if (not(VideoTransformTrack.COM_result is None)): + new_frame = VideoTransformTrack.__draw_landmarks_on_image(img.numpy_view(), VideoTransformTrack.COM_result) + new_frame = VideoFrame.from_ndarray(new_frame, format="bgr24") + new_frame.pts = frame.pts + new_frame.time_base = frame.time_base + return new_frame + + return frame + + @staticmethod + def __draw_landmarks_on_image(rgb_image: np.ndarray, detection_result) -> np.ndarray: + pose_landmarks_list = detection_result.pose_landmarks + annotated_image = np.copy(rgb_image) + + cv2.rectangle(annotated_image,(0,0),(200,200),(255,255,255),-1) + + # Loop through the detected poses to visualize. + for idx in range(len(pose_landmarks_list)): + # length is 33 + # check this guide to see what each index represents: https://developers.google.com/mediapipe/solutions/vision/pose_landmarker + pose_landmarks = pose_landmarks_list[idx] + + # Draw the pose landmarks. + pose_landmarks_proto = landmark_pb2.NormalizedLandmarkList() + pose_landmarks_proto.landmark.extend([ + landmark_pb2.NormalizedLandmark(x=landmark.x, y=landmark.y, z=landmark.z) for landmark in pose_landmarks + ]) + solutions.drawing_utils.draw_landmarks( + annotated_image, + pose_landmarks_proto, + solutions.pose.POSE_CONNECTIONS, + solutions.drawing_styles.get_default_pose_landmarks_style()) + + + VideoTransformTrack.__draw_COM(annotated_image, pose_landmarks, BSP) + + + return annotated_image + + @staticmethod + def __set_COM_result(result: PoseLandmarkerResult, *args) -> None: + VideoTransformTrack.COM_result = result + + + @staticmethod + def __draw_COM(img: np.ndarray, pose_landmarks: List[landmark_pb2.NormalizedLandmark], BSP: Dict[str, float]): + SCREEN_SCALE = 200 + PIC_SCALE = 40 + LIFTED_THRESHOLD = 0.025 + COM_DISTANCE_THRESHOLD = 0.7 + + def average_position(pose_landmarks, indices): + """Calculate the average position of specified landmarks.""" + if isinstance(indices, tuple): + x = sum(pose_landmarks[i].x for i in indices) / len(indices) + y = sum(pose_landmarks[i].y for i in indices) / len(indices) + z = sum(pose_landmarks[i].z for i in indices) / len(indices) + return x, y, z + else: + return pose_landmarks[indices].x, pose_landmarks[indices].y, pose_landmarks[indices].z + + def interpolate_segment(origin, other, l): + """Interpolate a segment between two points.""" + return (np.interp(l, [0, 1], [origin[i], other[i]]) for i in range(3)) + + def get_segment_mass(segment, pose_landmarks, BSP): + """Calculate the mass for a body segment.""" + origin = average_position(pose_landmarks, BSP[segment]['origin']) + other = average_position(pose_landmarks, BSP[segment]['other']) + segment_position = interpolate_segment(origin, other, BSP[segment]['l']) + return tuple(pos * BSP[segment]['m'] for pos in segment_position) + + def get_COM(pose_landmarks, BSP, SCREEN_SCALE): + """Calculate the Center of Mass (COM) for the pose.""" + com_x, com_y, com_z = 0.0, 0.0, 0.0 + for segment in BSP: + segment_mass = get_segment_mass(segment, pose_landmarks, BSP) + com_x += segment_mass[0] + com_y += segment_mass[1] + com_z += segment_mass[2] + return com_x * SCREEN_SCALE, com_y * SCREEN_SCALE, com_z * SCREEN_SCALE + + def rotate_image(image, angle): + """Rotate an image by a specific angle.""" + row, col = image.shape[:2] + center = tuple(np.array([row, col]) / 2) + rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0) + return cv2.warpAffine(image, rot_mat, (col, row)) + + def get_foot_angle(foot_heel, foot_toe): + """Calculate the angle for a foot.""" + return math.degrees(math.atan2(foot_heel.z - foot_toe.z, foot_heel.x - foot_toe.x)) + 90 + + + def get_foot_to_com_distance(x, z, com): + """Calculate the distance from a foot to the COM.""" + return abs((x - com[0]) ** 2 + (z - com[2]) ** 2) + + def set_footprint_colour(footprint, colour): + """Map colour names to BGR values""" + colour_map = { + "blue": (255, 255, 0), + "orange": (0, 165, 255), + "red": (0, 0, 255), + "dark_red": (0, 0, 122), + } + + # Check if the colour is in the map + if colour in colour_map: + b, g, r = colour_map[colour] + footprint[:, :, 0] = b + footprint[:, :, 1] = g + footprint[:, :, 2] = r + else: + print("Colour not recognized. Please add it to the colour_map.") + + return footprint + + def get_foot_to_com_distance(x, z, com): + """Calculate the distance from a foot to the COM.""" + return abs((x - com[0]) **2 + (z - com[2]) ** 2) + + def check_dimensions(crop, pic_scale): + """Check the if picture dimension matches""" + return crop.shape[0] != pic_scale or crop.shape[1] != pic_scale + + def overlay_image(alpha_mask, alpha_inv, src_img, overlay_img, y1, y2, x1, x2, channel): + """Overlay image to frame""" + src_img[y1:y2, x1:x2, channel] = (alpha_mask * overlay_img[:, :, channel] + + alpha_inv * src_img[y1:y2, x1:x2, channel]) + + def extract_alpha_masks(image): + """Extracts the alpha mask and its inverse from an image.""" + alpha_mask = image[:, :, 3] / 255.0 + alpha_inv = 1.0 - alpha_mask + return alpha_mask, alpha_inv + + def calculate_positions(offset_x, offset_y, shape): + """Calculate the y1, y2, x1, x2 positions based on offsets and image shape.""" + y1, y2 = offset_y, offset_y + shape[0] + x1, x2 = offset_x, offset_x + shape[1] + return y1, y2, x1, x2 + + left_heel = pose_landmarks[29] # left heel + left_toe = pose_landmarks[31] # left toe + + right_heel = pose_landmarks[30] # right heel + right_toe = pose_landmarks[32] # right toe + + left_shoulder = pose_landmarks[11] + right_shoulder = pose_landmarks[12] + + # angle + left_foot_angle = get_foot_angle(left_heel, left_toe) + right_foot_angle = get_foot_angle(right_heel, right_toe) + shoulder_angle = get_foot_angle(left_shoulder, right_shoulder) + # load pics + right_footprint = cv2.imread("right_footprint.png", -1) + left_footprint = cv2.imread("left_footprint.png", -1) + face = cv2.resize(cv2.imread("face.png", -1), (PIC_SCALE, PIC_SCALE)) + face = rotate_image(face, shoulder_angle + 90) + + # resize, change colour and rotate + right_footprint = cv2.resize(right_footprint, (PIC_SCALE, PIC_SCALE)) + right_footprint = set_footprint_colour(right_footprint, "blue") + right_footprint = rotate_image(right_footprint, right_foot_angle) + + left_footprint = cv2.resize(left_footprint, (PIC_SCALE, PIC_SCALE)) + left_footprint = rotate_image(left_footprint, left_foot_angle) + left_footprint = set_footprint_colour(left_footprint, "orange") + + # calculate offset + right_foot_x_offset = math.ceil((right_heel.x + right_toe.x) / 2 * SCREEN_SCALE) + right_foot_y_offset = -math.ceil((right_heel.z + right_toe.z) / 2 * SCREEN_SCALE) + int(SCREEN_SCALE / 2) + right_foot_z_offset = math.ceil((right_heel.z + right_toe.z) / 2 * SCREEN_SCALE) + + left_foot_x_offset = math.ceil((left_heel.x + left_toe.x) / 2 * SCREEN_SCALE) # feet width adjustment + left_foot_y_offset = -math.ceil((left_heel.z + left_toe.z) / 2 * SCREEN_SCALE) + int(SCREEN_SCALE / 2) + left_foot_z_offset = math.ceil((left_heel.z + left_toe.z) / 2 * SCREEN_SCALE) + + com = get_COM(pose_landmarks, BSP, SCREEN_SCALE) # correct + + face_x_offset, _, face_z_offset = com + face_x_offset = int(face_x_offset) + face_y_offset = -int(face_z_offset) + 50 + + + l_com_dist = get_foot_to_com_distance(left_foot_x_offset, left_foot_z_offset, com) + r_com_dist = get_foot_to_com_distance(right_foot_x_offset, right_foot_z_offset, com) + + # left heel lifted + if right_toe.y - left_toe.y > LIFTED_THRESHOLD: + right_footprint = set_footprint_colour(right_footprint, "red") + + # heel higher, number lower + # right heel lifted + elif left_toe.y - right_toe.y > LIFTED_THRESHOLD: + left_footprint = set_footprint_colour(left_footprint, "red") + + #com calculation have issue due to z axis + # com to right + elif l_com_dist * COM_DISTANCE_THRESHOLD > r_com_dist: + right_footprint = set_footprint_colour(right_footprint, "red") + + # # com to left + elif r_com_dist * COM_DISTANCE_THRESHOLD > l_com_dist: + left_footprint = set_footprint_colour(left_footprint, "red") + + # offset on screen + right_y1, right_y2, right_x1, right_x2 = calculate_positions(right_foot_x_offset, right_foot_y_offset, right_footprint.shape) + left_y1, left_y2, left_x1, left_x2 = calculate_positions(left_foot_x_offset, left_foot_y_offset, left_footprint.shape) + face_y1, face_y2, face_x1, face_x2 = calculate_positions(face_x_offset, face_y_offset, face.shape) + + # Check if the right_footprint image has an alpha channel + if right_footprint.shape[2] == 4: + right_alpha_mask, right_alpha_inv = extract_alpha_masks(right_footprint) + left_alpha_mask, left_alpha_inv = extract_alpha_masks(left_footprint) + face_alpha_mask, face_alpha_inv = extract_alpha_masks(face) + + for c in range(3): + right_crop = img[right_y1:right_y2, right_x1:right_x2, c] + left_crop = img[left_y1:left_y2, left_x1:left_x2, c] + face_crop = img[face_y1:face_y2, face_x1:face_x2, c] + + dimension_mismatch = any([ + check_dimensions(right_crop, PIC_SCALE), + check_dimensions(left_crop, PIC_SCALE), + check_dimensions(face_crop, PIC_SCALE) + ]) + + out_of_range = right_y2 > SCREEN_SCALE or left_y2 > SCREEN_SCALE + + if dimension_mismatch or out_of_range: + cv2.putText(img, "Please stand inside the camera", (0, int(SCREEN_SCALE / 2)), cv2.FONT_HERSHEY_SIMPLEX, + 1, (0, 0, 255), 4, cv2.LINE_AA) + return + + # Right foot overlay + overlay_image(right_alpha_mask, right_alpha_inv, img, right_footprint, right_y1, right_y2, right_x1, right_x2, c) + # Left foot overlay + overlay_image(left_alpha_mask, left_alpha_inv, img, left_footprint, left_y1, left_y2, left_x1, left_x2, c) + # Face overlay + overlay_image(face_alpha_mask, face_alpha_inv, img, face, face_y1, face_y2, face_x1, face_x2, c) + __TRANSFORMERS: Dict[str, Callable[[VideoFrame], VideoFrame]] = { - "cartoon": _cartoon_transformer, - "edges": _edges_transformer, - "rotate": _rotate_transformer, "skeleton": _skeleton_transformer, "segmentation": _segmentation_transformer, + "com": _center_of_mass_transformer } supported_transforms = list(__TRANSFORMERS.keys()) + COM_result = None + landmarker = PoseLandmarker.create_from_options(PoseLandmarkerOptions( + base_options=BaseOptions(model_asset_path='pose_landmarker_lite.task'), + running_mode=VisionRunningMode.LIVE_STREAM, + result_callback=__set_COM_result, + output_segmentation_masks=True, +)) + timestamp = 0 class UnsupportedTransform(Exception): def __init__(self, message: str): diff --git a/src/client/src/modules/Instructor.tsx b/src/client/src/modules/Instructor.tsx index acc2b84..fc7f600 100644 --- a/src/client/src/modules/Instructor.tsx +++ b/src/client/src/modules/Instructor.tsx @@ -10,7 +10,6 @@ import MessageModal from './MessageModal'; import SelectAnnotation from './SelectAnnotation'; import { connectAsConsumer, createPeerConnection, connectAsBroadcaster } from './RTCControl'; import logo from './logo.jpg'; -import tai_chi_video from './11_forms_demo_4min.mp4'; const theme = createTheme({ palette: { @@ -109,8 +108,6 @@ function Instructor() { const broadcastLocalVideo = async () => { const videoElement = document.createElement('video'); - videoElement.src = tai_chi_video; - videoElement.onloadedmetadata = async () => { const stream = (videoElement as any).captureStream(); @@ -177,7 +174,7 @@ return (