Author | Message | Time |
---|---|---|
Ratio | Components: ListBox - ListUser ListBox - ListAccess File - Users.txt [code] Public Sub AddUsers() Dim String1 As String,S() As String Open App.Path & "\Users.txt" For #1 As Input Do Until EOF(1) Line Input #1,String1 S() = Split(String1," ",2) Form1.ListUser.Additem S(0) Form1.ListAccess.Additem S(1) Loop Close #1 End Sub [/code] | August 16, 2006, 1:06 AM |
rabbit | .........stop posting this stuff. | August 16, 2006, 1:20 AM |
Topaz | You're that guy from Bnetweb, aren't you? oh my god Edit: http://bnetweb.net/e107_plugins/forum/forum_viewtopic.php?11988.7 http://bnetweb.net/e107_plugins/forum/forum_viewtopic.php?11988.19 http://bnetweb.net/e107_plugins/forum/forum_viewtopic.php?11845 http://bnetweb.net/e107_plugins/forum/forum_viewtopic.php?11724.3 http://bnetweb.net/e107_plugins/forum/forum_viewtopic.php?11685.13 | August 16, 2006, 1:58 AM |
Ratio | yes im Ratio@useast and there are people out there that are newbs to vb6 so pleasE? | August 16, 2006, 3:07 AM |
rabbit | And if they ask a question we will answer. Preemptive answering is called spam. Please stop. | August 16, 2006, 3:17 AM |
FrOzeN | [quote author=Ratio link=topic=15546.msg156812#msg156812 date=1155697654] .. and there are people out there that are newbs to vb6 so pleasE? [/quote] Incase you didn't notice, your a newb to VB6 aswell. In both of your posts the code you posted is poorly written. | August 16, 2006, 5:05 AM |
warz | Well, no offense, but how else would you write the code in this post so that it is not poorly written? :-P | August 16, 2006, 6:29 AM |
FrOzeN | Probably like.. [code]Public Sub AddUsers() Dim strLine As String, strParts() As String, intFile As Integer intFile = FreeFile Open App.Path & "\Users.txt" For Input As intFile Do Until EOF(intFile) Line Input #intFile, strLine strParts() = Split(strLine, Space$(1), 2) Form1.ListUser.AddItem strParts(0) Form1.ListAccess.AddItem strParts(1) Loop Close intFile End Sub[/code] [EDIT] Also, both pieces of his code are incorrect when opening the file. The "For [Number] As [Scope]" should be "For [Scope] As [Number]". | August 16, 2006, 6:58 AM |
Ratio | that still is not better code just a differnt way | August 29, 2006, 1:35 AM |
rabbit | No, it's better. It's still not good, though. | August 29, 2006, 1:42 AM |
FrOzeN | [quote author=rabbit link=topic=15546.msg157294#msg157294 date=1156815762] No, it's better. It's still not good, though. [/quote] Post what you'd consider "good". The only downsides that I can see with my code, is that it could error if the program (.exe) was placed in a root directory, where App.Path would return the path along with the backslash. Also, there should probably be a check on strLine before trying to Split() it, or I could add an "& Space$(1)" after the strLine inside the Split() call. | August 29, 2006, 5:49 AM |
rabbit | [code]Option Explicit Private Type UserAccessType strName As String intAccess As Integer End Type Private arrUserList() As UserAccessType Public Sub LoadUsers() Dim strLine As String Dim strParts() As String ReDim arrUserList(0) On Error GoTo LoadUsers_Err Open "D:\users.txt" For Input As #1 Do Until EOF(1) Line Input #1, strLine strParts() = Split(strLine, " ", 2) Call AddUser(strParts(0), strParts(1)) Loop Close #1 Exit Sub LoadUsers_Err: Debug.Print "Error #" & Err.Number Debug.Print "Error : " & Err.Description Debug.Print "Source : " & Err.Source Debug.Print "Help File : " & Err.HelpFile Debug.Print "Help Context : " & Err.HelpContext Err.Clear End Sub Public Sub AddUser(ByVal UserName As String, ByVal UserAccess As String) On Error GoTo AddUser_Err If arrUserList(UBound(arrUserList)).strName <> vbNullString Then ReDim Preserve arrUserList(UBound(arrUserList) + 1) End If If UserName <> vbNullString And IsNumeric(UserAccess) Then ' assuming it's an integer, which is bad, but w/e arrUserList(UBound(arrUserList)).strName = UserName arrUserList(UBound(arrUserList)).intAccess = CInt(UserAccess) Else Debug.Print "Error: username is null or access is not numeric" Exit Sub End If Exit Sub AddUser_Err: Debug.Print "Error #" & Err.Number Debug.Print "Error : " & Err.Description Debug.Print "Source : " & Err.Source Debug.Print "Help File : " & Err.HelpFile Debug.Print "Help Context : " & Err.HelpContext Err.Clear End Sub [/code]Something of that nature, of course with the error handlers and such tailored to the program. | August 29, 2006, 3:22 PM |
Quarantine | and rabbit for the win | August 29, 2006, 11:16 PM |
UserLoser | Lot of unnecessary and messy code there...prone to bugs and errors. Personally, I would not do it my self the following way, but try something along the lines of this (just wrote this up quickly did not test thoroughly)... It's basically rabbit's function cleaned up and crash free. [code] Private Const Config_Filename As String = ".\Config.ini" Private Type DatabaseEntry Usermask As String Flags As Long End Type Private DatabaseUsers() As DatabaseEntry Public Sub LoadUserDatabase() On Error GoTo ErrorHandler Dim FileNumber As Integer Dim DataArray As Variant Dim FileInput As String 'Reset our internal database list ReDim DatabaseUsers(0) 'Local constants Const Username = 0, Access = 1 'Get filenumber FileNumber = FreeFile() 'Check file, set function line numbers on places where error could possibly occur for debugging purposes post compilation and release. 17: If (FileLen(Config_Filename) > 0) Then 'Open file 19: Open Config_Filename For Input As FileNumber 'Loop through the file While EOF(FileNumber) = False 'Get our next line 23: Line Input #FileNumber, FileInput 'Split our data 25: DataArray = Split(FileInput, " ", 2) 'Check bounds of array If (UBound(DataArray) = 1) Then 'Add user to database 29: AddDatabaseEntry DataArray(Username), DataArray(Access) End If Wend 'End of file, erase data 33: Erase DataArray 'Close file Close FileNumber End If Exit Sub ErrorHandler: MsgBox "Error (LoadUserDatabase @ line " & Erl & "): " & Error(Err.Number), vbCritical Or vbMsgBoxSetForeground Err.Clear End Sub Private Sub AddDatabaseEntry(ByVal Usermask As String, ByVal Flags As Long) Dim NewSize As Long 'Get current size and one NewSize = UBound(DatabaseUsers) + 1 'Resize our array ReDim Preserve DatabaseUsers(0 To NewSize) 'Add entry DatabaseUsers(NewSize).Usermask = Usermask DatabaseUsers(NewSize).Flags = Flags End Sub [/code] Have not written in VB in a few months. UL FTW. | August 30, 2006, 5:52 AM |
FrOzeN | rabbit, your code isn't much better. It just has error handlers which I mistakenly left out. Your not checking if the file exists. Your using "#1" which could cause errors if that number is already in use for file handling. Your not checking the size of strParts() before parsing it. Incase of a corrupt user.txt file. Your error handling debug printout is a fair overkill. The line "If UserName <> vbNullString And IsNumeric(UserAccess) Then" is bad coding practise because it can cause problems at times where the compiler may misinterpret this as a binary comparison. A better/more efficient equivalent would be, "If (LenB(UserName) <> 0) And (IsNumeric(UserAccess) = True) Then". --- UL, the only comment on yours would be the naming convention ".ini" for something that isn't formatted correctly. Personally, I think it's best to stick to the .txt extension unless your specifically using .ini files to store data in there intended format. :) | August 30, 2006, 10:45 AM |
rabbit | [quote author=FrOzeN link=topic=15546.msg157340#msg157340 date=1156934733] rabbit, your code isn't much better. It just has error handlers which I mistakenly left out. Your not checking if the file exists. Your using "#1" which could cause errors if that number is already in use for file handling. Your not checking the size of strParts() before parsing it. Incase of a corrupt user.txt file. Your error handling debug printout is a fair overkill. The line "If UserName <> vbNullString And IsNumeric(UserAccess) Then" is bad coding practise because it can cause problems at times where the compiler may misinterpret this as a binary comparison. A better/more efficient equivalent would be, "If (LenB(UserName) <> 0) And (IsNumeric(UserAccess) = True) Then". [/quote]You clearly suck. IsNumeric() is BOOLEAN meaning it's either TRUE or FALSE. Checking for true is the same as checking for = true, so it doesn't matter. As for comparing the UserName variable to vbNullString, it's faster and just as safe as using LenB(). Also, I used #1 on purpose. I always use HARD NUMBERS as opposed to variables. I always and only use (say #1) for LoadUsers(), that way the user list isn't loaded multiple times consecutively or simultaneously, and I also know that any error thrown by opening a file #1 means that something I didn't intend to happen is happening, and easily traceable. As for checking strParts(), it's done by Split, and if there's an error, the error handler will take care of it. And as for the error handler, you clearly missed the part where I said[quote author=rabbit link=topic=15546.msg157312#msg157312 date=1156864932]error handlers and such tailored to the program. [/quote]I used Debug.Print for the sake of display, since I'm not writing a whole program. Do you honestly think I would use Debug.Print to handle errors in a release? You're clearly retarded. | August 30, 2006, 3:13 PM |
UserLoser | [quote author=FrOzeN link=topic=15546.msg157340#msg157340 date=1156934733] rabbit, your code isn't much better. It just has error handlers which I mistakenly left out. Your not checking if the file exists. Your using "#1" which could cause errors if that number is already in use for file handling. Your not checking the size of strParts() before parsing it. Incase of a corrupt user.txt file. Your error handling debug printout is a fair overkill. The line "If UserName <> vbNullString And IsNumeric(UserAccess) Then" is bad coding practise because it can cause problems at times where the compiler may misinterpret this as a binary comparison. A better/more efficient equivalent would be, "If (LenB(UserName) <> 0) And (IsNumeric(UserAccess) = True) Then". --- UL, the only comment on yours would be the naming convention ".ini" for something that isn't formatted correctly. Personally, I think it's best to stick to the .txt extension unless your specifically using .ini files to store data in there intended format. :) [/quote] Programmer sets naming convention, is constant for that purpose. As for my self I don't use text files to store configuration settings--I always use the registry. | August 30, 2006, 5:20 PM |
FrOzeN | [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787] You clearly suck. IsNumeric() is BOOLEAN meaning it's either TRUE or FALSE. Checking for true is the same as checking for = true, so it doesn't matter. As for comparing the UserName variable to vbNullString, it's faster and just as safe as using LenB().[/quote] Ok, your line in particular isn't going to cause problems because intellisense (or whatever VB6 uses) interprets it fine. I was only saying it's bad coding practise because on other occasions there can be mix ups and it's clear to distinguish it into parts. Also, "If someString = vbNullString" is slower than "If LenB(someString) = 0". Sure it makes pretty much makes no noticeable difference, but it's still faster. http://www.aivosto.com/vbtips/stringopt.html (See "The empty string") [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787]As for checking strParts(), it's done by Split, and if there's an error, the error handler will take care of it.[/quote] Well with your code, if say someone has setup the users.txt and accidently input an entry at the start which is an incorrect format (without a space). Your program would get to it and then just cut out, missing out on all the others. The simply UBound() If-statement check would just ignore that entry and continue on. Essentially, if you want, you could just add an Else-statement and notify the user of the damaged entry(s). [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787]And as for the error handler, you clearly missed the part where I said[quote author=rabbit link=topic=15546.msg157312#msg157312 date=1156864932]error handlers and such tailored to the program. [/quote]I used Debug.Print for the sake of display, since I'm not writing a whole program. Do you honestly think I would use Debug.Print to handle errors in a release? You're clearly retarded. [/quote] I'm not suggesting it was for release, it still doesn't mean you can't have overkill in your code whilst testing. There is no reason to be printing out the HelpFile/HelpContext as it's more than unlikely that you'll be referring to those files; ever. | August 30, 2006, 10:02 PM |
Quarantine | [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787] You clearly suck. IsNumeric() is BOOLEAN meaning it's either TRUE or FALSE. Checking for true is the same as checking for = true, so it doesn't matter. As for comparing the UserName variable to vbNullString, it's faster and just as safe as using LenB().[/quote] Ok, your line in particular isn't going to cause problems because intellisense (or whatever VB6 uses) interprets it fine. I was only saying it's bad coding practise because on other occasions there can be mix ups and it's clear to distinguish it into parts. [/quote] You don't need to explicitly state what you expect the return of the object to be when you're dealing with booleans. It's interpreted by the language as being true if nothing conflicts with it. Honestly, in complex statements like his (Statements which contain more than one condition) it's better to remove clutter whenever you can. [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] Also, "If someString = vbNullString" is slower than "If LenB(someString) = 0". Sure it makes pretty much makes no noticeable difference, but it's still faster. http://www.aivosto.com/vbtips/stringopt.html (See "The empty string") [/quote] I really don't see how this would be a problem, even if it wasn't optimized then the difference would only be something less than a milisecond. [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787]As for checking strParts(), it's done by Split, and if there's an error, the error handler will take care of it.[/quote] Well with your code, if say someone has setup the users.txt and accidently input an entry at the start which is an incorrect format (without a space). Your program would get to it and then just cut out, missing out on all the others. The simply UBound() If-statement check would just ignore that entry and continue on. Essentially, if you want, you could just add an Else-statement and notify the user of the damaged entry(s). [/quote] This is simply a difference in how to handle errors, rabbits method simply ignores the errors if they arn't function threatening, yours alerts the user of what happens. Regardless of what you or he thinks is better it isn't a very good argument to use against one's coding skill. [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] [quote author=rabbit link=topic=15546.msg157344#msg157344 date=1156950787]And as for the error handler, you clearly missed the part where I said[quote author=rabbit link=topic=15546.msg157312#msg157312 date=1156864932]error handlers and such tailored to the program. [/quote]I used Debug.Print for the sake of display, since I'm not writing a whole program. Do you honestly think I would use Debug.Print to handle errors in a release? You're clearly retarded. [/quote] I'm not suggesting it was for release, it still doesn't mean you can't have overkill in your code whilst testing. There is no reason to be printing out the HelpFile/HelpContext as it's more than unlikely that you'll be referring to those files; ever. [/quote] Honestly, when you're testing I'd Debug.Print, if something hangs the execution of the program (To the point where it cant even redraw itself) then I'd much rather have Debug.Print showing me data instead of another method. | August 31, 2006, 12:47 AM |
FrOzeN | [quote author=Warrior link=topic=15546.msg157356#msg157356 date=1156985275] [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] Also, "If someString = vbNullString" is slower than "If LenB(someString) = 0". Sure it makes pretty much makes no noticeable difference, but it's still faster. http://www.aivosto.com/vbtips/stringopt.html (See "The empty string") [/quote] I really don't see how this would be a problem, even if it wasn't optimized then the difference would only be something less than a milisecond. [/quote] I just pointed that out as rabbit said it wasn't faster. Your right in that it's an unnecessary change. [quote author=Warrior link=topic=15546.msg157356#msg157356 date=1156985275] Honestly, when you're testing I'd Debug.Print, if something hangs the execution of the program (To the point where it cant even redraw itself) then I'd much rather have Debug.Print showing me data instead of another method. [/quote] I wasn't implying not to use Debug.Print, just that the bottom 2 (of the 5 times) he used it are a bit excessive and arn't really needed. | August 31, 2006, 6:07 AM |
rabbit | [quote author=FrOzeN link=topic=15546.msg157357#msg157357 date=1157004427] [quote author=Warrior link=topic=15546.msg157356#msg157356 date=1156985275] [quote author=FrOzeN link=topic=15546.msg157353#msg157353 date=1156975351] Also, "If someString = vbNullString" is slower than "If LenB(someString) = 0". Sure it makes pretty much makes no noticeable difference, but it's still faster. http://www.aivosto.com/vbtips/stringopt.html (See "The empty string") [/quote] I really don't see how this would be a problem, even if it wasn't optimized then the difference would only be something less than a milisecond. [/quote] I just pointed that out as rabbit said it wasn't faster. Your right in that it's an unnecessary change. [quote author=Warrior link=topic=15546.msg157356#msg157356 date=1156985275] Honestly, when you're testing I'd Debug.Print, if something hangs the execution of the program (To the point where it cant even redraw itself) then I'd much rather have Debug.Print showing me data instead of another method. [/quote] I wasn't implying not to use Debug.Print, just that the bottom 2 (of the 5 times) he used it are a bit excessive and arn't really needed. [/quote]You keep saying stuff about speed and originally used ListBoxes to hold your userlist. | August 31, 2006, 2:40 PM |
Ringo | Eh, I had nothing to do, so I thought i would write a new/random style access class :P Hot or not? :) Useage: Add/Update users access: [code] Class.UserAccess("Ringo") = 100 (0 or lower access = removes user) [/code] Get Users access: [code] TmpAccess = Class.UserAccess("Ringo") (0 would mean user not found) [/code] Object Codeage: [code] Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal numbytes As Long) Private Type udt_UserAccess UserName As String * 20 UserHash As Long UserAccess As Long End Type Private m_User() As udt_UserAccess Private m_UserCount As Long Private m_UserHash As Long Private Const SizeOfUserAccess As Byte = 28 Public Sub LoadAccessFile(ByVal FilePath As String) If Dir$(FilePath) = vbNullString Then Exit Sub Dim FF As Integer FF = FreeFile Open FilePath For Binary As #FF If LOF(FF) <= 0 Then Put #FF, 1, CLng(-1) Get #FF, 1, m_UserCount If m_UserCount >= 0 Then ReDim m_User(m_UserCount) Get #FF, 5, m_User() End If Close #FF End Sub Public Function SaveAccessFile(ByVal FilePath As String) As Boolean On Error GoTo Err_SaveAccess If Not Dir$(FilePath) = vbNullString Then Kill FilePath Dim FF As Integer If m_UserCount >= 0 Then FF = FreeFile Open FilePath For Binary As #FF Put #FF, 1, m_UserCount Put #FF, 5, m_User() Close #FF FF = 0 End If SaveAccessFile = True Exit Function Err_SaveAccess: SaveAccessFile = False If FF > 0 Then Close #FF End Function Public Property Get UserAccess(ByVal UserName As String) As Long If GetTrueUser(UserName) = False Then Exit Property Dim i As Long i = FindUser(UserName) If i >= 0 Then UserAccess = m_User(i).UserAccess End If End Property Public Property Let UserAccess(ByVal UserName As String, ByVal NewAccess As Long) If GetTrueUser(UserName) = False Then Exit Property Dim i As Long i = FindUser(UserName) If i >= 0 Then If NewAccess <= 0 Then 'remove the user Call RemoveUser(i) Else 'update the user m_User(i).UserAccess = NewAccess End If Else If NewAccess <= 0 Then Exit Property i = m_UserCount + 1 ReDim Preserve m_User(i) With m_User(i) .UserName = Left$(UserName & String(20, 0), 20) .UserHash = m_UserHash .UserAccess = NewAccess End With m_UserCount = i End If End Property Private Sub Class_Initialize() m_UserCount = -1 End Sub Private Function GetTrueUser(ByRef UserName As String) As Boolean Dim i As Long i = InStr(1, UserName, "#", vbTextCompare) - 1 If i > 0 Then UserName = Left$(UserName, i) i = Len(UserName) If i > 20 Then UserName = Left$(UserName, 20) GetTrueUser = (i > 0) End Function Private Sub RemoveUser(ByRef Index As Long) If Index < 0 Or Index > m_UserCount Then Exit Sub Dim i As Long If Index < m_UserCount Then For i = Index To m_UserCount - 1 Call CopyMemory(m_User(i), m_User(i + 1), SizeOfUserAccess) Next i End If m_UserCount = m_UserCount - 1 If m_UserCount < 0 Then m_UserCount = -1 Erase m_User() Else ReDim Preserve m_User(m_UserCount) End If End Sub Private Function FindUser(ByRef StrUser As String) As Integer Dim i As Long Call HashString(StrUser) For i = 0 To m_UserCount If m_User(i).UserHash = m_UserHash Then If StrComp(Replace(m_User(i).UserName, vbNullChar, ""), StrUser, vbTextCompare) = 0 Then FindUser = i Exit Function End If End If Next i FindUser = -1 End Function Private Sub HashString(ByRef Name As String) Dim Key() As Byte, StrLen&, StrHash$, valHold&, i% StrHash = LCase(Name) StrLen = Len(StrHash) If (StrLen Mod 4) Then StrHash = StrHash & Left$(String(4, &H20), 4 - (StrLen Mod 4)) StrLen = Len(StrHash) End If ReDim Key(StrLen - 1) Call CopyMemory(Key(0), ByVal StrHash, StrLen) m_UserHash = 0 For i = 0 To (StrLen - 1) Step 4 valHold = (((Key(i) * 256& + Key(i + 1)) * 256& + Key(i + 2)) * 256& + Key(i + 3)) m_UserHash = m_UserHash Xor valHold Next i Erase Key() End Sub [/code] | August 31, 2006, 3:13 PM |
FrOzeN | [quote author=rabbit link=topic=15546.msg157361#msg157361 date=1157035205] You keep saying stuff about speed and originally used ListBoxes to hold your userlist. [/quote] The title reads "Loading Access From A File And Splitting It", mentioning nothing about storing the info. I was just demonstrating a more appropriate way to open the file, and read from it. I just used ListUser/ListAccess as that's how he had it. If I were to create my own storage for the userlist I would build a class module. | September 1, 2006, 1:41 AM |
Topaz | Shut up. | September 1, 2006, 1:57 AM |
ImaWh0re | In my opinion anyone that uses listboxes for reasons not nessicary should be shot. And ratio you're bad so just keep your code to yourself. I'm only flaming you because it's true and you do the same to others. Try storing access in a string, not an array/listbox. It's not that hard. Edited for example below. ----v --Don't give me this, it could error bull because theres no reason to not check for which file #s you're using-- [code] Public sFileAccess As String 'somewhere perhaps ^ Dim sUserAccess As String 'tmp variable Open TheFile For Input As #1 Do Until EOF(1) Line Input #1, sUserAccess If InstrB(2,sUserAccess,chrW$(32)) Then sFileAccess = sFileAccess & sUserAccess & ChrW$(0) 'since name must be before space, and have space so we can parse correctly. Loop Close #1 'Yes if access file is tampered with may return invalid results, to read... Public Function GetAccess(sName As String) As Integer 'you could format it to lcase when storing, all up to you If InstrB(1,LCase$(sFileAccess), LCase$(sName)) Then Dim sTemp As String sTemp = Mid$(sFileAccess,Instr(LCase$(sFileAccess), LCase$(sName))+1) 'gets name ---> sTemp = Mid$(sTemp, InStr(1, sTemp, ChrW$(32)) + 1) sTemp = Left$(sTemp, InStr(1, sTemp, ChrW$(0)) - 1) 'gets access --> 'if you are always storing in 3 digits set (which I suggest to make things easier, 'you could cut the above two lines and just use 'sTemp = Mid$(sTemp, InStr(1, sTemp, ChrW$(32)) + 1, 3) GetAccess = Val#(sTemp) 'done End If End Function 'storing isn't much harder either...and you can remove access using a similar method as above. No listbox, no loops, just one simple string.[/code] | September 22, 2006, 5:19 PM |
MyStiCaL | Shame on you for reviving old topic, Shame on me for even talkin.. | September 23, 2006, 9:04 PM |
ImaWh0re | [quote author=Mystical link=topic=15546.msg158819#msg158819 date=1159045446] Shame on you for reviving old topic, Shame on me for even talkin.. [/quote] Oh I didn't even notice the dates. Yeah shame on me :( It wasn't too far down in the list so I just assumed... | September 23, 2006, 9:28 PM |
Ratio | lol my coding has improved by alot since this topic began | November 5, 2006, 10:15 PM |