mIRC Home    About    Download    Register    News    Help

Print Thread
#150184 29/05/06 06:50 PM
Joined: Apr 2006
Posts: 464
O
Fjord artisan
OP Offline
Fjord artisan
O
Joined: Apr 2006
Posts: 464
I am currently working on a script that has to find information in a hash table, and retreive it.

The table is set up like:
<item> <data>

The <data> part is one string, seperated by horizontal tabs, representing columns. Like:
x ($chr9) y ($chr9) z ($chr9) name ($chr9) size ($chr9) score
1 ($chr9) 1 ($chr9) 1 ($chr9) blah ($chr9) 294 ($chr9) 25135
1 ($chr9) 1 ($chr9) 2 ($chr9) booh ($chr9) 954 ($chr9) 58462
... and this continues for like another 4000 lines.

Now I want to be able to retreive for example a top5 with the highest value in the size column or a top5 with highest value in score column.

Is this possible? And if so, can anyone help me getting going with the (I think $hfind and $hget) commands?

Your help is appreciated confused

#150185 29/05/06 08:06 PM
Joined: Jan 2003
Posts: 3,012
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2003
Posts: 3,012
The only ways I can see approaching this would be from a binary standpoint, i.e. go one by one and look for the top 5. No way of doing it with a mIRC cal, or so I'm aware.

That being said, do you have a ceiling on the score or size values, or can they continue to grow? If you know the ceiling, go in reverse order (counting down) and look for the table entry with the highest value, then subtract one. Look for the next highest, etc. Keep a queue of 5 "tops", and display them.

I'll see what i can do playing around with it. If anyone wants to play with it as well, here's a generator to give you something to work with:

Code:
alias pinfo {
  var %tbl = pinfo, %entries = 100

  if (!$hget(%tbl)) {
    /hmake %tbl 10

    var %p = 0, %tab = $chr(9)
    while (%p &lt; %entries) {
      var %n = 0, %len = $rand(6,12)
      while (%n &lt; %len) {
        var %name = $+(%name,$rand(a,z))
        /inc %n
      }
      /hadd %tbl %p $+($rand(1,10),%tab,$rand(1,10),%tab,$rand(1,10),%tab,%name,%tab,$rand(1,1000),%tab,$rand(1,65535))
      /unset %name
      /inc %p
    }
    /echo -s Table %tbl created with %p entries
  }
}


-KingTomato
#150186 29/05/06 08:34 PM
Joined: Jan 2003
Posts: 3,012
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2003
Posts: 3,012
Code:
alias pfind {
  var %tbl = pinfo, %tsize = $hget(%tbl,0).item, %win = @pinfo_srt, %win2 = @pinf_srtd

  ; add to window
  /window -h %win
  /window -h %win2
  var %p = 1
  while (%p &lt;= %tsize) {
    /aline %win $+($hget(%tbl,%p).item,$chr(9),$hget(%tbl,$hget(%tbl,%p).item))
    /inc %p
  }

  ; sort
  if ($1 == size) /filter -tuww 6 9 %win %win2
  else if ($1 == score) /filter -tuww 7 9 %win %win2

  ; Output
  var %lines = $line(%win2,0), %l = %lines - 5, %c = 1
  if (%l &lt; 0) var %l = 0
  while (%lines &gt; %l) {
    /echo -s $+(%c,.) $line(%win2,%lines)
    /inc %c
    /dec %lines
  }

  /window -c %win
  /window -c %win2
}


Nevermind wink /filter was just what i needed. Should work fine, and give you the results you want. You may even decide to make it call an alias, or reroute the information. As it is, change the /echo in the ; output section to do what you'd like. Also, change the %tbl variable to the name of your own table.

[edit]If you want to sort by anything else (name maybe, or even descending) fool with the filters. These will give you descending sorts for either option:

Code:
  ; sort
  if ($1 == size) /filter -tuww 6 9 %win %win2
  else if ($1 == score) /filter -tuww 7 9 %win %win2
  else if ($1 == sizedesc) /filter -etuww 6 9 %win %win2
  else if ($1 == scoresesc) /filter -etuww 7 9 %win %win2


use /pfind <size|sizedesc|score|scoredesc>


-KingTomato
#150187 29/05/06 08:47 PM
Joined: Apr 2006
Posts: 464
O
Fjord artisan
OP Offline
Fjord artisan
O
Joined: Apr 2006
Posts: 464
OMG, it works!

Alright, at the moment I have no idea how or why it works, but it definately does what I asked.

I'll go check the code out smile

Thx a lot KingTomato


[Edit]
This is really perfect. There are more fields indead that I might want to have the sorting on. I'll go play with it a bit.
Thx again man.

Last edited by OrionsBelt; 29/05/06 08:49 PM.
#150188 29/05/06 09:02 PM
Joined: Apr 2006
Posts: 464
O
Fjord artisan
OP Offline
Fjord artisan
O
Joined: Apr 2006
Posts: 464
Hmm, one other problem I now get.
The file contains a header, like file contents and stuff:

1. 1 HTTP/1.1 200 OK
2. 2 Date: Mon, 29 May 2006 20:06:06 GMT
3. 3 Server: Apache/2.0.54
4. 4 Last-Modified: Mon, 29 May 2006 20:02:01 GMT

Is there are way to get rid of this information?
Perhaps by not inserting it in the table at the beginning already?

Is it possible to specify where to start when loading a file into a hash table? Like start from line 15 till the end of the file?

(Especially with the desc functions, these are playing up).

Last edited by OrionsBelt; 29/05/06 09:08 PM.
#150189 29/05/06 11:46 PM
Joined: Jan 2003
Posts: 3,012
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2003
Posts: 3,012
Either don't input it in to the table, or change the %p below the /window commands.
I'm assuming you're readin this info off a web page, maybe just eliminate the reading of the header?


-KingTomato
#150190 30/05/06 02:13 AM
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Another way of doing it is to use HSAVE, as on tables of any size say the 4000 one he said he had, its much faster to output the hashtable to a file and sort it there.
Code:
alias pfind2 {
  var %tbl = pinfo
  ;
  ; save table (data only)
  hsave -n %tbl temp.txt
  ;
  ; sort
  if     ($1 == size)      { filter -ffctuen 5 9 temp.txt temp.txt }
  elseif ($1 == score)     { filter -ffctuen 6 9 temp.txt temp.txt }
  elseif ($1 == sizedesc)  { filter -ffctun  5 9 temp.txt temp.txt }
  elseif ($1 == scoredesc) { filter -ffctun  6 9 temp.txt temp.txt }
  else                     { return } | ; no valid sort directive
  ;
  ; Output for example
  var %i = 1, %m = 5
  while (%i &lt;= %m) {
    echo -s $+(%i,.) RAWinFILE = $read(temp.txt,nt,%i)
    inc %i
  }
  echo -s 
  var %i = 1, %m = 5
  while (%i &lt;= %m) {
    echo -s $+(%i,.) PROCESSED = item $hget(%tbl,$gettok($read(temp.txt,nt,%i),1,32)).item data $hget(%tbl,$gettok($read(temp.txt,nt,%i),1,32)).data
    inc %i
  }
  echo -s 
  .remove temp.txt
}


example
/pfind2 score
1. RAWinFILE = 2431 2<tab>1<tab>4<tab>pguyda<tab>915<tab>65534
2. RAWinFILE = 3683 9<tab>3<tab>8<tab>cnitrkds<tab>557<tab>65529
3. RAWinFILE = 1046 10<tab>2<tab>6<tab>xmzdtttgus<tab>528<tab>65525
4. RAWinFILE = 3016 3<tab>9<tab>10<tab>hvvzem<tab>423<tab>65518
5. RAWinFILE = 1497 1<tab>8<tab>8<tab>quifcdp<tab>144<tab>65515

1. PROCESSED = item 3635 data 2<tab>1<tab>4<tab>pguyda<tab>915<tab>65534
2. PROCESSED = item 2828 data 9<tab>3<tab>8<tab>cnitrkds<tab>557<tab>65529
3. PROCESSED = item 2036 data 10<tab>2<tab>6<tab>xmzdtttgus<tab>528<tab>65525
4. PROCESSED = item 1130 data 3<tab>9<tab>10<tab>hvvzem<tab>423<tab>65518
5. PROCESSED = item 2022 data 1<tab>8<tab>8<tab>quifcdp<tab>144<tab>65515

The methodology (i think thats the right word for it), is that when u hsave a hashtable, it is saved in the same order as you can access it using the $hget(table,N).item & .data properties (i would assume this is physical order in memory).
So you hsave just the data, but when u filter sort it, u add the -n option that adds line numbers to the output file (line number of the line from the input file), this gives u the N value to backrefrence into the table using $hget(table,N).item

*
Considering also what the OP has stated about the hashtable being loaded from a file in the first place, the key might infact be to filter sort the file before its even loaded into the table, thus giving the actual itemnames 1,2,3,4,5 the 5 in order he wants. Im still a bit unclear on what hes doing with that tho. sicne the sort might be something he wants done afterwards at some later time.

**
On a personal note, glad to see you back KT, You were here in a major way when i first started using mirc to script stuff, and I respected your input on anything i was doing, yours and a few others i wont name here tho incase i miss someone in the list, although the initials FO come bounding out of the page as someone who also deserves credit for his help.

#150191 30/05/06 06:46 PM
Joined: Apr 2006
Posts: 464
O
Fjord artisan
OP Offline
Fjord artisan
O
Joined: Apr 2006
Posts: 464
Alright, to give a bit of feedback.
I play this game, with loads of planets. MikeChat helped me downloading their database dumps in this thread

So, the idea of the script is to read that txt file using my bot.
Like !whois x:y:z will give you information on size, score etc. Almost like an interface to the game itself cool

When searching ($read) for info from this txt file, using wildmatch (iswm) characters, and processing all 3200+ lines, I noticed it freezes my bot for like 10 to 12 seconds. And that was for only 1 request, imagine 5 people use the same command!!!! Obviously not the way forward. So I started using hash tables instead and load the txt file in a hash table every hour.

Now I want to make all kinds of scripts that can read from this hash table. Like for example the top5 requested above.

I have to say the script of KingTomato works like a charm. I'm fine tuning that, and it's now returning the info in like 2/3 seconds. Obviously already a lot better.

Thx to ya'll for the help guys laugh

#150192 30/05/06 10:18 PM
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
10 to 12 seconds to read a text file with 3200 lines using wildmatch? omg where did u save the file to floppydisk?
I loaded KingTomatoe's and ran it, and his was taking around 1.05 seconds to function on mine now here is the problem with that
the 1.00 was to get the hashtable data into the window
the 0.05 was to sort it and output it in the order wanted
see the problem
using /hsave -n table file | /filter -ff file file method, takes around 0.10 seconds to hsave and 0.06 seconds to display results 0.16 is significantly better than 1.05.
assuming your getting 2 to 3 second results, i would assume that translats to 0.36/0.48 second results using /hsave

I well look at this other thread u mentioned and maybe come back with example code of how to source from the file itself.

* either way, I think a better solution for you might be to load the file to a hidden window, rather than a hashtable, a hashtables advanatage is for quick access to each bit of data based on supplying its unquie ITEMNAME, from what i understand your keeping all the info in the data, and thus this makes the use of a hashtable unlikely to be the correct tool.

#150193 31/05/06 12:23 AM
Joined: Sep 2003
Posts: 4,230
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Sep 2003
Posts: 4,230
Code:
;
;usage /updateinfo
;
alias updateinfo { 
  sockclose gameinfo
  sockopen gameinfo game.planetarion.com 80
}
on *:sockopen:gameinfo:{
  ///echo -st sockopen : $sockname
  sockwrite -n $sockname GET http://game.planetarion.com/botfiles/planet_listing.txt HTTP/1.1
  sockwrite $sockname HOST: game.planetarion.com $+ $crlf $+ $crlf
  .remove GAMEINFO.NEW
}
on *:sockread:gameinfo:{
  if ($sockerr &gt; 0) return
  if ($sock(gameinfo).mark != 2) {
    var %txtvar
    sockread -n %txtvar
    ///echo -st sockread : TXT : $sock(gameinfo).mark : $len(%txtvar) : %txtvar
    if (!$len(%txtvar)) {
      sockmark gameinfo $calc($sock(gameinfo).mark +  1) 
    }
  }
  else {
    sockread &amp;binvar
    ///echo -st sockread : BIN : $sock(gameinfo).mark : $bvar(&amp;binvar,0)
    bwrite GAMEINFO.NEW -1 -1 &amp;binvar
  }
}
on *:sockclose:gameinfo:{ 
  ///echo -st sockclose : $isfile(GAMEINFO.NEW)
  if ($isfile(GAMEINFO.NEW)) { 
    .remove GAMEINFO.TXT
    .rename GAMEINFO.NEW GAMEINFO.TXT
    hfree -w GAMEINFO
    hmake  GAMEINFO 1000
    hload -n GAMEINFO GAMEINFO.TXT
  }
}
;
;usage /sort.gameinfo N [A|D]
;  or
;usage $sort.gameinfo(N,[A|D])
;
; N = column to sort on
; A = Assending sort
; D = Descending sort (default if not entered)
;
;returns $true if completed, $false if failed.
;
alias sort.gameinfo {
  if (($int($1) isnum 1-10) &amp;&amp; (($2 == $null) || ($2 == A) || ($2 == D))) {
    hsave -n GAMEINFO GAMEINFO.TXT
    filter $+(-ffcu,$iif(($2 == A),e),t) $int($1) 9 GAMEINFO.TXT GAMEINFO.TXT
    hfree -w GAMEINFO
    hmake GAMEINFO 1000
    hload -n GAMEINFO GAMEINFO.TXT
    return $true
  }
  else { return $false }
}
;
; To access the sorted order of the hashtable use $hget(GAMEINFO,N)
; N = value of order position required,;
;
; example1: top five scores (column 8)
; //sort.gameinfo 8 D
; //echo -a 1st $hget(GAMEINFO,1)
; //echo -a 2st $hget(GAMEINFO,2)
; //echo -a 3st $hget(GAMEINFO,3)
; //echo -a 4st $hget(GAMEINFO,4)
; //echo -a 5st $hget(GAMEINFO,5)
;
; example2: top five size (column 7)
; //sort.gameinfo 7 D
; //echo -a 1st $hget(GAMEINFO,1)
; //echo -a 2st $hget(GAMEINFO,2)
; //echo -a 3st $hget(GAMEINFO,3)
; //echo -a 4st $hget(GAMEINFO,4)
; //echo -a 5st $hget(GAMEINFO,5)
;


ok i updated the pull down code a little, normally u want to just dump the file header (ends at the first $null string), but i noticed the actual data u want has some lines before it, followed by a $null string (empty line), so i dump everything before the 2nd $null, I then switch to binary read, just becuase i do my sockreads like that to file.

The echos with 3 /// at the front are just so u can observe it in action, remark or remove them when you feel like it.

I make a file called GAMEINFO.NEW, and only once its completed do i replace the GAMEINFO.TXT file, this is becuase anything might happen during the downloading process (website fails etc)

ok and once its downloaded, it replaces the old GAMEINFO hashtable
I assumed NO OTHER DATA exists in the table. If it does i would suggest you use a second tablename to hold it.

now since there is no itemnames just data i used the /hload -n option to load the data meaning the table is revrenced using itemnames 1,2,3.... but its just in the order it came from the website.

Now if u want sorted order simply used $sort.gameinfo(Column,[A|D]) A=accending D=deccending (default if u dont put it in)

what this does is actually dumps the hashtable to file, sorts it as needed and reloads it into the hashtable, the data thus gets issued itemnames 1,2,3.... in the order you speciifed

* On tables the size yours are this is a functional and fast option, dont be doing it on tables 20meg in size in other words (well actually i do but hey i got bulk ram)

#150194 31/05/06 05:36 AM
Joined: Apr 2006
Posts: 464
O
Fjord artisan
OP Offline
Fjord artisan
O
Joined: Apr 2006
Posts: 464
That looks pretty amazing DaveC.
I'm gonna test a little with it tonight, and see how the code works in practise.
This code at the moment is way over my head, but by testing and trying I should be able to understand how it all works.

In any case a big thx for your effort, looks really slick.

#150195 05/06/06 12:48 AM
Joined: Feb 2004
Posts: 2,019
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
Quote:
On a personal note, glad to see you back KT, You were here in a major way when i first started using mirc to script stuff, and I respected your input on anything i was doing, yours and a few others i wont name here tho incase i miss someone in the list, although the initials FO come bounding out of the page as someone who also deserves credit for his help.


o.O that's nice to hear! And I think you are one of the best helpers around here for the last year, and one of the best scripters around here as well. smile


Gone.

Link Copied to Clipboard