404 lines
12 KiB
Plaintext
404 lines
12 KiB
Plaintext
\documentclass[conference,a4paper]{IEEEtran}
|
|
|
|
\usepackage{graphicx} % for including figures
|
|
\usepackage{booktabs} % for nicer tables
|
|
\usepackage{float}
|
|
\usepackage[utf8x]{inputenc}
|
|
\usepackage[margin=1in]{geometry} % Adjust margins
|
|
\usepackage{caption}
|
|
\usepackage{hyperref}
|
|
\PassOptionsToPackage{hyphens}{url} % allow breaking urls
|
|
\usepackage{float}
|
|
\usepackage{wrapfig}
|
|
\usepackage{subcaption}
|
|
\usepackage{parskip}
|
|
|
|
\usepackage[style=ieee, backend=biber, maxnames=1, minnames=1]{biblatex}
|
|
\addbibresource{report.bib}
|
|
|
|
\begin{document}
|
|
|
|
\section{Abstract}\label{abstract}
|
|
We evaluated three on-screen keyboard layouts: QWERTY, Dvorak, and Circle. Objective performance, measured in words per minute (WPM), showed a significant main effect of layout. Post-hoc comparisons revealed that QWERTY was significantly faster than both Dvorak and Circle, while no difference was observed between Dvorak and Circle. Total error rate (TER) did not differ significantly between layouts. Subjective workload ratings assessed via NASA-TLX were similar for Dvorak and Circle, but QWERTY was perceived as less demanding. These results indicate that QWERTY offers superior typing speed, whereas error rates and perceived workload are comparable across layouts.
|
|
|
|
\section{Introduction}\label{introduction}
|
|
|
|
\section{Keyboard Designs}\label{keyboard-designs}
|
|
Three on-screen keyboard layouts were evaluated in this study: QWERTY, Dvorak, and a custom-designed Circle layout.
|
|
|
|
1. QWERTY: The standard layout commonly used in English typing, serving as a baseline for comparison.
|
|
|
|
2. Dvorak: An alternative layout designed to increase typing efficiency for physical keyboards
|
|
by placing frequently used letters in the home row, minimizing finger movements.
|
|
|
|
3. Circle Layout: A custom layout developed for this study, in which keys were arranged in a circular pattern. Letters that occur more frequently in English were positioned closer to the center and rendered larger to facilitate faster access. Less frequently used letters were placed toward the periphery and sized smaller, aiming to optimize ergonomic reach and visual salience.
|
|
|
|
This design allowed us to investigate both established and novel layouts, comparing objective typing performance, error rates, and subjective workload.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.45\textwidth]{images/qwerty-pic.png}
|
|
\caption{QWERTY Keyboard Layout}
|
|
\label{fig:qwerty}
|
|
\end{figure}
|
|
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.45\textwidth]{images/dvorak-pic.png}
|
|
\caption{Dvorak Keyboard Layout}
|
|
\label{fig:dvorak}
|
|
\end{figure}
|
|
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=0.3\textwidth]{images/circle-pic.png}
|
|
\caption{Circle Keyboard Layout}
|
|
\label{fig:circle}
|
|
\end{figure}
|
|
|
|
|
|
\section{Experiment}\label{experiment}
|
|
<<echo=FALSE, message=FALSE>>=
|
|
# load libraries here
|
|
library(knitr)
|
|
library(dplyr)
|
|
library(tidyr)
|
|
|
|
# Read the results CSV
|
|
results <- read.csv("../data/results.csv", sep=",", header=TRUE)
|
|
@
|
|
\subsection{Participants}\label{participants}
|
|
Our experiment was conducted using a small sample of 12 participants.
|
|
All of our participants, predominantly male with an average age of \Sexpr{round(mean(results$age),digits=1)}
|
|
were then presented all of our 3 keyboards.
|
|
|
|
\subsection{Apparatus}\label{apparatus}
|
|
The main body of our experimental apparatus was our On-Screen Keyboard, implemented using Tauri + Angular.
|
|
Text-entry measures were collected using TextTest \cite{texttest}.
|
|
|
|
\subsection{Procedure}\label{procedure}
|
|
Each participant was first provided with an overview of the three keyboard models and design rationale
|
|
They were then presented all three layouts in a counterbalanced order to mitigate common order effects
|
|
such as practice, fatigue and boredom.
|
|
Each keyboard was evaluated using only lowercase letters, space and enter to display the next sentence.
|
|
Due to our chosen time constraint of 30 minutes, each participant was given three practice sentences per keyboard,
|
|
followed by 10 recorded sentences for the experiment.
|
|
After completion of all 3 layouts, the participants were then asked to fill out the NASA Task Load Index \cite{nasatlx}.
|
|
|
|
\section{Results}\label{results}
|
|
|
|
\subsection{Descriptive Statistics}\label{descriptive-statistics}
|
|
|
|
\subsubsection{Objective Measures}\label{objective-measures}
|
|
|
|
<<echo=FALSE, message=FALSE>>=
|
|
|
|
ter_stats <- results %>%
|
|
summarise(
|
|
qwerty_min = min(qwerty_ter, na.rm = TRUE),
|
|
qwerty_q1 = quantile(qwerty_ter, 0.25, na.rm = TRUE),
|
|
qwerty_median = median(qwerty_ter, na.rm = TRUE),
|
|
qwerty_mean = mean(qwerty_ter, na.rm = TRUE),
|
|
qwerty_q3 = quantile(qwerty_ter, 0.75, na.rm = TRUE),
|
|
qwerty_max = max(qwerty_ter, na.rm = TRUE),
|
|
|
|
dvorak_min = min(dvorak_ter, na.rm = TRUE),
|
|
dvorak_q1 = quantile(dvorak_ter, 0.25, na.rm = TRUE),
|
|
dvorak_median = median(dvorak_ter, na.rm = TRUE),
|
|
dvorak_mean = mean(dvorak_ter, na.rm = TRUE),
|
|
dvorak_q3 = quantile(dvorak_ter, 0.75, na.rm = TRUE),
|
|
dvorak_max = max(dvorak_ter, na.rm = TRUE),
|
|
|
|
circle_min = min(circle_ter, na.rm = TRUE),
|
|
circle_q1 = quantile(circle_ter, 0.25, na.rm = TRUE),
|
|
circle_median = median(circle_ter, na.rm = TRUE),
|
|
circle_mean = mean(circle_ter, na.rm = TRUE),
|
|
circle_q3 = quantile(circle_ter, 0.75, na.rm = TRUE),
|
|
circle_max = max(circle_ter, na.rm = TRUE)
|
|
)
|
|
ter_tidy <- ter_stats %>%
|
|
pivot_longer(
|
|
cols = everything(),
|
|
names_to = c("layout", ".value"),
|
|
names_sep = "_"
|
|
)
|
|
ter_tidy <- ter_tidy %>%
|
|
select(layout, min, q1, median, mean, q3, max)
|
|
|
|
# Read the results CSV
|
|
results <- read.csv("../data/results.csv", sep=",", header=TRUE)
|
|
|
|
wpm_stats <- results %>%
|
|
summarise(
|
|
qwerty_min = min(qwerty_wpm, na.rm = TRUE),
|
|
qwerty_q1 = quantile(qwerty_wpm, 0.25, na.rm = TRUE),
|
|
qwerty_median = median(qwerty_wpm, na.rm = TRUE),
|
|
qwerty_mean = mean(qwerty_wpm, na.rm = TRUE),
|
|
qwerty_q3 = quantile(qwerty_wpm, 0.75, na.rm = TRUE),
|
|
qwerty_max = max(qwerty_wpm, na.rm = TRUE),
|
|
|
|
dvorak_min = min(dvorak_wpm, na.rm = TRUE),
|
|
dvorak_q1 = quantile(dvorak_wpm, 0.25, na.rm = TRUE),
|
|
dvorak_median = median(dvorak_wpm, na.rm = TRUE),
|
|
dvorak_mean = mean(dvorak_wpm, na.rm = TRUE),
|
|
dvorak_q3 = quantile(dvorak_wpm, 0.75, na.rm = TRUE),
|
|
dvorak_max = max(dvorak_wpm, na.rm = TRUE),
|
|
|
|
circle_min = min(circle_wpm, na.rm = TRUE),
|
|
circle_q1 = quantile(circle_wpm, 0.25, na.rm = TRUE),
|
|
circle_median = median(circle_wpm, na.rm = TRUE),
|
|
circle_mean = mean(circle_wpm, na.rm = TRUE),
|
|
circle_q3 = quantile(circle_wpm, 0.75, na.rm = TRUE),
|
|
circle_max = max(circle_wpm, na.rm = TRUE)
|
|
)
|
|
|
|
wpm_tidy <- wpm_stats %>%
|
|
pivot_longer(
|
|
cols = everything(),
|
|
names_to = c("layout", ".value"),
|
|
names_sep = "_"
|
|
)
|
|
|
|
wpm_tidy <- wpm_tidy %>%
|
|
select(layout, min, q1, median, mean, q3, max)
|
|
|
|
@
|
|
|
|
|
|
|
|
% TER table
|
|
\begin{table}[H]
|
|
\centering
|
|
\caption{Summary of Total Error Rate (TER)}
|
|
|
|
<<results='asis', echo=FALSE>>=
|
|
kable(ter_tidy, format="latex", booktabs=TRUE)
|
|
@
|
|
\end{table}
|
|
|
|
% WPM table
|
|
\begin{table}[H]
|
|
\centering
|
|
\caption{Summary of Words per Minute (WPM)}
|
|
<<results='asis', echo=FALSE>>=
|
|
kable(wpm_tidy, format="latex", booktabs=TRUE)
|
|
@
|
|
\end{table}
|
|
|
|
<<echo=FALSE, results='hide'>>=
|
|
# Create figures directory if it doesn't exist
|
|
dir.create("../figures", showWarnings=FALSE)
|
|
|
|
# Helper functions for standard deviation and confidence intervals
|
|
mean_sd <- function(x) {
|
|
m <- mean(x)
|
|
s <- sd(x)
|
|
c(mean=m, lower=m-s, upper=m+s)
|
|
}
|
|
|
|
mean_ci <- function(x) {
|
|
m <- mean(x)
|
|
se <- sd(x)/sqrt(length(x))
|
|
ci <- qt(0.975, df=length(x)-1)*se
|
|
c(mean=m, lower=m-ci, upper=m+ci)
|
|
}
|
|
|
|
# TER stats
|
|
ter_stats <- rbind(
|
|
mean_ci(results$qwerty_ter),
|
|
mean_ci(results$dvorak_ter),
|
|
mean_ci(results$circle_ter)
|
|
)
|
|
|
|
# Save TER barplot as PDF using LaTeX-compatible fonts
|
|
suppressMessages(pdf("../figures/ter_plot.pdf"))
|
|
bar_pos <- barplot(
|
|
ter_stats[,"mean"],
|
|
names.arg=c("QWERTY","DVORAK","CIRCLE"),
|
|
ylab="Total Error Rate (TER)",
|
|
main="TER of layouts",
|
|
ylim=c(0, max(ter_stats[,"upper"])*1.1)
|
|
)
|
|
# Add confidence intervals
|
|
arrows(
|
|
x0=bar_pos, y0=ter_stats[,"lower"],
|
|
x1=bar_pos, y1=ter_stats[,"upper"],
|
|
angle=90, code=3, length=0.05
|
|
)
|
|
dev.off()
|
|
|
|
# WPM stats
|
|
wpm_stats <- rbind(
|
|
mean_sd(results$qwerty_wpm),
|
|
mean_sd(results$dvorak_wpm),
|
|
mean_sd(results$circle_wpm)
|
|
)
|
|
|
|
# Save WPM barplot as PDF using LaTeX-compatible fonts
|
|
suppressMessages(pdf("../figures/wpm_plot.pdf"))
|
|
bar_pos <- barplot(
|
|
wpm_stats[,"mean"],
|
|
names.arg=c("QWERTY","DVORAK","CIRCLE"),
|
|
ylab="Words per minute (WPM)",
|
|
main="WPM of layouts",
|
|
ylim=c(0, max(wpm_stats[,"upper"])*1.1)
|
|
)
|
|
arrows(
|
|
x0=bar_pos, y0=wpm_stats[,"lower"],
|
|
x1=bar_pos, y1=wpm_stats[,"upper"],
|
|
angle=90, code=3, length=0.05
|
|
)
|
|
dev.off()
|
|
@
|
|
|
|
% Include TER plot
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\columnwidth]{../figures/ter_plot.pdf}
|
|
\caption{Total Error Rate (TER) by Keyboard Layout}
|
|
\end{figure}
|
|
|
|
% Include WPM plot
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\columnwidth]{../figures/wpm_plot.pdf}
|
|
\caption{Words per Minute (WPM) by Keyboard Layout}
|
|
\end{figure}
|
|
|
|
\subsubsection{Subjective Measures}\label{subjective-measures}
|
|
|
|
<<echo=FALSE, results='hide'>>=
|
|
# Read NASA-TLX data
|
|
nasa <- read.csv("../data/nasaTLX.csv")
|
|
nasa$layout <- factor(nasa$layout)
|
|
|
|
# Save boxplots as PDF using LaTeX-compatible fonts
|
|
suppressMessages(pdf("../figures/nasa_boxplots.pdf"))
|
|
par(mfrow=c(2,3)) # Arrange plots in 2 rows x 3 columns
|
|
boxplot(mental_demand ~ layout, data=nasa, main="Mental Demand")
|
|
boxplot(physical_demand ~ layout, data=nasa, main="Physical Demand")
|
|
boxplot(performance ~ layout, data=nasa, main="Performance")
|
|
boxplot(effort ~ layout, data=nasa, main="Effort")
|
|
boxplot(frustration ~ layout, data=nasa, main="Frustration")
|
|
par(mfrow=c(1,1))
|
|
dev.off()
|
|
@
|
|
|
|
% Include NASA-TLX boxplots
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\columnwidth]{../figures/nasa_boxplots.pdf}
|
|
\caption{NASA-TLX Scores by Keyboard Layout}
|
|
\end{figure}
|
|
|
|
\subsection{Inferential Statistics}\label{inferential-statistics}
|
|
Independent var: Keyboard type
|
|
|
|
Dependent var:
|
|
\begin{itemize}
|
|
\item WPM
|
|
\item TER
|
|
\item NASA-TLX
|
|
\end{itemize}
|
|
|
|
%Anova RM for WPM
|
|
<<echo=FALSE, results='hide'>>=
|
|
library(tidyr)
|
|
|
|
# Add participant ID
|
|
results$id <- 1:nrow(results)
|
|
|
|
# --- WPM Long Format ---
|
|
wpm_long <- results %>%
|
|
select(id, qwerty_wpm, dvorak_wpm, circle_wpm) %>%
|
|
pivot_longer(
|
|
cols = -id,
|
|
names_to = "layout",
|
|
values_to = "wpm"
|
|
)
|
|
|
|
wpm_long$id <- factor(wpm_long$id)
|
|
|
|
wpm_long$layout <- factor(wpm_long$layout,
|
|
levels=c("qwerty_wpm","dvorak_wpm","circle_wpm"),
|
|
labels=c("QWERTY","DVORAK","CIRCLE"))
|
|
|
|
# --- RM ANOVA for WPM ---
|
|
anova_wpm <- aov(wpm ~ layout + Error(id/layout), data=wpm_long)
|
|
@
|
|
Anova WPM results:
|
|
<<results='asis', echo=FALSE>>=
|
|
wpm_tab <- summary(anova_wpm)[[2]][[1]]
|
|
|
|
wpm_effect <- wpm_tab["layout", , drop=FALSE]
|
|
|
|
wpm_effect$`Pr(>F)` <- "$p< .001$"
|
|
|
|
colnames(wpm_effect) <- c("Df", "Sum Sq", "Mean Sq", "F value", "p-value")
|
|
|
|
kable(wpm_effect,
|
|
format="latex",
|
|
booktabs=TRUE,
|
|
caption="Layout Effect on WPM",
|
|
escape=FALSE)
|
|
@
|
|
|
|
|
|
%Anova RM for TER
|
|
<<echo=FALSE, results='hide'>>=
|
|
|
|
# --- TER Long Format ---
|
|
ter_long <- results %>%
|
|
select(id, qwerty_ter, dvorak_ter, circle_ter) %>%
|
|
pivot_longer(
|
|
cols = -id,
|
|
names_to = "layout",
|
|
values_to = "ter"
|
|
)
|
|
|
|
ter_long$id <- factor(ter_long$id)
|
|
|
|
ter_long$layout <- factor(ter_long$layout,
|
|
levels=c("qwerty_ter","dvorak_ter","circle_ter"),
|
|
labels=c("QWERTY","DVORAK","CIRCLE"))
|
|
|
|
# --- RM ANOVA for TER ---
|
|
anova_ter <- aov(ter ~ layout + Error(id/layout), data=ter_long)
|
|
@
|
|
Anova TER results:
|
|
<<results='asis', echo=FALSE>>=
|
|
ter_tab <- summary(anova_ter)[[2]][[1]]
|
|
|
|
ter_effect <- ter_tab["layout", , drop=FALSE]
|
|
|
|
colnames(ter_effect) <- c("Df", "Sum Sq", "Mean Sq", "F value", "p-value")
|
|
|
|
kable(ter_effect,
|
|
format="latex",
|
|
booktabs=TRUE,
|
|
caption="Repeated-Measures ANOVA for TER")
|
|
@
|
|
|
|
|
|
% Post-Hoc analysis with bonferroni correction for WPM
|
|
<<echo=FALSE, results='hide'>>=
|
|
suppressMessages(library(emmeans))
|
|
|
|
suppressMessages(emm_wpm <- emmeans(anova_wpm, ~ layout))
|
|
|
|
posthoc <- pairs(emm_wpm, adjust = "bonferroni")
|
|
|
|
print(posthoc)
|
|
@
|
|
|
|
\subsubsection{Objective Measures}\label{objective-measures-1}
|
|
|
|
\subsubsection{Subjective Measures}\label{subjective-measures-1}
|
|
|
|
\section{Discussion}\label{discussion}
|
|
|
|
\printbibliography
|
|
\end{document}
|