AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Add two KeyValue files together (https://forums.alliedmods.net/showthread.php?t=262225)

Phil25 04-30-2015 08:28

Add two KeyValue files together
 
Hello everyone!

I've been trying to figure out how to merge two files together using a clean and safe way, without destroying/replacing any keys or duplicating sections. For example:

File #1

File #2

Desired File


Any help with this greatly appreciated! :)

Dr. Greg House 04-30-2015 10:55

Re: Add two KeyValue files together
 
The biggest issue you have is being insane enough to store stats in a kv instead of doing it the appropriate way (that is dbs).
My general advice.

Exolent[jNr] 04-30-2015 11:43

Re: Add two KeyValue files together
 
Here are the steps I would go about merging those:
  • Load the files into KeyValues handles A and B.
  • (Optional) Create another KeyValues handle for the merge if you need to keep the original handles intact.
  • Iterate over A keys using GotoFirstSubKey() and GotoNextKey(), grabbing the current key using GetSectionName()
  • Check if A's key exists in B.
    • If yes, grab B stats and store the sum in the output handle (or A's handle if no output handle).
    • If no and are using an output handle, store A's data in the output handle.
  • Iterate over B keys same method as A.
  • If B's key does not exist in A, store B into the output handle (or A's handle if no output handle).

And there you will have them merged.

Phil25 04-30-2015 13:51

Re: Add two KeyValue files together
 
Quote:

Originally Posted by Exolent[jNr] (Post 2291867)
Here are the steps I would go about merging those:
  • Load the files into KeyValues handles A and B.
  • (Optional) Create another KeyValues handle for the merge if you need to keep the original handles intact.
  • Iterate over A keys using GotoFirstSubKey() and GotoNextKey(), grabbing the current key using GetSectionName()
  • Check if A's key exists in B.
    • If yes, grab B stats and store the sum in the output handle (or A's handle if no output handle).
    • If no and are using an output handle, store A's data in the output handle.
  • Iterate over B keys same method as A.
  • If B's key does not exist in A, store B into the output handle (or A's handle if no output handle).

And there you will have them merged.

Thank you for the plan, I guess I'll have a bit of a buisy night ;)


Quote:

Originally Posted by Dr. Greg House (Post 2291854)
The biggest issue you have is being insane enough to store stats in a kv instead of doing it the appropriate way (that is dbs).
My general advice.

Yea, I thought this could be done a neater way, I just didn't know that yet. Seemed all right at the time when I started to write that plugin. We all had this young and crazy time... but on the upside, others can learn my mistakes. Would this be really such a pain in the future though? :s

And besides, although I'm trying to do this with files holding player statistics, I've never mentioned that in this thread (except for the examples). So it's kinda universal and might help others whatever they'll try to accomplish.

Dr. Greg House 04-30-2015 14:00

Re: Add two KeyValue files together
 
Quote:

Originally Posted by Phil25 (Post 2291910)
Would this be really such a pain in the future though? :s

Yes.

Powerlord 04-30-2015 16:15

Re: Add two KeyValue files together
 
Even if you're using a SQLite database, it's still better than KeyValues.

Having said that, if this is for multiple servers (even on the same machine) you'll probably want a MySQL database. Unless the PostgreSQL driver is working these days... haven't looked at it lately.

Phil25 05-02-2015 22:08

Re: Add two KeyValue files together
 
All right, so I've taken a little different approach than the one Exolent suggested.

I've created an enum with all the keys of the section including the section name itself and made it into two arrays:

Code:
enum _:KVKeys{     String:s_section[32],     i_score,     i_kills,     i_deaths, }; new array_a[16][KVKeys]; new array_b[16][KVKeys];

Then cached key values from two files I wanted to merge in them:

Code:
static String:KVPathA[PLATFORM_MAX_PATH]; static String:KVPathB[PLATFORM_MAX_PATH]; static String:KVPathC[PLATFORM_MAX_PATH]; public OnPluginStart(){     BuildPath(Path_SM, KVPathA, sizeof(KVPathA), "data/[FILENAME]_a.txt");     BuildPath(Path_SM, KVPathB, sizeof(KVPathB), "data/[FILENAME]_b.txt");     BuildPath(Path_SM, KVPathC, sizeof(KVPathC), "data/[FILENAME]_c.txt"); //'C' will be A and B merged     CacheFileA(); //Caching the A file     CacheFileB(); //Caching the B file     CreateFileC(); //Create the merged file }
CacheFileA()
CacheFileB()


And then created the final file using the two arrays:

CreateFileC()


NOTE: For some reason in the final file the root section is treated like a subsection. Meaning that at some point in the file there will something like:
I haven't looked into on how to fix it as the solution is to simply remove those lines and everything's good to go.

FINAL NOTE: Please don't hate on me for having player stats in a KV file, I'll port them to MySQL once I learn how everything works, I swear.. ;~;

Exolent[jNr] 05-04-2015 11:38

Re: Add two KeyValue files together
 
That method is much slower and uses more memory as well. I don't see the reason to do it that way.
Also, you should use an if statement when jumping to keys in case it fails, even if you tell it to create the key when it doesn't exist.

Code:
if (KvJumpToKey(myKv, "Key", true)) {     KvSetNum(myKv, "stuff", 1);     KvGoBack(myKv); }

That way you don't "Go Back" when it never moved in the first place.

Phil25 05-04-2015 11:51

Re: Add two KeyValue files together
 
Quote:

Originally Posted by Exolent[jNr] (Post 2293295)
That method is much slower and uses more memory as well. I don't see the reason to do it that way.
Also, you should use an if statement when jumping to keys in case it fails, even if you tell it to create the key when it doesn't exist.

That way you don't "Go Back" when it never moved in the first place.

Noted, I didn't use if statements only because I had some error before related to that part and I didn't add them again.

Other than that, I do understand that it uses more memory, but I didn't really mind since I was only to use it once.

Potato Uno 05-04-2015 12:55

Re: Add two KeyValue files together
 
Is keyvalues really that much less efficient than databases in terms of data storage?

I figure adding something to RAM is faster than performing I/O, especially if you have no intention to store the data to disk (e.g. stats that are recorded during a round, and then are discarded on round finish).


All times are GMT -4. The time now is 19:32.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.