Okay, back to working on my IRC bot again.

I finished getting sqlite3 support as per Jonimus's suggestion, and now it will retrieve data from a local database. Now, I'm trying to get my IRC bot to count how many times each person in my channel swears, and then will announce when someone hits a certain number of swears.

I took into account that, people sometimes will swear multiple times in the same line, and made it count the number of times that each person swears in each line with variable swearCount. After that, it increments their number in the database, then stores their total number of times sworn before incrementing as swearTotalOld, and after incrementing as swearTotalNew.

I'm currently trying to get it so it will announce when someone hits a certain number of times sworn, so I made it just something simple, every 5 times, and when you swear the first time. (range(0,1000,5) or 1).

However, I quickly realized that if per se I was at 4, then I swore twice, I would cross right over 5, and my bot wouldn't announce that I went over 5. I'm trying to think of a way in which to make it see that someone has crossed over any of the values in the given list. Any ideas?
Oooh, let's see, that's a good question. I think I have the answer.

1) If the new number is exact. This one's obvious:

Code:
if swearTotalNew in xrange(0,1000,5).append(1):


2) If the new number crossed a border. This one will take advantage of signedness:


Code:
sgn = lambda x : (x>0) - (x<0)
if -1 in [sgn(aa-swearTotalNew)*sgn(aa-swearCount) for aa in xrange(0,1000,5)]:
I honestly have no idea how yours works, (and I don't like using code I don't have some understanding of) so I played with the console for a while until I found one that works nicely with one line. It uses the fact that when you divide one integer by another, it returns the floor value (largest integer in the given number) of what should be the dividend, then detects if that changed.


Code:
if swearTotalOld==0 or swearTotalOld/5!=swearTotalNew/5:


I don't like that it's not referring to an actual given list or that this could very well not work in other languages, but I do like how it's simple and works needing only that one line of code.

Also, I'm trying to improve my method for finding when people swear. Currently, it will look through each word in their message and look to see if the word contains any profanity, then count each up. It sets all messages to lower case and removes punctuation, but I can't think of any way to reliably remove repeated letters (for instances like people saying "daaaaamn") without having to worry about cases like "a" becoming "as," a perfectly acceptable word.

Opinions?
Let me explain how mine works, then.

1) Calculate 5, 10, 15, .... -oldvalue.
2) Calculate 5, 10, 15, .... -newvalue.
3) Say that oldvalue is 4 and newvalue is 6. 5-4 is positive, and 5-6 is negative. If corresponding old/new values changed sign, then the number crossed a multiple-of-five boundary.
4) Multiplying signs, neg to neg is -1*-1=1, pos to pos is 1*1=1, but boundary crossing is 1*-1=-1, so if the list containing the products of the signs has any -1s in it, the number crossed a boundary. You essentially do the same solution, more efficiently (but less fun use of list iteration).
KermMartian wrote:

Code:
sgn = lambda x : (x>0) - (x<0)
if -1 in [sgn(aa-swearTotalNew)*sgn(aa-swearCount) for aa in xrange(0,1000,5)]:


0.0

Holy wasteful code, batman!


Code:
def shouldPrint(old, new):
    if old == 0 and new > 0: return True
    if (new - old) >= 5: return True
    if new % 5 == 0: return True
    if (new % 5) < (old % 5): return True
    return False


Consolidate to one line if you want
Want to buy logical "or" operator. Razz
KermMartian wrote:
Want to buy logical "or" operator. Razz


That's left as an exercise to the reader. I wasn't sure you guys would be able to follow such complex code, seeing as you all were doing ridiculously insanity stuff with iterators and lambdas.

I mean really, a slow O(N) solution that includes creating a giant list in memory and loops twice when a fast O(1) solution with no loops is trivial? Guess that's why I work at Google and you don't Razz
Kllrnohj wrote:
I mean really, a slow O(N) solution that includes creating a giant list in memory and loops twice when a fast O(1) solution with no loops is trivial? Guess that's why I work at Google and you don't Razz
Yes, because I obviously didn't see the trivial solution at all, and definitely wasn't trying to use the opportunity that the OP had mentioned ranges as a solution to introduce him to lambda functions and to list statements. Surely the reality is that I'm such a horribly poor programmer that I write disgustingly wasteful code.
KermMartian wrote:
Yes, because I obviously didn't see the trivial solution at all, and definitely wasn't trying to use the opportunity that the OP had mentioned ranges as a solution to introduce him to lambda functions and to list statements. Surely the reality is that I'm such a horribly poor programmer that I write disgustingly wasteful code.


Good for you, the first step is admitting you have a problem. Clearly you are addicted to syntax sugar crack. I know, I know, Python makes it so much fun, but sometimes you've just got to say no.

Oh, and stop being a horribly poor programmer.
Kllrnohj wrote:
Oh, and stop being a horribly poor programmer.
Will do.
What are some good modules for trying to make a UI of some sort with windows? I've been trying to make one with Tkinter, but I can't seem to get the hang of it and wanted to see if there are others available, or if Tkinter is my only option.


I'm trying to see if I could make my own UI for my IRC bot at all, so it's easier to manage some of the data for it, and have generally better control over what it's doing, and eventually use that experience to try and make my own IRC client for myself. Which brings me to my second problem. I'd like to figure out how to get my program to both receive messages from the IRC server, and how to send them. Currently, my bot will receive messages via s=socket.socket(); s.recv(1024), however the problem with that is that it will sit at s.recv(1024) until it receives a message. This means that should I get a proper UI for an IRC client running, then I'd have to wait for the client to be pinged to be able to send a message.

Before anyone mentions it or anything like it, I know this is because I'm too used to seeing programs as one line of code after another, and not knowing or being used to trying to run codes parallel inside of the same program.

I'd appreciate any help that doesn't shoo me off to google. ;P
Most other GUI libraries will not be significantly different from Tkinter. Since Tkinter is a part of the standard install, it might be worth your time to get familiar with it.
Your problem with receive is that the call is blocking; just use s.setblocking(0). Be aware that a socket.Error will be thrown if no data is available.
Feel free to use Google to supplement your knowledge.
(Also, there are more sophisticated ways to handle sockets in a non-blocking manner, but for only one socket it's not worth getting into them. Alternately, you could use threads, with a thread devoted to reading bytes into some shared structure.)
A couple of gui libraries to take a look at, are wxPython and pygtk.

Edit: Also there is pyqt.
For threading, you should check out my FeedScreamer project, which you can download here, to get an idea of basic threading. There are easy ways to do non-blocking sockets without threads too; I'll share code from the Python gCnHub application if you'd like.
Kerm, like setblocking(0), which I mentioned in my post? Wink
The other option is the select module.
Indeed, setblocking(0) along with a try/catch around EWOULDBLOCK is both the correct and the Pythonic solution, as far as I can tell. Smile
Hey guys, I know that mathematically speaking, X/Y/Z = X/(Y*Z), but I was wondering if in Python, the same would be the case when dividing integers. So for instance, when trying to find number of hours when give time, would I be better off using second/60/60 or will seconds/3600 be just as reliable? Also, all of this is ignoring modulus for number of hours exceeding 24.
As long as you're dealing strictly with integers, it will be the same. If you start getting into floating-point numbers, you'll run into precision problems, but with integers you're fine.
Alright thanks, appreciate the info.

In the end, this is the bit of code I used it for. I'm sure there's something like this that already exists, but I'd rather make my own code than figure out someone else's code:

Code:

def timeAgoToString(time):
    import string
    resultRaw=[]
    if 1==time/(60*60*24*365):
        resultRaw.append("1 year")
    if 1<time/(60*60*24*365):
        resultRaw.append("%s years" % int(time/(60*60*24*365)))
    if 1==time/(60*60*24)%365/7:
        resultRaw.append("1 week")
    if 1<time/(60*60*24)%365/7:
        resultRaw.append("%s weeks" % int(time/(60*60*24)%365/7))
    if 1==time/(60*60*24)%365%7:
        resultRaw.append("1 day")
    if 1<time/(60*60*24)%365%7:
        resultRaw.append("%s days" % int(time/(60*60*24)%365%7))
    if 1==time/(60*60)%24:
        resultRaw.append("1 hour")
    if 1<time/(60*60)%24:
        resultRaw.append("%s hours" % int(time/(60*60)%24))
    if 1==time/60%60:
        resultRaw.append("1 minute")
    if 1<time/60%60:
        resultRaw.append("%s minutes" % int(time/60%60))
    if 1==time%60:
        resultRaw.append("1 second")
    if 1<time%60:
        resultRaw.append("%s seconds" % int(time%60))
    if 0==len(resultRaw):
        resultRaw=['0 seconds']
    result=''
    if 1==len(resultRaw):
        result=resultRaw[0]
    if 2==len(resultRaw):
        result=string.join(resultRaw,' and ')
    if 2<len(resultRaw):
        result=string.join(resultRaw[0:-1],', ')+', and '+resultRaw[-1]
    return result


I'm adding a feature to my IRC bot to log when people log in for the first time, and then let people know when it's asked, how long ago that was. And since this is the third feature that could use code like this, I figured I'd finally make a more official method for itself to use.
Not bad! I feel like there must be a way to combine the 1 and N versions of each of those time units, but the efficient solution hasn't quite jumped out to me yet. It's not horrible as it is now, of course.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 2 of 3
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement