mIRC Home    About    Download    Register    News    Help

Print Thread
#225187 27/08/10 09:41 PM
Joined: Feb 2003
Posts: 3,432
S
sparta Offline OP
Hoopy frood
OP Offline
Hoopy frood
S
Joined: Feb 2003
Posts: 3,432
I have been trying to solve a problem a while now, i got items stored in a table the format is:

hadd table date. $+ $nick $date

This add the nick with a date in the table, and i want to remove the last one if the table is full. the table can hold 1000 items, and so far i have 786 stored items, how can i remove the oldest item so the table wont be full when im up to 1000 and i want to add one more, maybe somone have a bether idea then the use of $date ..


if ($me != tired) { return } | else { echo -a Get a pot of coffee now $+($me,.) }
Joined: Nov 2009
Posts: 295
P
Fjord artisan
Offline
Fjord artisan
P
Joined: Nov 2009
Posts: 295
well from what you said I get the impression you think there is a limited number of items you can add. You can add as many things to a hash table as you wish if that's your concern. Read the help if you don't believe me.

If you would just want to limit it to a max of 1000 regardless of their being no limit. I believe hash tables always add more items to the "end" so you could just remove the first item in the table. Which you can get the name by using $hget(tablename,1).item

Last edited by pball; 27/08/10 11:27 PM.

http://scripting.pball.win
My personal site with some scripts I've released.
Joined: Dec 2002
Posts: 2,962
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Dec 2002
Posts: 2,962
Quote:

If you would just want to limit it to a max of 1000 regardless of their being no limit. I believe hash tables always add more items to the "end" so you could just remove the first item in the table. Which you can get the name by using $hget(tablename,1).item

No a hash table is an unsorted structure, there is no beginning or end. $hget(tablename, 1).item will return an arbitrary item completely unrelated to the order it was added.


Spelling mistakes, grammatical errors, and stupid comments are intentional.
Joined: Nov 2009
Posts: 295
P
Fjord artisan
Offline
Fjord artisan
P
Joined: Nov 2009
Posts: 295
whoops, didn't think of that.

Then I guess you'd have to loop through each item and find the oldest value. If you want just the oldest item, I'd suggesting using $ctime, which is just the amount of time in seconds from date. You can convert it to a normal form of date also. I suggest using $ctime since the smaller the number the older the date and the easier to compare it is.


http://scripting.pball.win
My personal site with some scripts I've released.
Joined: Dec 2002
Posts: 2,962
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Dec 2002
Posts: 2,962
Is there any particular reason you are using a hash table to store this information? It seems like you would be better off using an ordered method of storing information such as a window or file.

In that case you could use aline to add entries and something like:
if ($line(@mydata,0) > 1000) dline @mydata 1- $+ $calc($v1 - 1000)
to trim it down to 1000 entries.


Spelling mistakes, grammatical errors, and stupid comments are intentional.
Joined: Nov 2009
Posts: 295
P
Fjord artisan
Offline
Fjord artisan
P
Joined: Nov 2009
Posts: 295
the following code finds the oldest value in the hast table test with the following format.
//hadd test date.pball $ctime
Just call the alias and it echos the oldest item and then deletes it
Code:
alias oldest {
  set -l %num 1
  set -l %oldest $ctime
  while ($hget(test,%num).data) {
    if ($hget(test,%num).data < %oldest) { set -l %oldest $v1 | set -l %item $hget(test,%num).item }
    inc %num
  }
  echo -a %item
  hdel test %item
}


warning this could take a while with 1000 entries and you could call it like if ($hget(test,0).item == 1000) oldest


http://scripting.pball.win
My personal site with some scripts I've released.
Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
Just so you know, hmake table 1000 does not make 1000 slots for data.

If you still want to delete the last item you need to know what order they are in. What you can do is add a number to the name.

/hadd table $+($calc($hget(table,0).item + 1),date.,$nick) $date

When I make the table I'm getting the total number of items in the table and adding 1 to it. I used the $+ identifier to join the data.

So your entry will look like.

1date.Nickname date

Now if you want to remove the last number, you can use $hget(table,0).item to get your total number. So if that returns 756, you know to delete 756.

If you want to delete the top 10 you know its 746 - 756.

var %x = $hget(table,0).item, %y = $calc(%x - 10)

You can use /hdel -w table 756* to delete it.


Quote:
maybe somone have a bether idea then the use of $date ..

I don't know why you want to store the date. Thats up to you.

Last edited by DJ_Sol; 27/08/10 11:58 PM.
Joined: Feb 2003
Posts: 3,432
S
sparta Offline OP
Hoopy frood
OP Offline
Hoopy frood
S
Joined: Feb 2003
Posts: 3,432
I trying to make a seen script, and i add every nick to the hash table with..
Code:
on *:join:#: {
  if ($nick != $me) && ($seen.chans == $true) {
      hadd seen action. $+ $nick join
      hadd seen channel. $+ $nick $chan
      hadd seen time. $+ $nick $ctime
      hadd seen network. $+ $nick $network
    }
  }
}

and i want the script to clear out the oldest data, not that good if you let the table be to big.

I removed the date part


if ($me != tired) { return } | else { echo -a Get a pot of coffee now $+($me,.) }
Joined: Aug 2010
Posts: 134
T
Vogon poet
Offline
Vogon poet
T
Joined: Aug 2010
Posts: 134
If you're not using any other identifiers, you'll have to find the one with the lowest time.

Code:
while $hfind(seen, time.*, 0, w) > 999 {

  ;Set %time to $ctime at start. Compare all entries to this %time variable.
  var %time $ctime

  ;Check all time. entries.
  var %count 0
  while %count < 1000 {
    var %count $calc(%count + 1)
    var %entry $hfind(seen, time.*, %count, w)

    ;If the value for this entry is lower than %time, this is the lowest entry found so far.
    if $hget(seen, %entry) < %time {
      var %time $hget(seen, %entry)
      var %nick $right(%entry, -5)
    }
  }

  ;Remove the oldest entry
  hdel seen action. $+ %nick
  hdel seen channel. $+ %nick
  hdel seen time. $+ %nick
  hdel seen network. $+ %nick
}


Put the code in your on join script or in it's own alias, and whenever there are more than 999 entries, it will keep deleting the highest entry until 999 are left.

PS. it might be smarter to base your database on time instead of simply the last 1000 entries.

EDIT: $+ between time. and * was kind of obsolete :P

Last edited by Thels; 28/08/10 05:31 PM.

Learning something new every day.
Joined: Aug 2004
Posts: 7,252
R
Hoopy frood
Offline
Hoopy frood
R
Joined: Aug 2004
Posts: 7,252
As this is untested, I recommend that you backup your hash table entries before trying this.

Usage is /purge

It should, determine the oldest time entry in the current hash table, then delete from the table those entries that match.

Code:
alias purge {
  var %a = 1, %b = $hget(seen,0).item, %oldest.time
  while %a <= %b {
    if (time.* iswm $hget(seen,%a).item) {
      if !%oldest.time || (%oldest.time > $hget(seen,%a).data) {
        %oldest.time = $v2
      }
    }
    inc %a
  }
  while $hfind(seen,%oldest.time,0,w).data {
    var %nick = $hget(seen,$hfind(seen,%oldest.time,0,w).data).item
    %nick = $gettok(%nick,2,46)
    .hdel -w seen $+(*.,%nick)
  }
}


If this works as I think, then you'll be able to use it to purge the oldest data when you want and/or have it called automatically if the number of entries in the table exceeds a certain level.

Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
Personally I would store all that information in one slot.

hadd table seen.$nick $event $chan $ctime $network
Now you can use $gettok to grab the data you want from each entry. Space isn't the best delimiter IMO I just used it here as a basic example.

If you want to delete the last one I would add the integer to the item name, as I showed above. If you want to keep them as seperate entries then I would make a table for each one.

hadd action $nick $event
hadd channel $nick $chan
hadd time $nick $ctime
hadd seen $nick $network

Then a table that listed the nicks in order of appearance like I showed you above. That would be your master list.

hadd master $calc($hget(master,0).item + 1) $nick
( Stored as $hget(master,1) = $nick )

If you wanted the last nickname, you find the last nick in this list then use that nick to reference the entries in the other tables.

$hget(master,$hget(master,0).item) = last nickname entered.

The way you have it set up seems to messy to me.

Joined: Feb 2003
Posts: 3,432
S
sparta Offline OP
Hoopy frood
OP Offline
Hoopy frood
S
Joined: Feb 2003
Posts: 3,432
I did change the code a bit and i using the line:

hadd seen $+($nick,|,$event,|,$chan,|,$network,|,$ctime)

But i still cant get it to delete the oldest post. Been testing a bit with the code examples i was given here, and no luck with them. so somone that have any other idea how to deal with this?

//echo -a -> $gettok($hget(seen,N).item,5,124)

return the time to me.


if ($me != tired) { return } | else { echo -a Get a pot of coffee now $+($me,.) }
Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
I told you how to number them and then delete them.

You have to k eep track of the order in a hash table. The item number doesn't get saved in order. Do not store the data in the item name, store it in the data section.

/hadd seen $nick $+($event,|,$chan,|,$network,|,$ctime)

I suggested you add an integer to the item name so you know the order. You could evaluate the time and find the latest time but that would take a lot of parsing. When you add the entry, simply include the number. Since it will be the last item entered, the number would be the total of items in the table plus 1.

/hadd seen $+($calc($hget(seen,0).item + 1),.,$nick) $+($event,|,$chan,|,$network,|,$ctime)

This will be stored as 1.Nickname event|chan|network|ctime.

To delete the last entry, you could use this:

/hdel -w seen $+($hget(seen,0).item,.*)

If you wanted to delete the last 5...

Code:
var %total = $hget(seen,0).item, %last5 = $calc(%total - 5)
while (%last5 <= %total) {
hdel -w seen $+(%last5,.*)
inc %last5
}


This code and idea wouldn't work well if you wanted to remove the 25th entry in a list of 200. It will only work successfully if you are removing the last entries of the list. Since that is what you specifically asked for, this is the simplest solution I can think of.

Also, I wrote this here without testing. Let me know if you have issues.


Link Copied to Clipboard