)>}]
شركة التطبيقات المتكاملة لتصميم وبرمجة البرمجيات الخاصة ش.ش.و.
Integrated Applications Programming Company
Skip Navigation LinksHome » Code Library » Test

Public general use code classes and xml files that we've compiled and used over the years:

Test Class

    1: using System.Data;
    2:  
    3: namespace Ia.TentPlay.Cl.Model.Memorise
    4: {
    5:     ////////////////////////////////////////////////////////////////////////////
    6:  
    7:     /// <summary publish="true">
    8:     /// Test Class
    9:     /// </summary>
   10:     /// <value>
   11:     /// https://msdn.microsoft.com/en-us/library/z1hkazw7(v=vs.100).aspx
   12:     /// </value>
   13:     /// <remarks> 
   14:     /// Copyright © 2008-2018 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
   15:     ///
   16:     /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
   17:     /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
   18:     ///
   19:     /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
   20:     /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   21:     /// 
   22:     /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
   23:     /// 
   24:     /// Copyright notice: This notice may not be removed or altered from any source distribution.
   25:     /// </remarks> 
   26:     public abstract class Test
   27:     {
   28:         protected static Random random = new Random(DateTime.UtcNow.Second);
   29:  
   30:         protected static int NumberOfMinutesThatMustPassBeforeAWordIsTestedAgain = 3;
   31:  
   32:         protected static TimeSpan ResponseSecondsThatIndicateMemorizationTimeSpan
   33:         {
   34:             get
   35:             {
   36:                 return TimeSpan.Parse("00:00:03"); // three seconds indicate memorization
   37:             }
   38:         }
   39:  
   40:         //static int numberOfCumulativeAnswerCorrectnessIndicatorThatIndicatesRetention = 7;
   41:         //static int numberOfPoolWords = 7 * 7;
   42:         protected abstract TestTopic testTopic { get; }
   43:  
   44:         // below: order is very important
   45:         /// </summary>
   46:         public enum TestTopic { MorseCode = 0, German = 1, Math = 2, Kanji = 3, Russian = 4, Kana = 5, PhoneticAlphabet = 6 };
   47:  
   48:         /// </summary>
   49:         public enum TestOption { PrefereOrderByAscendingId, PreferRandom }
   50:  
   51:         /// </summary>
   52:         public enum AnswerType { Correct, CorrectButSlow, Incorrect }
   53:  
   54:         /*
   55:          * Calculate and return the proper words withing a proper question range based on the test taking history from the database
   56:          * 
   57:          * - Initially all words will have Enabled = false.
   58:          * - The process will assign a pool of enabled words for testing.
   59:          * - At any time the user will be memorizing the pool of words only.
   60:          * - If a word is consedered memorised by its test history it will exit the word testing pool and another will be randomly added
   61:          */
   62:  
   63:         ////////////////////////////////////////////////////////////////////////////
   64:  
   65:         /// <summary>
   66:         ///
   67:         /// </summary>
   68:         public Test() { }
   69:  
   70:         ////////////////////////////////////////////////////////////////////////////
   71:  
   72:         /// <summary>
   73:         ///
   74:         /// </summary>
   75:         public void CalculatedTestQuestionAndOptions(TestOption testOption, out Ia.TentPlay.Cl.Model.Memorise.Score testQuestion, out List<Ia.TentPlay.Cl.Model.Memorise.Score> optionList, out string debug)
   76:         {
   77:             int testQuestionTypeId, testQuestionId, optionIndex1, optionIndex2, optionIndex3;
   78:             DateTime timeMinusMinutesThatMustPassBeforeAWordIsTestedAgainDateTime;
   79:             List<Ia.TentPlay.Cl.Model.Memorise.Score> questionList;
   80:  
   81:             debug = "";
   82:             optionIndex1 = optionIndex2 = optionIndex3 = 0;
   83:             optionList = new List<Ia.TentPlay.Cl.Model.Memorise.Score>();
   84:  
   85:             timeMinusMinutesThatMustPassBeforeAWordIsTestedAgainDateTime = DateTime.UtcNow.AddHours(3).AddMinutes(-NumberOfMinutesThatMustPassBeforeAWordIsTestedAgain);
   86:  
   87:             testQuestionTypeId = WeightedRandomTypeIdAccordingTypeDistribution(Guid.Empty);
   88:  
   89:             using (var db = new Ia.TentPlay.Db())
   90:             {
   91:                 if (testOption == TestOption.PreferRandom || testOption == TestOption.PrefereOrderByAscendingId)
   92:                 {
   93:                     if (testOption == TestOption.PreferRandom)
   94:                     {
   95:                         testQuestion = (from s in db.Scores
   96:                                         where s.TestId == (int)testTopic && s.TypeId == testQuestionTypeId && s.Viewed < timeMinusMinutesThatMustPassBeforeAWordIsTestedAgainDateTime
   97:                                         orderby s.CumulativeAnswerCorrectnessIndicator, s.NumberOfTimesAsked, s.NumberOfConsecutiveCorrects, s.UserId ascending
   98:                                         select s).Take(5).FirstOrDefault();
   99:  
  100:                         if (testQuestion == null)
  101:                         {
  102:                             testQuestion = (from s in db.Scores
  103:                                             where s.TestId == (int)testTopic && s.TypeId == testQuestionTypeId
  104:                                             orderby s.CumulativeAnswerCorrectnessIndicator, s.NumberOfTimesAsked, s.NumberOfConsecutiveCorrects, s.UserId ascending
  105:                                             select s).Take(5).FirstOrDefault();
  106:                         }
  107:                     }
  108:                     else if (testOption == TestOption.PrefereOrderByAscendingId)
  109:                     {
  110:                         testQuestion = (from s in db.Scores
  111:                                         where s.TestId == (int)testTopic && s.TypeId == testQuestionTypeId && s.Viewed < timeMinusMinutesThatMustPassBeforeAWordIsTestedAgainDateTime
  112:                                         orderby s.CumulativeAnswerCorrectnessIndicator, s.NumberOfTimesAsked, s.NumberOfConsecutiveCorrects, s.Id, s.UserId ascending
  113:                                         select s).Take(5).FirstOrDefault();
  114:  
  115:                         if (testQuestion == null)
  116:                         {
  117:                             testQuestion = (from s in db.Scores
  118:                                             where s.TestId == (int)testTopic && s.TypeId == testQuestionTypeId
  119:                                             orderby s.CumulativeAnswerCorrectnessIndicator, s.NumberOfTimesAsked, s.NumberOfConsecutiveCorrects, s.Id, s.UserId ascending
  120:                                             select s).Take(5).FirstOrDefault();
  121:                         }
  122:                     }
  123:                     else
  124:                     {
  125:                         throw new Exception("Unrecognized test option");
  126:                     }
  127:  
  128:                     if (testQuestion != null)
  129:                     {
  130:                         testQuestionId = testQuestion.Id;
  131:                         testQuestionTypeId = testQuestion.TypeId;
  132:  
  133:                         // below: update Viewed
  134:                         testQuestion.Viewed = DateTime.UtcNow.AddHours(3);
  135:                         db.SaveChanges();
  136:  
  137:                         questionList = (from s in db.Scores where s.TestId == (int)testTopic && s.TypeId == testQuestionTypeId && s.Id != testQuestionId select s).ToList();
  138:  
  139:                         if (questionList.Count > 0)
  140:                         {
  141:                             // below: select random, non-similar numbers
  142:                             while (optionIndex1 == optionIndex2 || optionIndex1 == optionIndex3 || optionIndex2 == optionIndex3 || questionList[optionIndex1].Answer == testQuestion.Answer || questionList[optionIndex2].Answer == testQuestion.Answer || questionList[optionIndex3].Answer == testQuestion.Answer)
  143:                             {
  144:                                 optionIndex1 = random.Next(questionList.Count);
  145:                                 optionIndex2 = random.Next(questionList.Count);
  146:                                 optionIndex3 = random.Next(questionList.Count);
  147:                             }
  148:  
  149:                             optionList.Add(questionList[optionIndex1]);
  150:                             optionList.Add(questionList[optionIndex2]);
  151:                             optionList.Add(questionList[optionIndex3]);
  152:  
  153:                             // below: insert the correct answer randomally
  154:                             optionList.Insert(random.Next(optionList.Count + 1), testQuestion);
  155:                         }
  156:                         else
  157:                         {
  158:                             throw new Exception("questionList.Count == 0");
  159:                         }
  160:                     }
  161:                     else
  162:                     {
  163:                         throw new Exception("testQuestion == null");
  164:                     }
  165:                 }
  166:                 else
  167:                 {
  168:                     throw new Exception("Unrecognized test option");
  169:                 }
  170:             }
  171:         }
  172:  
  173:         ////////////////////////////////////////////////////////////////////////////
  174:  
  175:         /// <summary>
  176:         ///
  177:         /// </summary>
  178:         public Ia.TentPlay.Cl.Model.Memorise.Test.AnswerType CheckSelectedAnswerToQuestion(Ia.TentPlay.Cl.Model.Memorise.Score testQuestion, Ia.TentPlay.Cl.Model.Memorise.Score selectedOption, TimeSpan responseTimeSpan, out string debug)
  179:         {
  180:             Ia.TentPlay.Cl.Model.Memorise.Test.AnswerType answerType;
  181:  
  182:             using (var db = new Ia.TentPlay.Db())
  183:             {
  184:                 testQuestion = db.Scores.FirstOrDefault(q => q.Id == testQuestion.Id);
  185:  
  186:                 debug = "timeSpan: " + responseTimeSpan.TotalSeconds + "; cu: " + testQuestion.CumulativeAnswerCorrectnessIndicator + "; num ask: " + testQuestion.NumberOfTimesAsked + "; num con cu: " + testQuestion.NumberOfConsecutiveCorrects + "; av cu:" + string.Format("{0:0.00}", AverageCumulativeAnswerCorrectnessIndicator());
  187:  
  188:                 if (testQuestion.Answer == selectedOption.Answer)
  189:                 {
  190:                     if (responseTimeSpan < ResponseSecondsThatIndicateMemorizationTimeSpan)
  191:                     {
  192:                         testQuestion.CumulativeAnswerCorrectnessIndicator++;
  193:                         testQuestion.NumberOfConsecutiveCorrects++;
  194:  
  195:                         answerType = Ia.TentPlay.Cl.Model.Memorise.Test.AnswerType.Correct;
  196:                     }
  197:                     else
  198:                     {
  199:                         answerType = Ia.TentPlay.Cl.Model.Memorise.Test.AnswerType.CorrectButSlow;
  200:                     }
  201:                 }
  202:                 else
  203:                 {
  204:                     testQuestion.CumulativeAnswerCorrectnessIndicator--;
  205:                     testQuestion.NumberOfConsecutiveCorrects = 0;
  206:  
  207:                     answerType = Ia.TentPlay.Cl.Model.Memorise.Test.AnswerType.Incorrect;
  208:                 }
  209:  
  210:                 testQuestion.Updated = testQuestion.Viewed = DateTime.UtcNow.AddHours(3);
  211:                 testQuestion.NumberOfTimesAsked++;
  212:  
  213:                 db.SaveChanges();
  214:             }
  215:  
  216:             return answerType;
  217:         }
  218:  
  219:         ////////////////////////////////////////////////////////////////////////////
  220:  
  221:         /// <summary>
  222:         ///
  223:         /// </summary>
  224:         public double AverageCumulativeAnswerCorrectnessIndicator()
  225:         {
  226:             double average;
  227:  
  228:             average = 0;
  229:  
  230:             using (var db = new Ia.TentPlay.Db())
  231:             {
  232:                 average = (from s in db.Scores where s.TestId == (int)testTopic select s.CumulativeAnswerCorrectnessIndicator).Average();
  233:             }
  234:  
  235:             return average;
  236:         }
  237:  
  238:         ////////////////////////////////////////////////////////////////////////////
  239:  
  240:         /// <summary>
  241:         ///
  242:         /// </summary>
  243:         public abstract void PopulateTestDatabaseTableWithInitialQuestionsIfEmpty(Guid userId);
  244:  
  245:         ////////////////////////////////////////////////////////////////////////////
  246:  
  247:         /// <summary>
  248:         ///
  249:         /// </summary>
  250:         public abstract int WeightedRandomTypeIdAccordingTypeDistribution(Guid userId);
  251:  
  252:         ////////////////////////////////////////////////////////////////////////////
  253:  
  254:         /// <summary>
  255:         ///
  256:         /// </summary>
  257:         public void DeleteTestRecordsOfUser(Guid userId)
  258:         {
  259:             using (var db = new Ia.TentPlay.Db())
  260:             {
  261:                 //db.Database.ExecuteSqlCommand("delete from Scores where userId = {0}", userId);
  262:             }
  263:         }
  264:  
  265:         ////////////////////////////////////////////////////////////////////////////
  266:         ////////////////////////////////////////////////////////////////////////////    
  267:     }
  268:  
  269:     ////////////////////////////////////////////////////////////////////////////
  270:     ////////////////////////////////////////////////////////////////////////////   
  271: }