DrawThink/main.py

299 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import socket,threading,sys,random,multiprocessing,time
import draw,pygame
import requests,json # Get problem
MAX = 1024
class Server:
roomList = []
def __init__(self,ip,port):
self.ip = ip
self.port = port
def start(self):
# Base server
# Set the room for mainClient and redirect client into the room
print("Set server on {}:{}".format(self.ip,self.port))
listensock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
listensock.bind((self.ip,self.port))
listensock.listen(5)
while True:
sock,sockname = listensock.accept()
print("{} has connected.".format(sockname))
setTypeThread = threading.Thread(target = self.selectType,args=(sock,),daemon=True) # Create a thread for communicating with client.
setTypeThread.start()
def selectType(self,sock):
data = sock.recv(MAX).decode('utf-8')
#print(data)
if data == "MAIN":
sock.send("OK.SERVER".encode('utf-8'))
self.main(sock) # Set main client mode
elif data == "CLIENT":
sock.send("OK.CLIENT".encode('utf-8'))
self.client(sock) # Set client mode
else:
sock.send("FAIL".encode('utf-8')) # Error type
def main(self,sock):
portNum = random.randint(1025,65535) #決定port
roomNum = chr(random.randint(65,90)) + chr(random.randint(65,90)) # 隨機房號給client方便導向不需要ip:port
flag = 1
# 防止房號相同,若重複必須重新設定
while flag:
portNum = random.randint(1025,65535) #決定port
roomNum = chr(random.randint(65,90)) + chr(random.randint(65,90))
flag = 0
for i in self.roomList:
if i['portNum'] == portNum or i['roomNum'] == roomNum:
flag =1
room = Room(self.ip,portNum)
# Room process, process the game.
# Should handle all client which are redirected to this room.
roomProcess = multiprocessing.Process(target=room.start)
roomProcess.start()
# Set a list which save all rooms' info
self.roomList.append(
{
'portNum' : portNum,
'roomNum' : roomNum,
}
)
print(self.roomList)
# Let main client know the roomNumber.So it can connect to this room and share it's roomNumber to his/her friends.
sock.send("{} {}".format(roomNum,portNum).encode('utf-8'))
def client(self,sock):
# Get roomNumber which client want to join.
receiveMsg = sock.recv(MAX).decode('utf-8')
flag = False
for i in self.roomList:
# Find PORT NUMBER to let clients' socket can connect to.
if i['roomNum'] == receiveMsg:
# send PORT NUMBER to let client can connecte
sock.send(str(i['portNum']).encode('utf-8'))
flag = True
if not flag:
# NO THIS NUMBER
sock.send("FAIL".encode('utf-8'))
class Room:
startFlag = True
sockList = [] # Client's sock list
def __init__(self,ip,portNum):
self.ip = ip
self.portNum = portNum
self.problem = self.getProblem()
#print(self.problem)
def start(self):
# Build a room's socket to start game
self.allPeerName = []
listensock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
listensock.bind((self.ip,self.portNum))
print("\t{}:{}".format(self.ip,self.portNum))
listensock.listen(5)
emptyFlag = True
while self.startFlag:
sock,sockname = listensock.accept()
print("[ {} ]{} has connected.".format(self.portNum,sockname))
self.sockList.append(sock) # 把sock放入list
# Send socket list to client to build a user list and put it beside picture.
self.allPeerName.append({'name':sock.getpeername(),'score':0})
for sock in self.sockList:
sock.send("[list] {}".format(json.dumps(self.allPeerName)).encode('utf-8'))
receiveDataThread = threading.Thread(target=self.receiveData,args=(sock,),daemon=True)
# 負責與client通信傳輸遊戲所必須的指令
receiveDataThread.start()
if emptyFlag:
self.game()
emptyFlag = False
def game(self):
mainSocket = random.choice(self.sockList)
self.problem = self.getProblem()
time.sleep(2)
#print("GAME SEND PROBLEM")
for clientSock in self.sockList:
if clientSock == mainSocket:
clientSock.send('[prob] {}'.format(self.problem).encode('utf-8'))
else:
clientSock.send('[gues]'.encode('utf-8'))
for sock in self.sockList:
sock.send("[list] {}".format(json.dumps(self.allPeerName)).encode('utf-8'))
def connect(self):
time.sleep(0.5)
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((self.ip,self.portNum))
return sock
def getProblem(self):
jsonResponse = requests.get('https://ncnu-hungrycat.com/pyGartic.php')
jsonData = json.loads(jsonResponse.text)
return jsonData['problem']
def receiveData(self,sock):
# room's socket receive MAINCLIENT'S mouse position.
# And send this MOUSE position to other client.
# Let them can draw the same picture on the screen
while True:
origin = sock.recv(MAX)
data = origin.decode('utf-8')
if data:
#print(data)
if data[0]=='(': # Form MAIN CLIENT,it is position data
for clientSock in self.sockList: # 遍歷socket list
if clientSock != sock: # 不是自己的才傳送資料.Needn't send position to MAIN
clientSock.send(origin)
elif data=='[restart]': # [restart]
#print('game restart')
time.sleep(1)
for clientSock in self.sockList:
clientSock.send('restart'.encode('utf-8'))
self.game() #restart
else: # it is from other client. He/she want to send answer to check the answer
if data == self.problem:
sock.send('y'.encode('utf-8'))
for peer in self.allPeerName:
if sock.getpeername() == peer['name']:
peer['score'] = peer['score']+1
elif data == 'exit':
sock.send('exitok'.encode('utf-8'))
self.sockList.remove(sock)
for peer in self.allPeerName:
if sock.getpeername() == peer['name']:
self.allPeerName.remove(peer)
if len(self.sockList) == 0 :
self.startFlag = False
for clientSock in self.sockList:
clientSock.send("[list] {}".format(json.dumps(self.allPeerName)).encode('utf-8'))
break
else:
sock.send('n'.encode('utf-8'))
for clientSock in self.sockList:
clientSock.send("[list] {}".format(json.dumps(self.allPeerName)).encode('utf-8'))
class Client:
def __init__(self,ip,port):
self.ip = ip
self.port = port
def start(self):
# START to choose MAIN OR CLIENT.
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((self.ip,self.port))
self.setType(sock)
sock.close()
def setType(self,sock):
print("Type in 'MAIN' to set a new room\nType in 'CLIENT' to join a room")
msg = input("> ")
sock.send(msg.encode('utf-8'))
receiveMsg = sock.recv(MAX).decode('utf-8') # Get response
if receiveMsg=="OK.SERVER":
receiveMsg = sock.recv(MAX).decode('utf-8')
print(receiveMsg)
# get ROOMNUM and PORTNUM
connectData = receiveMsg.split(' ')
room = Room(self.ip,int(connectData[1]))
sock.close()
sock = room.connect() # sock可覆蓋了
# receiveDataThread = threading.Thread(target=self.receiveData,args=(sock,))
# receiveDataThread.start()
# sendDataThread = threading.Thread(target=self.sendData,args=(sock,))
# sendDataThread.start()
elif receiveMsg=="OK.CLIENT":
roomNum = input("Room Number> ")
sock.send(roomNum.encode('utf-8'))
receiveMsg = sock.recv(MAX).decode('utf-8')
# Get port number
room = Room(self.ip,int(receiveMsg))
sock.close()
sock = room.connect() # sock可覆蓋了
# receiveDataThread = threading.Thread(target=self.receiveData,args=(sock,))
# receiveDataThread.start()
# sendDataThread = threading.Thread(target=self.sendData,args=(sock,))
# sendDataThread.start()
else:
print("ERROR TYPE")
exit
userList = sock.recv(1024).decode('utf-8')
#print("List: ",userList)
## SET PYGAME
pygame.init()
pygame.display.set_caption('Draw Think')
size= [1080, 480]
screen= pygame.display.set_mode(size)
continueFlag = False
while not continueFlag:
screen.fill((255, 255, 255))
pgStringVar = pygame.font.Font(None,40).render("Please wait...",False,(0,0,0))# 文字物件
screen.blit(pgStringVar,(500,240))# draw font
pygame.display.update()
#print("START RECEIVE.")
data = sock.recv(1024).decode('utf-8')
role = data[1:5]
#print("Role: ",role)
if role == "prob":
problem = data.split(' ')[1]
continueFlag = draw.sendDraw(sock,userList,screen,problem)
elif role == "gues":
continueFlag = draw.receiveDraw(sock,screen,userList)
elif role == "list":
userList = data
#print("List: ",userList)
continueFlag = False
else: #useless position
continueFlag = False
pygame.quit()
# def receiveData(self,sock):
# while True:
# data = sock.recv(MAX).decode('utf-8')
# if data:
# print(data)
# def sendData(self,sock):
# while True:
# data = input("> ")
# sock.send(data.encode('utf-8'))
def main():
ip = sys.argv[2]
port = sys.argv[3]
port = int(port)
print(ip,port)
if(sys.argv[1]=='server'):
server = Server(ip,port)
server.start()
elif(sys.argv[1]=='client'):
client = Client(ip,port)
client.start()
else:
print("Usage: python main.py {server,client} ip port")
main()