Author | Message | Time |
---|---|---|
Tontow | (Note: this is being done in Visual Basic 6.0) What is the Most efficient way of makeing a User Database? I could store everyting in a single file: usernames, moderator lvl, flags, etc. and use one of the methods discussed in "Most efficient way of saving settings on a bot?" - https://davnit.net/bnet/vL/phpbbs/index.php?topic=11769.0 or I could use a seperate file for each user, useing the user's nick as the file name. | July 4, 2005, 4:03 AM |
Kp | Presuming your program has the capability to cache the results in memory, it won't matter too much which of those methods you go with. However, from a disk usage perspective, saving one file per username is horribly wasteful. Also, if you really care about efficiency, stop using VB. :) At least upgrade to VB.NET and use the oft-touted support for compiling to MSIL (and from there to native code), which might get you close to performance of a C application if the VB.NET->MSIL generator doesn't do too terrible a job. Our resident .NET geeks can probably give you more advice in this area if you decide to pursue it. | July 4, 2005, 4:54 AM |
Dyndrilliac | This is how I do it.[code]Option Explicit Private Type UserList Username As String Flags As String End Type Private UL() As UserList Public Users As Integer Public Sub LoadUsers() Dim Splt() As String, sInput As String, pfNum As Integer, I As Integer If Dir$(App.Path & "\Database.dcu") = vbNullString Then Call MsgBox("Error: User Database could not be found!", vbCritical, "Error!") Exit Sub End If ReDim UL(0) I = 0 pfNum = FreeFile Open (App.Path & "\Database.dcu") For Input As #pfNum Do Until EOF(pfNum) Input #pfNum, sInput If Not sInput = vbNullString Then Splt() = Split(sInput, ":", 1) '// Userlist syntax is "Username:Flags" UL(I).Username = Splt(0) If (InStr(Splt(1), "B") <> 0) Then If (InStr(Splt(1), "L") <> 0) Then Splt(1) = "BL" Else Splt(1) = "B" End If ElseIf (InStr(Splt(1), "K") <> 0) Then If (InStr(Splt(1), "L") <> 0) Then Splt(1) = "KL" Else Splt(1) = "K" End If ElseIf (InStr(Splt(1), "Z") <> 0) Then If (InStr(Splt(1), "L") <> 0) Then Splt(1) = "ZL" Else Splt(1) = "Z" End If End If UL(I).Flags = UCase$(Alphabetize(Splt(1))) I = I + 1 ReDim Preserve UL(0 To UBound(UL) + 1) End If Loop Close #pfNum Users = I End Sub[/code] | July 4, 2005, 5:19 AM |
Kp | Let me be the first to say: eww! Even without writing VB, I can point out a few improvements (aside from the obvious one of not using VB, of course). [list][li]Compose your pathname once, not twice. It's not a relevant performance hit to do it twice, but it could become a maintenance issue later if you change one and not the other. Compose it to a temporary variable, then do both your existence test and your open against the contents of that variable.[/li][li]Modify the error message to print out the file it sought (and ideally the path also). Expecting the user to guess what to do about a missing database is a bad idea, and that's effectively what your code does. Remember, documentation is only meant to kill trees: we don't want to write it, and users don't want to read it. An error message announcing what is missing and what to do about it (or at least containing a reference on where to find that information) would be helpful.[/li][li]Compose your flags in a temporary buffer, rather than trying to filter the existing one. That is, do this (your problem to convert pseudocode to VB):[code]flags = ""; if (fromFile[1] contains "B") flags += "B"; if (fromFile[1] contains "L") flags += "L"; if (fromFile[1] contains "Z") flags += "Z"; user_record.flags = flags;[/code]My approach is much more extensible, and IMO more readable. Of course, I'd still highly advise going to a binary flags approach internally, but at least get away from enumerating every possible combination of access flags![/li] [li]Reallocate the record array less often. Consider having it grow in size by z% when needed, and then truncate it down to the minimal size when you're done. For a good choice of z, that should get you down to a half dozen or so reallocations even for a huge list.[/li][/list] | July 4, 2005, 5:54 AM |
Tontow | I may oneday leave the darkside of the programming force and learn C# or C++ :P ---------------------------------------------------------------------------------------------------------------------------------------------------------- I would think useing a single user defined type with some properties as arrays in a binary file would be better and maby smaller than that IE: (I'm not shure if the syntax is correct, but..) public type database users() as string IndexOfLastEntrie as integer flaga() as string flagb() as string flagc() as string flagd() as string end type So as to store and grap everything with just one put or get statment and not have to split anything; though, you would have to loop through to find the correct user. Yet, Useing one file for each user with the filename being the username would remove the need to loop through; just open put or get a single user defined varable and close. It is possable that the userdata base could get very large and the method used should be able to access a single user when the database could possably contain 10,000 or more users.- I think that that big of a database would not make it possable to loop through all those users. I could also use a string varable to store all the usernames with the array position. IE: username,index,username,index,username,index,username,index,username,index and then use find or somthing to retreave a carater position and then work from there to find the index number | July 4, 2005, 7:19 AM |
R.a.B.B.i.T | [code]'---------------------------------------------------------------------------- ' Module : modDatabase ' DateTime : 5/5/2005 12:44 ' Author : Spencer Ragen ' Purpose : Database handling, duh '---------------------------------------------------------------------------- Option Explicit Public Type s_DatabaseEntry UserName As String * 25 AddBy As String * 25 AddOn As String * 8 AddAt As String * 12 Access As Integer Master As Boolean End Type Private DBUsers() As s_DatabaseEntry Public Sub DBStartup() ReDim DBUsers(0) End Sub Public Sub debugdb() Dim c As s_DatabaseEntry Dim i As Integer For i = LBound(DBUsers) To UBound(DBUsers) c = DBUsers(i) Debug.Print c.UserName Debug.Print c.Master Debug.Print c.Access Debug.Print c.AddBy Debug.Print c.AddOn Debug.Print c.AddAt & vbNewLine Next i End Sub Public Sub LoadDatabase() Dim t As String If varDatabase = "" Or Dir$(varDatabase) = "" Then AddC vbRed, "Database file is invalid" End If Dim c As s_DatabaseEntry Dim k As String Open varDatabase For Random As #1 Do While Not EOF(1) Get #1, , c If c.UserName <> String(25, vbNullChar) Then c.UserName = Trim(c.UserName) c.AddBy = Trim(c.AddBy) AddDBUser c End If Loop Close #1 If Not IsFound(BotMaster) Then GetTimeStamp t c.UserName = LCase(BotMaster) c.Access = 101 c.Master = True t = Replace(t, " ", "") t = Replace(t, "[", "") c.AddAt = Replace(t, "]", "") c.AddBy = "#settings" c.AddOn = Format(Date, "mm.dd.yy") AddDBUser c End If 'Ignore this, it's for my bot :\ 'If ShowMisc Then AddC colInfo, UBound(DBUsers) + 1 & " database entries loaded" End Sub Public Sub SaveDatabase() Dim i As Integer Dim o As Integer Dim ent As String Dim list() As String ReDim list(0) Open varDatabase For Random As #1 For i = LBound(DBUsers) To UBound(DBUsers) For o = 0 To UBound(list) If LCase(list(o)) = LCase(DBUsers(i).UserName) Then GoTo SkipSave Next o If list(UBound(list)) <> "" Then ReDim Preserve list(UBound(list) + 1) End If list(UBound(list)) = DBUsers(i).UserName If DBUsers(i).UserName <> Null And DBUsers(i).UserName <> "" Then Put #1, , DBUsers(i) SkipSave: Next i Close #1 End Sub Public Sub AddDBUser(c As s_DatabaseEntry) If DBUsers(UBound(DBUsers)).UserName <> "" And DBUsers(UBound(DBUsers)).UserName <> String(25, vbNullChar) Then ReDim Preserve DBUsers(UBound(DBUsers) + 1) End If DBUsers(UBound(DBUsers)) = c If c.Access >= 30 Or c.Master Then AddSafe c.UserName End Sub Public Sub DelDBUser(strName As String) Dim i As Integer For i = LBound(DBUsers) To UBound(DBUsers) If LCase(strName) = Trim(DBUsers(i).UserName) Then DBUsers(i).UserName = "" Call SaveDatabase Exit Sub End If Next i End Sub Public Function IsFound(strUser As String) As Boolean Dim i As Integer For i = LBound(DBUsers) To UBound(DBUsers) If LCase(strUser) = Trim(DBUsers(i).UserName) Then IsFound = True Exit Function End If Next i End Function Public Function GetDBEntry(strName As String) As s_DatabaseEntry Dim i As Integer For i = LBound(DBUsers) To UBound(DBUsers) If LCase(strName) = Trim(DBUsers(i).UserName) Then GetDBEntry = DBUsers(i) Exit Function End If Next i GetDBEntry.UserName = "not found" End Function Public Function GetAccess(strName As String) As Integer Dim i As Integer For i = LBound(DBUsers) To UBound(DBUsers) If LCase(strName) = Trim(DBUsers(i).UserName) Then GetAccess = DBUsers(i).Access Exit Function End If Next i GetAccess = -1 End Function[/code] | July 4, 2005, 5:25 PM |
Tontow | What about an application data file? Perhaps a MS Access file? Would that be better than any of the other methods discussed thus far? | July 5, 2005, 12:39 AM |