// calculate medians and save results public void finish() { /* calculate medians */ int[] reactTimesCorrect = new int[totalCorrect]; int[] reactTimesIncorrect = new int[totalCompleted - totalCorrect]; int rtcIndex = 0, rtiIndex = 0; for (int i = 0; i < totalCompleted; i++) { if (trials[i].correct) { reactTimesCorrect[rtcIndex++] = trials[i].reactTime; } else { reactTimesIncorrect[rtiIndex++] = trials[i].reactTime; } } this.mrtCorrect = CogTest.findMedian(ref reactTimesCorrect); this.mrtIncorrect = CogTest.findMedian(ref reactTimesIncorrect); saveResultsFile(); }
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); CogTest.Run(); }
// load form - align elements and set up test private void frmStroop_Load(object sender, EventArgs e) { CogTest.setControlVisibility(this, false); if (this.testStatus == CogTest.TEST_DEMO) { // demo screen - show three different labels Point center = new Point(this.ClientSize.Width / 2, this.ClientSize.Height / 2); lblDisplay.Text = "55555"; lblDisplay.Left = (ClientSize.Width - lblDisplay.Width) / 2; lblDisplay.Top = (ClientSize.Height - lblDisplay.Height) / 2 + 100; Label lblDemo1 = new Label(); Label lblDemo2 = new Label(); this.addLabel(lblDemo1, "3333", new Point( (center.X - lblDisplay.Width) / 2, center.Y - lblDisplay.Height - 100)); this.addLabel(lblDemo2, "444", new Point( (center.X + lblDemo1.Left), center.Y - lblDisplay.Height - 100)); this.BackColor = CogTest.DEMO_COLOR; CogTest.enableDoubleEnterAdvance(this); CogTest.setControlVisibility(this, true); } else { lblDisplay.Left = (ClientSize.Width - lblDisplay.Width) / 2; lblDisplay.Top = (ClientSize.Height - lblDisplay.Height) / 2; // practice test - 1 block with 16 trials (8 congruent, 8 incongruent) // or official test - 4 blocks with 32 trials (16 congruent, 16 incongruent) curTest = (this.testStatus == CogTest.TEST_PRACTICE) ? new StroopTest(1, 16) : new StroopTest(4, 32); showFixation(); CogTest.setControlVisibility(this, true); } }
/// <summary> /// Displays a warning dialog box if the user triggered the FormClosing event. /// To close the form normally, use CogTest.closeForm() /// </summary> public static void FormClosing(object sender, FormClosingEventArgs e) { Form form = (Form)sender; enterStopwatch.Reset(); if (form.DialogResult == DialogResult.Cancel) { DialogResult result = MessageBox.Show("Are you sure you want to quit the program early?" + Environment.NewLine + "The data for each of the completed tests has already been saved," + Environment.NewLine + "but all of the data for the current test will be lost.", "Cognitive Assessments - Quit Program", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2); if (result == DialogResult.Yes) { // we have to sleep for a second before closing or Environment.Exit throws the following error: // "Cannot execute operation because current thread is in a spin, wait, or sleep operation CogTest.closeForm(form); Environment.Exit(1); } else { e.Cancel = true; } } }
// check keypress and ignore anything that isn't a number void txtInput_KeyPress(object sender, KeyPressEventArgs e) { if (CogTest.ValidateKeyPress() == false || e.KeyChar < 49 || e.KeyChar > 57) { e.Handled = true; } }
private void btnSubmit_Click(object sender, EventArgs e) { // at this point, the only way they could be wrong that we didn't catch in btnClick // is if they didn't finish the sequence // don't do anything if we are in demo mode if (this.testStatus == CogTest.TEST_DEMO) { return; } if (curIndex < answerSeq.Count) { correct = false; } setEnabledStatus(false); if (corsi.nextTrial(correct, ref answerSeq) == true) { // there is another trial - run it System.Threading.Thread.Sleep(500); // wait about 500 ms between trials showNextTrial(); } else { // end of test if (this.testStatus == CogTest.TEST_OFFICIAL) { corsi.finishTest(); } CogTest.closeForm(this); } }
// check the official test stopwatch every second // quit early if the test takes longer than 10 minutes private void testTimer_Tick(object sender, EventArgs e) { if (stopwatch.ElapsedMilliseconds >= 600000) { testTimer.Stop(); saveResultsFile(); CogTest.closeForm(this); } }
// main splash screen (blue) public static void mainSplash(string name, Form owner) { frmSplash frm = new frmSplash(); frm.lblName.Text = name; frm.lblInstruct.Visible = false; frm.BackColor = Color.FromArgb(0, 0, 64); CogTest.enableDoubleEnterAdvance(frm); frm.ShowDialog(owner); }
// official test splash screen (green) public static void testSplash(string name, Form owner) { frmSplash frm = new frmSplash(); frm.lblName.Text = name; frm.lblInstruct.Visible = true; frm.lblInstruct.Text = "Official Test"; frm.BackColor = Color.FromArgb(0, 64, 0); CogTest.enableDoubleEnterAdvance(frm); frm.ShowDialog(owner); }
// final splash screen (yellow) public static void finalSplash(Form owner) { frmSplash frm = new frmSplash(); frm.lblName.Text = "The End"; frm.lblInstruct.Visible = true; frm.lblInstruct.Text = "Thank you!"; frm.BackColor = Color.FromArgb(64, 64, 0); CogTest.enableDoubleEnterAdvance(frm); frm.ShowDialog(owner); }
private void frmRaven_KeyPress(object sender, KeyPressEventArgs e) { // accept either 1-6 or 1-8 if (this.testStatus != CogTest.TEST_DEMO && CogTest.ValidateKeyPress() == true) { if (e.KeyChar >= 49 && (e.KeyChar <= 54 || e.KeyChar <= 56 && lbl7.Visible == true)) { processInput((e.KeyChar - 48) == answer); } } }
public int span3, span4, span5, span6, span7; // number correct for a span of 3, 4, 5, etc #region Test Creation public CorsiTest(int numTrials, bool isPractice, ref ArrayList nextIndexes) { this.rand = new Random(); this.numTrials = numTrials; this.trials = createTrials(numTrials, isPractice); this.span3 = 0; this.span4 = 0; this.span5 = 0; this.span6 = 0; this.span7 = 0; this.curTrialIndex = 0; nextIndexes = CogTest.createRandomList(0, 8, trials[0].spanLength, ref rand); }
/* generate 10 unique <key, value> string pairs, * as well as 5 questions: each question has 4 options, * only one of which is correct */ public Dictionary <string, string> generateGrid(out string[] answers, out string[,] options) { // create the main grid Dictionary <string, string> dict = new Dictionary <string, string>(10); for (int i = 1; i <= 10; i++) { FindRandoms: string num = rand.Next(1000, 10000).ToString(); string str = randString(); if (dict.Keys.Contains(num) || dict.Values.Contains(str)) { goto FindRandoms; } dict.Add(num, str); } // pick 5 unique answers ArrayList answerIndexes = CogTest.createRandomList(0, 9, 5, ref rand); options = new string[5, 4]; answers = new string[5]; // pick 4 options for each question (one of which is correct) for (int i = 0; i < 5; i++) { answers[i] = dict.ElementAt((int)answerIndexes[i]).Value; // choose which option will be the correct answer options[i, rand.Next(0, 4)] = dict.ElementAt((int)answerIndexes[i]).Key; // set other possible options (must be different from correct answer) GenerateOtherOptions: ArrayList dictIndexes = CogTest.createRandomList(0, 9, 3, ref rand); if (dictIndexes.Contains((int)answerIndexes[i])) { goto GenerateOtherOptions; } int arrayListIndex = 0; for (int j = 0; j < 4; j++) { if (options[i, j] == null) { options[i, j] = dict.ElementAt((int)dictIndexes[arrayListIndex++]).Key; } } } return(dict); }
private void frmSpeed_Load(object sender, EventArgs e) { grid[0] = lbl0; grid[1] = lbl1; grid[2] = lbl2; grid[3] = lbl3; grid[4] = lbl4; grid[5] = lbl5; grid[6] = lbl6; grid[7] = lbl7; grid[8] = lbl8; grid[9] = lbl9; btns[0] = btnA; btns[1] = btnB; btns[2] = btnC; btns[3] = btnD; lblBtns[0] = lblBtnA; lblBtns[1] = lblBtnB; lblBtns[2] = lblBtnC; lblBtns[3] = lblBtnD; CogTest.setControlVisibility(this, false); alignElements(); if (testStatus == CogTest.TEST_DEMO) { // demo screen - use what's in the designer this.BackColor = CogTest.DEMO_COLOR; CogTest.enableDoubleEnterAdvance(this); CogTest.setControlVisibility(this, true); lblQuestion.Focus(); } else { // display the actual test newGrid(); nextTrial(); formTimer.Interval = STOPWATCH_CHECK_INTVL; CogTest.setControlVisibility(this, true); lblQuestion.Focus(); formTimer.Start(); testStopwatch.Start(); } }
/// <summary> /// Closes form after a double tap on the enter key. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> static void KeyUp(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { if (enterStopwatch.IsRunning && enterStopwatch.ElapsedMilliseconds <= DOUBLE_ENTER_INTVL) { // successful double-tap on the enter key - close form CogTest.closeForm(currentSplashForm); } else { // first enter key pressed - start stopwatch to wait for second press enterStopwatch.Reset(); enterStopwatch.Start(); } } }
// process input and return true if there are more trials public bool nextTrial(bool correct, ref ArrayList nextIndexes) { trials[curTrialIndex].correct = correct; // update global counter for appropriate span length if (correct == true) { switch (trials[curTrialIndex].spanLength) { case 3: span3++; break; case 4: span4++; break; case 5: span5++; break; case 6: span6++; break; case 7: span7++; break; } } curTrialIndex++; if (curTrialIndex == numTrials) { // no trials left - end of the current test return(false); } else { nextIndexes = CogTest.createRandomList(0, 8, trials[curTrialIndex].spanLength, ref rand); return(true); } }
/* Timer tick - either the practice test ended, or it's time to check the official test stopwatch. * A form timer is not used for the official test because form timers aren't very accurate * for long intervals (more than a minute). */ private void formTimer_Tick(object sender, EventArgs e) { if (this.testStatus == CogTest.TEST_PRACTICE) { if (testStopwatch.ElapsedMilliseconds >= PRACTICE_DUARTION) { // practice test ended CogTest.closeForm(this); } } else if (this.testStatus == CogTest.TEST_OFFICIAL) { if (testStopwatch.ElapsedMilliseconds >= OFFICIAL_DURATION) { // regular test ended test.finish(); CogTest.closeForm(this); } } }
private void frmKeyboardTutorial_Load(object sender, EventArgs e) { CogTest.setControlVisibility(this, false); Point center = new Point(ClientSize.Width / 2, ClientSize.Height / 2); btnContinue.Top = 20; btnContinue.Left = ClientSize.Width - btnContinue.Width - 20; lblDisplay.Left = center.X - lblDisplay.Width / 2; lblDisplay.Top = center.Y - lblDisplay.Height - 50; txtInput.Left = center.X - txtInput.Width / 2; txtInput.Top = center.Y + 50; txtInput.Text = ""; nextNumber(); CogTest.setControlVisibility(this, true); txtInput.Focus(); }
// pick a new number to display private void nextNumber() { if (numFinished == MAX_NUMBERS) { // finished all of the trials - close form CogTest.closeForm(this); } else { string newDigit; do { newDigit = randGen.Next(1, 10).ToString(); } while (newDigit == txtInput.Text); lblDisplay.Text = newDigit; txtInput.Enabled = true; txtInput.Text = ""; txtInput.Focus(); } }
/* ========== This is the top level execution sequence =========*/ void frmBase_Shown(object sender, EventArgs e) { // randomize the test ordering System.Collections.ArrayList order = CogTest.createRandomList(1, 4, 4, ref rand); frmSplash.mainSplash("Keyboard Training", this); frmKeyboardTutorial keyTut = new frmKeyboardTutorial(); keyTut.ShowDialog(this); dispatch((int)order[0]); frmSplash.breakSplash(this); dispatch((int)order[1]); frmSplash.breakSplash(this); dispatch((int)order[2]); frmSplash.breakSplash(this); dispatch((int)order[3]); frmSplash.finalSplash(this); Environment.Exit(0); }
private void frmCorsi_Load(object sender, EventArgs e) { boxes[0] = btn0; boxes[1] = btn1; boxes[2] = btn2; boxes[3] = btn3; boxes[4] = btn4; boxes[5] = btn5; boxes[6] = btn6; boxes[7] = btn7; boxes[8] = btn8; CogTest.setControlVisibility(this, false); setupForm(); if (testStatus == CogTest.TEST_DEMO) { // show demo screen this.BackColor = CogTest.DEMO_COLOR; CogTest.enableDoubleEnterAdvance(this); CogTest.setControlVisibility(this, true); btnSubmit.Visible = false; panel.Focus(); } else { // practice test has 3 trials, official test has 15 corsi = (this.testStatus == CogTest.TEST_PRACTICE) ? new CorsiTest(3, true, ref answerSeq) : new CorsiTest(15, false, ref answerSeq); CogTest.setControlVisibility(this, true); foreach (Button btn in boxes) { btn.Visible = true; } setEnabledStatus(false); System.Threading.Thread.Sleep(1500); // wait about 1.5 seconds before showing the first trial showNextTrial(); } }
// process a keypress during the test private void frmStroop_KeyPress(object sender, KeyPressEventArgs e) { // only allow non-numpad number keys to be pressed, and only while a test is running if (e.KeyChar >= 49 && e.KeyChar <= 57 && stopwatch.IsRunning && CogTest.ValidateKeyPress() == true) { stopwatch.Stop(); int elapsedTime = (int)stopwatch.ElapsedMilliseconds; stopwatch.Reset(); if (curTest.processTrial(e.KeyChar - 48, elapsedTime) == true) { // there is another trial to run showFixation(); } else if (curTest.processBlock() == true) { // advance to the next block after a 30 second break lblDisplay.BorderStyle = BorderStyle.None; lblDisplay.Text = "00:30"; lblDisplay.Font = fntNormal; break_time = 30; breakTimer.Interval = 1000; breakTimer.Start(); } else { // we have reached the end of the current test if (testStatus == CogTest.TEST_OFFICIAL) { // save the data only if it is an official test curTest.finish(); } CogTest.closeForm(this); } } }
// write results to a text file private void saveResultsFile() { /* ----- write all of the raw trial data to a new file -------- */ string rawFilename = "subj" + CogTest.uid + "corsi.txt"; System.IO.StreamWriter rawFile = new System.IO.StreamWriter(rawFilename); for (int i = 0; i < numTrials; i++) { string line = CogTest.uid + ',' + trials[i].spanLength.ToString() + ',' + CogTest.boolToChar(trials[i].correct); rawFile.WriteLine(line); } rawFile.Close(); /* ----- append the summary data to corsiSummary.txt -------- */ System.IO.StreamWriter summaryFile = new System.IO.StreamWriter("corsiSummary.txt", true); string summaryLine = CogTest.uid + ',' + span3.ToString() + ',' + span4.ToString() + ',' + span5.ToString() + ',' + span6.ToString() + ',' + span7.ToString(); summaryFile.WriteLine(summaryLine); summaryFile.Close(); }
// write results to a text file private void saveResultsFile() { /* ----- write all of the raw trial data to a new file -------- */ string rawFilename = "subj" + CogTest.uid + "speed.txt"; System.IO.StreamWriter rawFile = new System.IO.StreamWriter(rawFilename); for (int i = 0; i < totalCompleted; i++) { string line = CogTest.uid + ',' + trials[i].trialNum.ToString() + ',' + trials[i].reactTime.ToString() + ',' + CogTest.boolToChar(trials[i].correct); rawFile.WriteLine(line); } rawFile.Close(); /* ----- append the summary data to speedSummary.txt -------- */ System.IO.StreamWriter summaryFile = new System.IO.StreamWriter("speedSummary.txt", true); string summaryLine = CogTest.uid + ',' + totalCorrect.ToString() + ',' + totalCompleted.ToString() + ',' + mrtCorrect.ToString() + ',' + mrtIncorrect.ToString() + ',' + trtCorrect.ToString() + ',' + trtIncorrect.ToString(); summaryFile.WriteLine(summaryLine); summaryFile.Close(); }
private void processInput(bool correct) { // double clicks (within 350 ms) are ignored if (doublePress == true) { return; } if (this.testStatus == CogTest.TEST_OFFICIAL) { if (correct == true) { numCorrect++; } } numUnfinished--; questions.RemoveAt(0); if (numUnfinished == 0) { // finished with the test if (this.testStatus == CogTest.TEST_OFFICIAL) { saveResultsFile(); } CogTest.closeForm(this); } else { // load the next question showNextQuestion(); doublePress = true; clickTimer.Start(); picBox.Focus(); // focus away from the buttons } }
private void frmSpeed_KeyPress(object sender, KeyPressEventArgs e) { if (reactStopwatch.IsRunning && testStatus != CogTest.TEST_DEMO && CogTest.ValidateKeyPress() == true) { switch (e.KeyChar) { case (char)49: // the '1' key processInput(btnA.Text); break; case (char)50: // the '2' key processInput(btnB.Text); break; case (char)51: // the '3' key processInput(btnC.Text); break; case (char)52: // the '4' key processInput(btnD.Text); break; } } }
// close break screen after BREAK_TIME milliseconds private void breakTimer_Tick(object sender, EventArgs e) { CogTest.closeForm(this); }
private void frmRaven_Load(object sender, EventArgs e) { CogTest.setControlVisibility(this, false); rand = new Random(); btns = new Button[8]; btns[0] = btn0; btns[1] = btn1; btns[2] = btn2; btns[3] = btn3; btns[4] = btn4; btns[5] = btn5; btns[6] = btn6; btns[7] = btn7; lbls = new Label[8]; lbls[0] = lbl0; lbls[1] = lbl1; lbls[2] = lbl2; lbls[3] = lbl3; lbls[4] = lbl4; lbls[5] = lbl5; lbls[6] = lbl6; lbls[7] = lbl7; // align main picture box picBox.Width = 550; picBox.Height = Math.Min((int)(this.ClientSize.Height / 2.5), 440); picBox.Left = (ClientSize.Width - picBox.Width) / 2; picBox.Top = 20;//-20; // test summary data numCorrect = 0; switch (this.testStatus) { case CogTest.TEST_DEMO: // show what is currently on form for demo mode this.BackColor = CogTest.DEMO_COLOR; CogTest.enableDoubleEnterAdvance(this); alignButtons(8); CogTest.setControlVisibility(this, true); break; case CogTest.TEST_PRACTICE: questions = new ArrayList(2); questions.Add(-1); questions.Add(-2); numUnfinished = 2; CogTest.setControlVisibility(this, true); showNextQuestion(); break; case CogTest.TEST_OFFICIAL: questions = CogTest.createRandomList(1, 10, 10, ref rand); numUnfinished = 10; // set visibility before loading the question because the question may only need 6 butons CogTest.setControlVisibility(this, true); showNextQuestion(); testTimer.Start(); stopwatch.Start(); break; } picBox.Focus(); }
private void btnContinue_Click(object sender, EventArgs e) { CogTest.closeForm(this); }