Changeset - 782476e472ab
[Not reviewed]
default
0 5 0
Laman - 7 years ago 2017-12-01 19:51:08

configurable image directory, refactored constants
5 files changed with 20 insertions and 15 deletions:
0 comments (0 inline, 0 general)
src/config.py
Show inline comments
 
import os
 
import logging
 
import json
 

	
 

	
 
srcDir=os.path.dirname(__file__)
 

	
 
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.DEBUG)
 
with open(os.path.join(os.path.dirname(__file__), "..", "config.json")) as f:
 
with open(os.path.join(srcDir, "..", "config.json")) as f:
 
	cfgFile=json.load(f)
 

	
 
class misc:
 
	file=cfgFile["misc"]
 
	version=(0,0,0)
 
	defaultImage=file.get("defaultImage", 0)
 

	
 
	_imgDir=file.get("imgDir","../images")
 
	imgDir=_imgDir if os.path.isabs(_imgDir) else os.path.join(srcDir,_imgDir)
 

	
 
class gui:
 
	file=cfgFile["gui"]
 
	showBigPoints=file.get("showBigPoints", False)
 
	showGrid=file.get("showGrid", True)
src/core.py
Show inline comments
 
import os
 
import multiprocessing
 
import threading
 
import logging as log
 
import PIL
 
from util import MsgQueue
 
from gui import gui
 
from imageanalyzer import ImageAnalyzer
 
from go import Go, isLegalPosition
 
from statebag import StateBag
 
import config as cfg
 

	
 

	
 
class Core:
 
	def __init__(self):
 
		self.grid=None
 
		self.go=Go()
 
		self.detector=ImageAnalyzer()
 
		self.states=StateBag()
 

	
 
		self._ownMessages=MsgQueue(self._handleEvent)
 
		self._guiMessages=MsgQueue()
 

	
 
		self._imgDir=os.path.join(os.path.dirname(__file__), "..","images")
 
		self._imgs=sorted(os.listdir(self._imgDir))
 
		self._imgs=sorted(os.listdir(cfg.misc.imgDir))
 
		self._imgIndex=cfg.misc.defaultImage
 
		imgPath=os.path.join(self._imgDir,self._imgs[self._imgIndex])
 
		imgPath=os.path.join(cfg.misc.imgDir,self._imgs[self._imgIndex])
 
		self._frame=PIL.Image.open(imgPath)
 

	
 
		self._guiProc=multiprocessing.Process(name="gui", target=gui, args=(self._guiMessages,self._ownMessages))
 
		self._guiProc.start()
 
		self.relativeFrame(0)
 

	
 
	def setCorners(self,corners):
 
		self.detector.setGridCorners(corners)
 
		self.analyze()
 

	
 
	def setTresholds(self,tresB=None,tresW=None):
 
		if tresB is not None: self.detector.tresB=tresB
 
		if tresW is not None: self.detector.tresW=tresW
 
		self.analyze()
 

	
 
	def relativeFrame(self,step):
 
		self._imgIndex=(self._imgIndex+step)%len(self._imgs)
 
		imgPath=os.path.join(self._imgDir,self._imgs[self._imgIndex])
 
		imgPath=os.path.join(cfg.misc.imgDir,self._imgs[self._imgIndex])
 
		self._frame=PIL.Image.open(imgPath)
 
		self._guiMessages.send("setCurrentFrame",(self._frame.copy(),))
 
		self.analyze()
 

	
 
	def analyze(self):
 
		if self.detector.analyze(self._frame):
 
			if isLegalPosition(self.detector.board):
 
				self.states.pushState(self.detector.board)
 
				self._guiMessages.send("setGameState",(self.detector.board,))
 

	
 
				self.go.transitionMove(self.detector.board)
 
				log.debug("game record: %s",self.go._record)
 
			else:
 
				log.info("illegal position detected")
 

	
 
	def listen(self):
 
		listenerThread=threading.Thread(target=lambda: self._ownMessages.listen())
 
		listenerThread.start()
 

	
 
	def joinGui(self):
 
		self._guiProc.join()
 
		self._ownMessages.send("!kill")
 

	
 
	def _handleEvent(self,e):
 
		actions={
 
			"setCorners": self.setCorners,
 
			"setTresholds": self.setTresholds,
 
			"prevFrame": lambda: self.relativeFrame(-1),
 
			"nextFrame": lambda: self.relativeFrame(1)
 
		}
 
		(actionName,args,kwargs)=e
 

	
 
		return actions[actionName](*args,**kwargs)
 

	
 
core=Core()
 
core.listen()
src/gamerecord.py
Show inline comments
 
import logging as log
 

	
 

	
 
colorNames={1:"B",-1:"W"}
 
from util import colorNames
 

	
 

	
 
class Point:
 
	def __init__(self,c,r):
 
		self.r=r
 
		self.c=c
 

	
 
	def __iter__(self):
 
		yield self.c
 
		yield self.r
 

	
 
	def __str__(self):
 
		a=ord("a")
 
		return chr(a+self.c)+chr(a+self.r)
 

	
 

	
 
class GameRecord:
 
	def __init__(self):
 
		self.playerB=""
 
		self.playerW=""
 
		self.root=Node()
 
		self.currNode=self.root
 

	
 
	def move(self,color,row,col):
src/go.py
Show inline comments
 
import logging as log
 

	
 
from util import EMPTY,BLACK,WHITE,colorNames
 
from gamerecord import GameRecord
 

	
 

	
 
EMPTY=0
 
BLACK=1
 
WHITE=-1
 

	
 

	
 
class Go:
 
	## Initializes self.board to a list[r][c]=EMPTY.
 
	def __init__(self,boardSize=19):
 
		self.boardSize=boardSize
 
		self.board=[[EMPTY]*boardSize for x in range(boardSize)]
 
		self._temp=[[EMPTY]*boardSize for x in range(boardSize)]
 
		self.toMove=BLACK
 
		self._record=GameRecord()
 

	
 
	## Executes a move.
 
	#
 
	#  Doesn't check for kos. Suicide not allowed.
 
	#
 
	#  @param color BLACK or WHITE
 
	#  @return True on success, False on failure (illegal move)
 
	def move(self,color,row,col):
 
		if color!=self.toMove: log.warning("move by %s out of order",color)
 
		if color!=self.toMove: log.warning("move by %s out of order",colorNames[color])
 
		if self.board[row][col]!=EMPTY: return False
 

	
 
		self.board[row][col]=color
 

	
 
		# capture neighbors
 
		for r,c in ((-1,0),(1,0),(0,-1),(0,1)):
 
			self._clearTemp()
 
			if not self._floodFill(-color,row+r,col+c): self._remove()
 

	
 
		# check for suicide
 
		self._clearTemp()
 
		if not self._floodFill(color,row,col):
 
			self.board[row][col]=EMPTY
 
			return False
 
		self._record.move(color,row,col)
 
		self.toMove=-1*color
 
		return True
 

	
 
	def transitionMove(self,board):
 
		res=transitionMove(self.board,board)
 
		if not res: return res
 
		(r,c,color)=res
 
		return self.move(color,r,c)
 

	
src/util.py
Show inline comments
 
import multiprocessing
 
import logging as log
 

	
 

	
 
EMPTY=0
 
BLACK=1
 
WHITE=-1
 

	
 
colorNames={BLACK:"B",WHITE:"W"}
 

	
 

	
 
class MsgQueue:
 
	def __init__(self,handler=None):
 
		self._queue=multiprocessing.Queue()
 
		self._event=multiprocessing.Event()
 
		self._handleEvent=handler
 

	
 
	def send(self,actionName,args=tuple(),kwargs=None):
 
		if kwargs is None: kwargs=dict()
 
		self._queue.put((actionName,args,kwargs))
 
		self._event.set()
 

	
 
	def listen(self,handleEvent=None):
 
		if handleEvent is not None: self._handleEvent=handleEvent
 

	
 
		while True:
 
			self._event.wait()
 
			msg=self._queue.get()
 
			if self._queue.empty():
 
				self._event.clear()
 
			log.info(msg)
 
			if msg[0]=="!kill": break
 
			self._handleEvent(msg)
 

	
 
	def setHandler(self,handler):
0 comments (0 inline, 0 general)