public void AlphaNumericWithNumericCodesShouldSkipBadCodes() { int attemptCombination = 0; try { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 600; i++) { attemptCombination = i; code = AttendanceCodeService.GetNew(2, 0, 3, true); codeList.Add(code.Code); } var matches = codeList.Where(c => AttendanceCodeService.noGood.Any(ng => c.Contains(ng))); bool hasMatchIsBad = matches.Any(); Assert.IsFalse(hasMatchIsBad, "bad codes were: " + string.Join(", ", matches)); } catch (TimeoutException) { // If an infinite loop was detected, but we tried at least 600 codes then // we'll consider this a pass. Assert.IsTrue(attemptCombination >= 600); } }
public void NumericCodeWithLengthOf2ShouldNotGoBeyond99() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); try { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 101; i++) { code = AttendanceCodeService.GetNew(0, 0, 2, false); codeList.Add(code.Code); } // should not be longer than 2 characters // This is a known bug in v7.4 and earlier, and possibly fixed via PR #3071 Assert.That.IsTrue(codeList.Last().Length == 2, "last code was " + codeList.Last().Length + " characters long."); } catch (TimeoutException) { // An exception in this case is considered better than hanging (since there is // no actual solution). Assert.That.IsTrue(true); } finally { stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test NumericCodeWithLengthOf2ShouldNotGoBeyond99 took {0} ms.", stopWatch.ElapsedMilliseconds)); } }
public void RequestingMoreCodesThanPossibleShouldThrowException() { var codeList = new List <string>(); AttendanceCode code = null; // Generate 99 codes (the maximum number of valid codes). for (int i = 0; i < 100; i++) { code = AttendanceCodeService.GetNew(0, 0, 2, true); codeList.Add(code.Code); } // Now try to generate one more... which should NOT hang but instead, may // throw one of two exceptions. try { code = AttendanceCodeService.GetNew(0, 0, 2, true); } catch (InvalidOperationException) { Assert.IsTrue(true); } catch (TimeoutException) { // An exception in this case is considered better than hanging (since there is // no actual solution). Assert.IsTrue(true); } }
public void AlphaOnlyCodesShouldNotRepeat() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); var codeList = new List <string>(); AttendanceCode code = null; // 4847 (17*17*17 minus ~50 bad codes) possible combinations of 17 letters for (int i = 0; i < 4860; i++) { //System.Diagnostics.Debug.WriteIf( i > 4700, "code number " + i + " took... " ); code = AttendanceCodeService.GetNew(0, 3, 0, false); codeList.Add(code.Code); //System.Diagnostics.Debug.WriteLineIf( i > 4700, "" ); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.That.IsTrue(duplicates.Count() == 0); stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test AlphaOnlyCodesShouldNotRepeat took {0} ms.", stopWatch.ElapsedMilliseconds)); }
public void RandomNumericCodesShouldNotRepeat() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 998; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, true); codeList.Add(code.Code); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.That.IsTrue(duplicates.Count() == 0, "repeated codes: " + string.Join(", ", duplicates)); stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test RandomNumericCodesShouldNotRepeat took {0} ms.", stopWatch.ElapsedMilliseconds)); }
public void TwoAlphaWithFourRandomNumericCodesShouldSkipBadCodes() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); int attemptCombination = 0; var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 2500; i++) { attemptCombination = i; code = AttendanceCodeService.GetNew(0, 2, 4, true); codeList.Add(code.Code); } // TODO: Once the combination of codes issue is addressed, this next line should be uncommented // and replace the one below it: //var matches = codeList.Where( c => AttendanceCodeService.noGood.Any( ng => c.Contains( ng ) ) ); var matches = codeList.Select(x => x).Intersect(AttendanceCodeService.noGood); bool hasMatchIsBad = matches.Any(); Assert.That.IsFalse(hasMatchIsBad, "bad codes were: " + string.Join(", ", matches)); stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test AlphaOnlyWithNumericOnlyCodesShouldSkipBadCodes took {0} ms.", stopWatch.ElapsedMilliseconds)); }
public void NumericCodeWithLengthOf2ShouldNotGoBeyond99() { Cleanup(); try { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 101; i++) { code = AttendanceCodeService.GetNew(0, 0, 2, false); codeList.Add(code.Code); } // should not be longer than 4 characters // This is a known bug in v7.4 and earlier, and possibly fixed via PR #3071 Assert.True(codeList.Last().Length == 4); } catch (TimeoutException) { // An exception in this case is considered better than hanging (since there is // no actual solution). Assert.True(true); } }
public void AlphaNumericWithNumericCodesShouldSkipBadCodes() { Cleanup(); int attemptCombination = 0; try { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 676; i++) { attemptCombination = i; code = AttendanceCodeService.GetNew(2, 0, 2, true); codeList.Add(code.Code); } bool hasMatchIsBad = codeList.Where(c => noGood.Any(ng => c.Contains(ng))).Any(); Assert.False(hasMatchIsBad); } catch (TimeoutException) { // If an infinite loop was detected, but we tried at least 616 codes then // we'll consider this a pass. Assert.True(attemptCombination >= 616); } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public static AttendanceCode GetNew(int codeLength = 3) { string code = string.Empty; var attendanceCode = new AttendanceCode(); var rockContext = new Rock.Data.RockContext(); var service = new AttendanceCodeService( rockContext ); // Make sure only one instance at a time is checking for unique code lock (obj) { // Find a good unique code for today while ( code == string.Empty || noGood.Any( s => s == code ) || service.Get( RockDateTime.Today, code ).Any() ) { code = GenerateRandomCode( codeLength ); } attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); } return attendanceCode; }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public AttendanceCode GetNew(int codeLength = 3) { string code = string.Empty; var attendanceCode = new AttendanceCode(); // Make sure only one instance at a time is checking for unique code lock (obj) { // Find a good unique code for today while ( code == string.Empty || noGood.Any( s => s == code ) || Get(DateTime.Today, code).Any()) { code = GenerateRandomCode( codeLength ); } attendanceCode.IssueDateTime = DateTime.Now; attendanceCode.Code = code; this.Add( attendanceCode, null ); this.Save( attendanceCode, null ); } return attendanceCode; }
public void AlphaNumericWith1NumericCodeShouldGenerateAtLeast5100Codes() { int attemptCombination = 0; var stopWatch = new System.Diagnostics.Stopwatch(); var stopWatchSingle = new System.Diagnostics.Stopwatch(); stopWatch.Start(); stopWatchSingle.Start(); var outputDebug = false; try { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 1; i < 5100; i++) { attemptCombination = i; if (i > 4000 && i % 100 == 0) { outputDebug = true; stopWatchSingle.Restart(); System.Diagnostics.Debug.Write("code number " + i + " took... "); } code = AttendanceCodeService.GetNew(2, 0, 1, true); if (outputDebug) { System.Diagnostics.Debug.WriteLine(stopWatchSingle.ElapsedMilliseconds + " ms"); outputDebug = false; } codeList.Add(code.Code); } var matches = codeList.Where(c => AttendanceCodeService.NoGood.Any(ng => c.Contains(ng))); bool hasMatchIsBad = matches.Any(); Assert.That.IsFalse(hasMatchIsBad, "bad codes were: " + string.Join(", ", matches)); var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.That.True(duplicates.Count() == 0); } catch (TimeoutException) { // If an infinite loop was detected, but we tried at least 5100 codes then // we'll consider this a pass. Assert.That.IsTrue(attemptCombination >= 5100); } finally { stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test AlphaNumericWith1NumericCodeShouldGenerateAtLeast5100Codes took {0} ms.", stopWatch.ElapsedMilliseconds)); } }
public void Increment100SequentialNumericCodes() { AttendanceCode code = null; for (int i = 0; i < 100; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); } Assert.That.Equal("100", code.Code); }
public void CheckThreeCharNumericNonRandom002Code() { AttendanceCode code = null; for (int i = 0; i < 2; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); } Assert.That.Equal("002", code.Code); }
public void CheckThreeChar002Code() { AttendanceCode code = null; for (int i = 0; i < 2; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); } Assert.AreEqual("002", code.Code); }
private void LoadFromModel(AttendanceCode model) { Code = model.Code; Description = model.Description; MeaningId = model.MeaningId; Active = model.Active; Restricted = model.Restricted; if (model.CodeType != null) { CodeType = new AttendanceCodeTypeModel(model.CodeType); } }
public void NumericCodesShouldSkip911And666() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 2000; i++) { code = AttendanceCodeService.GetNew(0, 0, 4, false); codeList.Add(code.Code); } Assert.That.DoesNotContain(codeList, "911"); Assert.That.DoesNotContain(codeList, "666"); }
public void NumericCodesShouldNotContain911And666() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 2000; i++) { code = AttendanceCodeService.GetNew(0, 0, 4, false); codeList.Add(code.Code); } Assert.IsFalse(codeList.Any(s => s.Contains("911"))); Assert.IsFalse(codeList.Any(s => s.Contains("666"))); }
public void ThreeCharAlphaWithFourCharNumericCodesShouldSkipBadCodes() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 6000; i++) { code = AttendanceCodeService.GetNew(0, 3, 4, true); codeList.Add(code.Code); } bool hasMatchIsBad = codeList.Where(c => AttendanceCodeService.NoGood.Any(ng => c.Contains(ng))).Any(); Assert.That.False(hasMatchIsBad); }
public void AlphaOnlyCodesShouldSkipBadCodes() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 1000; i++) { code = AttendanceCodeService.GetNew(0, 3, 0, true); codeList.Add(code.Code); } bool hasMatchIsBad = codeList.Where(c => AttendanceCodeService.noGood.Any(ng => c.Contains(ng))).Any(); Assert.That.IsFalse(hasMatchIsBad); }
public void AlphaOnlyWithNumericOnlyCodesShouldSkipBadCodes() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 6000; i++) { code = AttendanceCodeService.GetNew(0, 1, 4, true); codeList.Add(code.Code); } var matches = codeList.Where(c => AttendanceCodeService.noGood.Any(ng => c.Contains(ng))); bool hasMatchIsBad = matches.Any(); Assert.IsFalse(hasMatchIsBad, "bad codes were: " + string.Join(", ", matches)); }
public void AlphaNumericCodesShouldNeverContain911And666() { Cleanup(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 10000; i++) { code = AttendanceCodeService.GetNew(3, 0, 2, false); codeList.Add(code.Code); } Assert.False(codeList.Any(s => "911".Contains(s))); Assert.False(codeList.Any(s => "666".Contains(s))); }
public void RandomNumericCodesShouldNotRepeat() { var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 998; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, true); codeList.Add(code.Code); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.IsTrue(duplicates.Count() == 0, "repeated codes: " + string.Join(", ", duplicates)); }
public void AlphaNumericCodesShouldSkipBadCodes() { Cleanup(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 6000; i++) { code = AttendanceCodeService.GetNew(3, 0, 0, false); codeList.Add(code.Code); } bool hasMatchIsBad = codeList.Where(c => noGood.Any(ng => c.Contains(ng))).Any(); Assert.False(hasMatchIsBad); }
public void NumericCodeWithLengthOf2ShouldNotGoBeyond99() { Cleanup(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 101; i++) { code = AttendanceCodeService.GetNew(0, 0, 2, false); codeList.Add(code.Code); } // should not be longer than 4 characters // This is a known bug in v7.4 and earlier, and possibly fixed via PR #3071 Assert.True(codeList.Last().Length == 4); }
public void RandomNumericCodesShouldNotRepeat() { int maxThreeDigitCodes = 997; var codeList = new List <string>(); AttendanceCode code = null; for (int i = 1; i < maxThreeDigitCodes; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, true); codeList.Add(code.Code); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.That.True(duplicates.Count() == 0); }
public void Increment100SequentialNumericCodes() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); AttendanceCode code = null; for (int i = 0; i < 100; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); } Assert.That.AreEqual("100", code.Code); stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test Increment100SequentialNumericCodes took {0} ms.", stopWatch.ElapsedMilliseconds)); }
public void AlphaNumericCodesShouldSkipBadCodes() { Cleanup(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 6000; i++) { code = AttendanceCodeService.GetNew(3, 0, 0, false); codeList.Add(code.Code); } bool hasMatchIsBad = codeList.Select(x => x) .Intersect(noGood) .Any(); Assert.False(hasMatchIsBad); }
public void CheckThreeChar002Code() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); AttendanceCode code = null; for (int i = 0; i < 2; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); } Assert.That.AreEqual("002", code.Code); stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test CheckThreeChar002Code took {0} ms.", stopWatch.ElapsedMilliseconds)); }
public void NumericCodesShouldNotRepeat() { Cleanup(); var codeList = new List <string>(); AttendanceCode code = null; for (int i = 0; i < 999; i++) { code = AttendanceCodeService.GetNew(0, 0, 3, false); codeList.Add(code.Code); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.True(duplicates.Count() == 0); }
public void ThreeCharAlphaOnlyCodesShouldNotRepeat() { var codeList = new List <string>(); AttendanceCode code = null; // 4800 (17*17*17 minus ~80 badcodes) possible combinations of 17 letters for (int i = 0; i < 4800; i++) { //System.Diagnostics.Debug.WriteIf( i > 4700, "code number " + i + " took... " ); code = AttendanceCodeService.GetNew(0, 3, 0, false); codeList.Add(code.Code); //System.Diagnostics.Debug.WriteLineIf( i > 4700, "" ); } var duplicates = codeList.GroupBy(x => x) .Where(group => group.Count() > 1) .Select(group => group.Key); Assert.That.True(duplicates.Count() == 0); }
public int CreateAttendanceCode(AttendanceCode attendanceCode) { try { SqlParameter[] m = new SqlParameter[5]; m[0] = new SqlParameter("@ID", SqlDbType.Int); m[1] = new SqlParameter("@GroupID", attendanceCode.GroupID); m[2] = new SqlParameter("@AttendanceDate", attendanceCode.AttendanceDate); m[3] = new SqlParameter("@AttendanceCode", attendanceCode.Code); m[4] = new SqlParameter("@CreateDate", attendanceCode.CreateDate); m[0].Direction = ParameterDirection.Output; SqlHelper.ExecuteNonQuery(Connection.Connection_string, CommandType.StoredProcedure, "AttendanceCodeInsert", m); object ivalue = m[0].Value; return((int)ivalue); } catch (Exception ex) { throw ex; } }
public void RequestingMoreCodesThanPossibleShouldThrowException() { var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); var codeList = new List <string>(); AttendanceCode code = null; // Generate 99 codes (the maximum number of valid codes). for (int i = 0; i < 100; i++) { code = AttendanceCodeService.GetNew(0, 0, 2, true); codeList.Add(code.Code); } // Now try to generate one more... which should NOT hang but instead, may // throw one of two exceptions. try { code = AttendanceCodeService.GetNew(0, 0, 2, true); } catch (InvalidOperationException) { Assert.That.IsTrue(true); } catch (TimeoutException) { // An exception in this case is considered better than hanging (since there is // no actual solution). Assert.That.IsTrue(true); } finally { stopWatch.Stop(); System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out)); System.Diagnostics.Trace.WriteLine(string.Format("Test RequestingMoreCodesThanPossibleShouldThrowException took {0} ms.", stopWatch.ElapsedMilliseconds)); } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode"/> /// </summary> /// <param name="codeLength">A <see cref="System.Int32"/> representing the length of the (security) code.</param> /// <returns>A new <see cref="Rock.Model.AttendanceCode"/></returns> public static AttendanceCode GetNew( int codeLength = 3 ) { lock ( _obj ) { using ( var rockContext = new Rock.Data.RockContext() ) { var service = new AttendanceCodeService( rockContext ); DateTime today = RockDateTime.Today; if ( _todaysCodes == null || !_today.HasValue || !_today.Value.Equals( today ) ) { _today = today; DateTime tomorrow = today.AddDays( 1 ); _todaysCodes = service.Queryable().AsNoTracking() .Where( c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow ) .Select( c => c.Code ) .ToList(); } // Find a good unique code for today string code = GenerateRandomCode( codeLength ); while ( noGood.Any( s => s == code ) || _todaysCodes.Any( c => c == code ) ) { code = GenerateRandomCode( codeLength ); } _todaysCodes.Add( code ); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); return attendanceCode; } } }
/// <summary> /// Returns a new <see cref="Rock.Model.AttendanceCode" /> with a specified number of alpha characters followed by /// another specified number of numeric characters. The numeric character sequence will not repeat for "today" so /// ensure that you're using a sufficient numericLength otherwise it will be unable to find a unique number. /// Also note as the issued numeric codes reaches the maximum (from the set of possible), it will take longer and /// longer to find an unused number. /// </summary> /// <param name="alphaLength">A <see cref="System.Int32"/> representing the length of the (alpha) portion of the code.</param> /// <param name="numericLength">A <see cref="System.Int32"/> representing the length of the (digit) portion of the code.</param> /// <param name="isRandomized">A <see cref="System.Boolean"/> that controls whether or not the AttendanceCodes should be generated randomly or in order (starting from the smallest).</param> /// <returns> /// A new <see cref="Rock.Model.AttendanceCode" /> /// </returns> public static AttendanceCode GetNew( int alphaLength = 2, int numericLength = 4, bool isRandomized = true ) { lock ( _obj ) { using ( var rockContext = new Rock.Data.RockContext() ) { var service = new AttendanceCodeService( rockContext ); DateTime today = RockDateTime.Today; if ( _todaysCodes == null || !_today.HasValue || !_today.Value.Equals( today ) ) { _today = today; DateTime tomorrow = today.AddDays( 1 ); _todaysCodes = service.Queryable().AsNoTracking() .Where( c => c.IssueDateTime >= today && c.IssueDateTime < tomorrow ) .Select( c => c.Code ) .ToList(); } // Find a good alpha code string alphaCode = GenerateRandomAlphaCode( alphaLength ); while ( noGood.Any( s => s == alphaCode ) ) { alphaCode = GenerateRandomAlphaCode( alphaLength ); } // Find a good unique numeric code for today string numericCode = string.Empty; if ( isRandomized ) { numericCode = GenerateRandomNumericCode( numericLength ); while ( noGood.Any( s => s == numericCode ) || _todaysCodes.Any( c => c.EndsWith( numericCode ) ) ) { numericCode = GenerateRandomNumericCode( numericLength ); } } else { var lastCode = _todaysCodes.OrderBy( c => c.Substring( alphaLength ) ).LastOrDefault(); if ( lastCode != null ) { var maxCode = lastCode.Substring( alphaLength ); numericCode = ( maxCode.AsInteger() + 1 ).ToString( "D" + numericLength ); } else { numericCode = 0.ToString( "D" + numericLength ); } } string code = alphaCode + numericCode; _todaysCodes.Add( code ); var attendanceCode = new AttendanceCode(); attendanceCode.IssueDateTime = RockDateTime.Now; attendanceCode.Code = code; service.Add( attendanceCode ); rockContext.SaveChanges(); return attendanceCode; } } }
/// <summary> /// Adds attendance data for each child for each weekend since the starting date up to /// the weekend ending X weeks ago (endingWeeksAgo). It will randomly skip a weekend /// based on the percentage (pctAttendance) and it will vary which service they attend /// between the scheduleId and altScheduleId based on the percentage (pctAttendedRegularService) /// given. /// </summary> /// <param name="familyMembers">The family members.</param> /// <param name="startingDate">The first date of attendance</param> /// <param name="endDate">The end date of attendance</param> /// <param name="pctAttendance">The PCT attendance.</param> /// <param name="pctAttendedRegularService">The PCT attended regular service.</param> /// <param name="scheduleId">The schedule identifier.</param> /// <param name="altScheduleId">The alt schedule identifier.</param> /// <param name="attendanceData">The attendance data.</param> private void CreateAttendance( ICollection<GroupMember> familyMembers, DateTime startingDate, DateTime endDate, int pctAttendance, int pctAttendedRegularService, int scheduleId, int altScheduleId, Dictionary<Guid, List<Attendance>> attendanceData ) { // foreach weekend between the starting and ending date... for ( DateTime date = startingDate; date <= endDate; date = date.AddDays( 7 ) ) { // set an additional factor int summerFactor = ( 7 <= date.Month && date.Month <= 9 ) ? summerPercentFactor : 0; if ( _random.Next( 0, 100 ) > pctAttendance - summerFactor ) { continue; // skip this week } // which service did they attend int serviceSchedId = ( _random.Next( 0, 100 ) > pctAttendedRegularService ) ? scheduleId : altScheduleId; // randomize check-in time slightly by +- 0-15 minutes (and 1 out of 4 times being late) int minutes = _random.Next( 0, 15 ); int plusMinus = ( _random.Next( 0, 4 ) == 0 ) ? 1 : -1; int randomSeconds = _random.Next( 0, 60 ); var time = _scheduleTimes[serviceSchedId]; DateTime dtTime = new DateTime( date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second ); DateTime checkinDateTime = dtTime.AddMinutes( Convert.ToDouble( plusMinus * minutes ) ).AddSeconds( randomSeconds ); // foreach child in the family foreach ( var member in familyMembers.Where( m => m.GroupRoleId == _childRoleId ) ) { // Find a class room (group location) // TODO -- someday perhaps we will change this to actually find a real GroupLocationSchedule record var item = ( from classroom in _classes where member.Person.AgePrecise >= classroom.MinAge && member.Person.AgePrecise <= classroom.MaxAge orderby classroom.MinAge, classroom.MaxAge select classroom ).FirstOrDefault(); // If no suitable classroom was found, skip if ( item == null ) { continue; } // Only create one attendance record per day for each person/schedule/group/location AttendanceCode attendanceCode = new AttendanceCode() { Code = GenerateRandomCode( _securityCodeLength ), IssueDateTime = RockDateTime.Now, }; Attendance attendance = new Attendance() { ScheduleId = scheduleId, GroupId = item.GroupId, LocationId = item.LocationId, DeviceId = _kioskDeviceId, AttendanceCode = attendanceCode, StartDateTime = checkinDateTime, EndDateTime = null, DidAttend = true, CampusId = 1 }; if ( !attendanceData.Keys.Contains( member.Person.Guid )) { attendanceData.Add( member.Person.Guid, new List<Attendance>()); } attendanceData[member.Person.Guid].Add( attendance); } } }