‽
|
I was encouraged to post random bits of code, so I figured I'd whip up a small app and post it here.
Code:
#!/usr/bin/env ruby
# Protocol docs: http://cho.cyan.com/chat/protocol1.html
#
# ToDo:
# - implement ignore
# - convert encodings (assumptions: CC uses Windows-1252; Ruby uses UTF-8)
# - make interactive
# - wrap UI around
#
require 'socket'
Version = "1.0d5"
DefaultHost = 'cho.cyan.com'
DefaultPort = 1812
DebugPort = 1813
C2SNickname = 10
C2SQuit = 15
C2SPrivMsg = 20
C2SRoomMsg = 30
C2SWelcome = 40
C2SIgnore = 70
S2CNickErr = 10
S2CNickSet = 11
S2CPrivMsg = 21
S2CMessage = 31
S2CWhoList = 35
S2CWelcome = 40
S2CIgnore = 70
GroupUser = 0
GroupCyan = 1
GroupServer = 2
GroupGuest = 4
Timestamps = 1
RotateLines = 1
Nickname = "cccccccTest"
class CCConnection < TCPSocket
attr_accessor(:alreadyWelcomed, :connectAutomatically)
attr_reader(:host, :port)
def initialize(host=DefaultHost, port=DefaultPort)
super(host, port)
@alreadyWelcomed = 0
@connectAutomatically = 1
end
def c2sCmd(cmd)
self.send(cmd, 0)
end
def c2sNickname(nick)
self.c2sCmd(C2SNickname.to_s + "|" + nick + "\n")
end
def c2sQuit()
self.c2sCmd(C2SQuit.to_s + "\n")
end
def c2sPrivMsg(userclass, nickname, message)
self.c2sCmd(C2SPrivMsg.to_s + "|" + userclass.to_s + nickname + "|^1" + message + "\n")
# e.g. 21|0chucker|^1foo\n
end
def c2sRoomMsg(message)
self.c2sCmd(C2SRoomMsg.to_s + "|^1" + message + "\n")
end
def c2sWelcome()
self.c2sCmd(C2SWelcome.to_s + "|1\n")
end
def c2sIgnore()
self.c2sCmd(C2SIgnore.to_s) # not implemented
end
end
def printx(output)
if Timestamps == 1
output = Time.now.strftime('%X ') + output + "\n"
end
print output
end
def errorx(output)
if Timestamps == 1
output = Time.now.strftime('%X ERROR: ') + output + "\n"
end
print output
end
def s2cPrivMsg(line)
if line.slice!(0) && (line[0].chr == GroupServer.to_s) && line.slice!(0) && line.include?("|^1")
messageArray = line.split("|^1")
messageSender = messageArray[0]
messageContent = messageArray[1]
printx "["+messageSender+"] "+messageContent
end
end
def s2cWhoList(line)
line.slice!(0)
puts line
whoHash = Hash[*line.split("|").map! {|x| x.split(",")}.flatten]
# this isn't actually useful;
# we need to store the Group as well, which is completely retarded but such is life.
# Two-dimensional array, I suppose.
puts whoHash.class
puts whoHash.to_s
puts whoHash["chucker"]
# when RespWhoList.to_s
# if bufferLines[0][0] == "|"
# while bufferLines[0].length > 0
# bufferLines[0].slice!(0)
# while bufferLines[0][0] != ","
# tmp += bufferLines[0][0]
# end
# puts tmp
# whoList[]
# end
# end
end
def s2cWelcome(line)
printx(line)
end
def handleResponse(connection, line)
case bufferCmd = line.slice!(0,2)
when S2CPrivMsg.to_s
s2cPrivMsg(line)
when S2CWhoList.to_s
if line.length > 1
if line[0].chr == "|"
line.slice!(0)
s2cWhoList(line)
else
errorx("Erroneous who list response! " + line)
exit
end
else
printx("Room is empty")
end
when S2CWelcome.to_s
if line[0..1] == "|1"
line.slice!(0,2)
s2cWelcome(line)
if connection.alreadyWelcomed == 0
connection.alreadyWelcomed = 1
if connection.connectAutomatically == 1
connection.c2sNickname(Nickname)
sleep 3
connection.c2sPrivMsg(GroupUser, "chucker", "PM test")
connection.c2sRoomMsg("Hi!")
connection.c2sQuit()
exit
end
end
else
errorx("Erroneous welcome response!")
exit
end
else
puts "cmd "+bufferCmd+"\n"
end
end
connection = CCConnection.new()
connection.c2sWelcome()
i=1
while # this line / condition needs fixing, i.e. "while connection open"
buffer = connection.recv(1024)
# puts connection.alreadyWelcomed
bufferLines = buffer.split(/\r\n/)
puts bufferLines.length.to_s+" lines"
puts bufferLines[0]
if bufferLines.length > 1
while bufferLines.length > 1
if RotateLines == 1
bufferLines.reverse!
end
handleResponse(connection, bufferLines[0])
bufferLines.slice!(0)
end
else
handleResponse(connection, bufferLines.to_s)
end
i+=1
end There's various big problems with this code, notably:
As such, the anticipated improvements are:
Now, I don't know much about 1). As for 2): I know next to nothing about this. Sure, I can use primitive functions like "gets", but that's not exactly my idea. I experimented with ncurses about a year ago, in C, but didn't really like my results of that either. ![]() Finally, 3): is it possible at all to put received commands in the class? After all, class methods are there to send a message to the class, not to receive one from it, so it's somewhat illogical. Am I missing something? Any pointers whatsoever appreciated. ![]() |
quote |
Veteran Member
Join Date: May 2004
Location: Clayton, NC
|
Chucker, can we have your English (non-code) description of what this program does? We need to know the higher-level purpose/design of this program in order to determine if you've done a good job of translating that into code.
I can kind of tell what it's up to, but I'd like to know what you were wanting to create. Ugh. |
quote |
Senior Member
|
I can't really help much with the actual code, as I'm still learning Ruby (Although, I'll look through it... It will probably help my knowledge)
However, RubyCocoa seems like some good bindings, if you're looking for a GUI. EDIT: Just read you wanted it on Windows... Tk has Ruby bindings, and is pretty well accepted (from the tutorials I've seen) |
quote |
‽
|
Quote:
Right now, the program logs in with a predefined name ("cccccccTest"), sends a public message "Hi!", sends a private message "PM test" to "chucker" (if he's there) and logs back out. It displays some debugging info as well. |
|
quote |
‽
|
Quote:
|
|
quote |
Not a tame lion...
Join Date: May 2004
Location: Narnia
|
Quote:
![]() |
|
quote |
Not a tame lion...
Join Date: May 2004
Location: Narnia
|
Also, as far as critical assessment goes, if I may be so bold
![]() Does ruby support breaking up your program into different files ? If so that would be a good start to making it more object oriented (if that is what you are still interested in). A basic textbook example would have you break up your program into a class for the object and a driver class that instantiates the object (and then does stuff with it). I can see where you have defined CCConnection and then instantiated it again with connection = CCConnection.new(). Normally you would want to separate these into two different files. Although it doesn't serve much practical purpose now, if you wanted to reuse your CCConnection class in another program without cutting, pasting, and tweaking, you would be better off having it separate from the start. Of course, if ruby doesn't work like this then... umm, please disregard everything I said ![]() |
quote |
Antimatter Man
Join Date: May 2004
Location: that interweb thing
|
Your code is ugly and its mother dresses it funny.
![]() |
quote |
‽
|
Quote:
![]() Actually, turns out my brother came by and insulted it enough already, so I'm in the process of rewriting it to use more classes, and then, uh, I'll maybe get back to you. |
|
quote |
‽
|
Quote:
![]() |
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Java is a much better idea than Ruby, because it forces you to do everything in classes, you have to declare all your variables, there's strict type checking, etc. I don't know Ruby too well (it looks rather straight-forward from your example, though), but apparently it allows you the same sloppy programming that all those glorified scripting languages like Perl, PHP, etc. do. The idea of classes in those languages is nice, but it's usually just slapped on top of the existing stuff, and doesn't really add a lot. Learning a proper language is a much better idea. You can always go back to PHP et al. later. But to understand the concepts of object-oriented programming, you need a more thoroughly object-oriented language.
Edit: And to all those that will now post stuff like "Oh noes! You have to learn teh SmallTalk C++ Eiffel Occam": Java has the big advantage of being sufficiently object oriented, while still being of practical relevance and providing a lot of useful information when errors occur. Java exceptions tell you what happened, and they usually occur close to the actual error. When you go one element past an array in C and overwrite a pointer, you will get an error somewhere that has nothing at all to do with the actual problem in your program. That makes Java the perfect language for learning programming, IMHO. °<>< - Parallel Sets: Open Source Categorical Data Visualization - Visualization and Visual Communication Blog eagereyes Last edited by ghoti : 2006-04-16 at 11:59. |
quote |
Member
Join Date: Aug 2004
Location: Denver, Colorado
|
If I commented that it would be better in COBOL, I'd probably get ridiculed?
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Yes.
![]() |
quote |
Member
Join Date: Aug 2004
Location: Denver, Colorado
|
Then I won't
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Unless, of course, you posted a COBOL opera for our amusement.
Code:
IF X IS REALLY LESS THAN 5,000 THEN PLEASE ADD FOUR TO X AND STORE IN LOCATION Y;
THANK YOU. SCNR ![]() |
quote |
‽
|
Quote:
![]() |
|
quote |
Member
Join Date: Aug 2004
Location: Denver, Colorado
|
If Whatever-x-means Is Less Than 5000
Then Compute Wherever-y-is Equal Whatever-x-means + 4 On Size-error Perform Wake-up-the-programmer. |
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Quote:
|
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Quote:
|
|
quote |
‽
|
Quote:
![]() Quote:
Mistake of mine to start this thread, it would appear. Last edited by chucker : 2006-04-16 at 12:23. |
||
quote |
Member
Join Date: Aug 2004
Location: Denver, Colorado
|
Ghoti - No offense taken -- I reaped a good income from that language for many years.
![]() |
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
chucker, I posted that because you're obviously interested in learning OOP, and I thought I'd point out a fact, even if you had not asked for it. And believe me, I know a lot of programming languages (though not Ruby, admittedly), and also OOP very well, so I do feel that advice on using a language that may be better suited for a task is of value.
|
quote |
Not a tame lion...
Join Date: May 2004
Location: Narnia
|
Quote:
|
|
quote |
Senior Member
|
Quote:
|
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Alright, I should have done my homework. It seems to be a rather nice OOP language, I just don't like the weak typing. And since you can write functions outside of classes, the "everything is an object" description isn't quite true.
I still maintain that for learning OOP, Java is superior to practically any other language - I didn't say it was "better" for everything. |
quote |
Veteran Member
Join Date: Nov 2005
|
I'll back you up on this one, ghoti. At least with regard to Java being a very good OO learning environment. More than any other language I know, it really tries to nudge you into an OO way of thinking, which is the biggest hurdle you need to clear. I don't know Ruby, so won't try to comment on that. I've had loads of experience with C, C++, and Perl. Java certainly has the cleanest syntax and most elegant object model of any of those languages. The strong typing can be annoying, but is often a blessing in disguise as it will catch many programming errors at compile time. When my twelve-year old son asked me what language he should start with, I told him Java. Then he went out and bought a Python book.
![]() I do agree that "proper" probably isn't a very good term to use. As in any endeavor, you need to select the right tool for the task at hand. Perl tends to be my language of choice for day-to-day, nuts and bolts tasks where you are trying to integrate disparate pieces of software, process lots of text, and get things done quickly. I like Java for big, structured systems and web applications. I respectfully disagree with those who disparage Perl, Ruby, TCL, etc. as "scripting" languages simply because they are interpreted instead of compiled. They are all mature, robust programming environments in their own right. |
quote |
Veteran Member
Join Date: Nov 2005
|
Quote:
![]() |
|
quote |
Senior Member
|
Quote:
So actually, everything /is/ an object. (Even language Keywords!) Last edited by rollercoaster375 : 2006-04-16 at 22:08. |
|
quote |
‽
|
What he said. Writing a method outside a class creates an implicit receiver, namely 'self'.
|
quote |
owner for sale by house
Join Date: Apr 2005
Location: Charlotte, NC
|
Okay, now you lost me. You're saying that functions like handleResponse in chucker's example are part of an implicit class? Then what about the while loop at the end that's not even contained in a function? And besides, self doesn't have anything to do with that. When a function within CCConnection calls another one, it can leave out the self (and also doesn't have to pass it as a parameter, which has to be done implicitly, or the function won't know what object it belongs to), but that still means that functions within the same class are called, and not the functions of some implicit "catch-all" class.
|
quote |
Posting Rules | Navigation |
|
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Microsoft forced to (kind of) open XP source code... | Wyatt | General Discussion | 4 | 2006-01-25 11:17 |
Prettier HTML Source Code | drewprops | Programmer's Nook | 5 | 2005-12-20 00:36 |
Result Code in Toast 6.1 | pilot1129 | Genius Bar | 6 | 2005-07-21 23:29 |
Microsoft code garbage? | alexluft | Third-Party Products | 10 | 2005-04-28 10:05 |
10.3.6 Available in Software Update | Moogs | Apple Products | 86 | 2004-11-20 15:12 |