Skip to content

Commit 0901878

Browse files
committed
refactored bot into MVC structure
1 parent bca31e4 commit 0901878

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1478
-4427
lines changed

Images/chat/text/done.png

86 Bytes
Loading

bot.sikuli/bot.html

+9-1,423
Large diffs are not rendered by default.

bot.sikuli/bot.py

+10-1,424
Large diffs are not rendered by default.

code.py

+7-1,540
Large diffs are not rendered by default.

controller/ErrorHandler$py.class

4.93 KB
Binary file not shown.

controller/ErrorHandler.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class ErrorHandler(Exception):
2+
#custom Exception parent class to handle errors
3+
4+
def __init__(self, message):
5+
ERRORHANDLERAPP = settings["ERRORHANDLERAPP"]
6+
self._errormsg = message
7+
ErrorHandlerApp = App(ERRORHANDLERAPP)
8+
if not ErrorHandlerApp.window():
9+
App.open(ERRORHANDLERAPP); wait(2)
10+
ErrorHandlerApp.focus(); wait(1)
11+
self.__openRecord()
12+
self.__writeRecord()
13+
ErrorHandlerApp.close()
14+
def __openRecord(self):
15+
#this will be different depending on the application
16+
pass
17+
def __writeRecord(self):
18+
type(self._errormsg + "\n")

controller/MainController$py.class

11.2 KB
Binary file not shown.

controller/MainController.py

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
exec(open("c:/users/darkray16/desktop/my dropbox/mtgo bot/ini.py", "rb").read())
2+
3+
import sys
4+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/model")
5+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/controller")
6+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/view")
7+
import ErrorHandler
8+
import Session
9+
10+
import ITrade
11+
import ISell
12+
import IBuy
13+
import ISignIn
14+
import IClassified
15+
import IChat
16+
17+
class MainController(object):
18+
#this class will control and instanciate all the other classes
19+
#it will contain the logic and manipulate all the data
20+
#and pass data between the classes it owns
21+
22+
__single = None
23+
24+
def __init__(self):
25+
26+
self.Itrade = ITrade.ITrade()
27+
self.Isell = ISell.ISell()
28+
self.Ibuy = IBuy.IBuy()
29+
self.Isignin = ISignIn.ISignIn()
30+
self.Iclassified = IClassified.IClassified()
31+
self.Ichat = IChat.IChat()
32+
self.selling_greeting = """Entering selling mode. When you are finished taking products, please type the word \"DONE\" in all lowercase"""
33+
self.buying_greeting = """Entering buying mode. I will search your collection for products to buy. Please wait..."""
34+
35+
#make controller object a singleton class. only one instance should be run at a time
36+
if MainController.__single:
37+
raise ErrorHandler.ErrorHandler("Controller class cannot be instantiated more than once")
38+
MainController.__single = self
39+
40+
#run the controllers startup method on instanciation
41+
self.mode = settings["DEFAULTMODE"]
42+
43+
def startup(self):
44+
#log into Magic Online
45+
self.interface._define_region()
46+
if (self.Isigninlog_in()):
47+
print("logged in")
48+
#run maintanence and inventory check
49+
self.maintenance_mode()
50+
#once everything is clear and ready, start selling
51+
self.Iclassified.set_posting()
52+
if(self.mode == "default"):
53+
self.default_mode()
54+
elif(self.mode == "buy"):
55+
self.buy_mode()
56+
elif(self.mode == "maintenance"):
57+
self.maintenance_mode()
58+
else:
59+
raise ErrorHandler("Default mode not set in bot settings")
60+
61+
def trade_mode(self, mode=None):
62+
"""if you wish to set the bot to only sell or buy, then set param mode to
63+
"sell" or "buy" to force the bot mode"""
64+
65+
#puts the bot into sell mode, will wait for trade request
66+
if(self.Itrade.start_wait("incoming_request")):
67+
#minimize the chat window to the side
68+
if(self.Itrade.accept_trade()):
69+
self.Ichat.minimize_chat_window()
70+
71+
## DEBUG: onChange method is not working correctly, ##
72+
#signals that the customer is taking something and the transaction will be a sale
73+
#wait(2)
74+
#self.Itrade.giving_window_region.onChange(self.set_mode("sell"))
75+
if not mode:
76+
mode="buy"
77+
78+
self.set_mode(mode=mode)
79+
#open a session to record data to
80+
session = Session.Session()
81+
82+
83+
#enter selling mode
84+
if self.get_mode() == "sell":
85+
self.Ichat.type_msg(self.selling_greeting)
86+
self.Isell.set_windows()
87+
products_sold = self.Isell.complete_sale()
88+
89+
receipt = None
90+
if products_sold:
91+
receipt = {"sold":{}, "bought":{}}
92+
for product in products_sold:
93+
receipt["sold"][product["name"]] = product["quantity"]
94+
95+
#enter buying mode
96+
elif self.get_mode() == "buy":
97+
self.Ichat.type_msg(self.buying_greeting)
98+
self.Ibuy.set_windows()
99+
#take packs from the customer
100+
products_bought = self.Ibuy.complete_purchase()
101+
102+
receipt = None
103+
if products_bought:
104+
receipt = {"sold":{}, "bought":{}}
105+
for product in products_bought:
106+
receipt["bought"][product["name"]] = product["quantity"]
107+
108+
109+
if receipt is not None:
110+
session.set_transaction(receipt)
111+
session.set_time(datetime.now())
112+
session.record()
113+
del(session)
114+
else:
115+
#record trade failure
116+
pass
117+
118+
#check if bot is part of a bot network before trying to transfer items
119+
if(self.settings["NETWORK"]):
120+
121+
self.transfer_mode()
122+
123+
self.trade_mode()
124+
125+
def transfer_mode(self):
126+
#puts the bot into transfer mode, will check inventory and transfer items to other bots
127+
#check if bot is part of network
128+
if(BotSetting.getSetting("NETWORK")):
129+
pass
130+
131+
def maintenance_mode(self):
132+
#puts the bot maintanence mode to check inventory
133+
pass
134+
135+
def set_mode(self, mode):
136+
#set the bot mode to sell or buy
137+
self.status = mode
138+
139+
def get_mode(self):
140+
#get the current mode
141+
if self.status:
142+
return self.status
143+
else:
144+
raise ErrorHandler("Current Mode Uknown")

controller/__init__$py.class

2.23 KB
Binary file not shown.

controller/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from MainController import *
2+
from ErrorHandler import *

ini$py.class

4.12 KB
Binary file not shown.

ini.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from sikuli.Sikuli import *
2+
3+
#this object will hold all global settings for the application
4+
settings = {"ERRORHANDLERAPP":"Notepad", "LOGIN_WAIT":45, "PASSWORD":"nancy214", "BOTUSERNAME":"rcdark16", "BOTPASSWORD":"Esther", "FORCEMODE":"", "NETWORK":False, "DEFAULTMODE":"sell"}
5+
6+
#default is 1
7+
Settings.MoveMouseDelay = 0.2
8+
#default is False, don't show visual guide to actions
9+
setShowActions(False)
10+
#default is 2.0(2 seconds delay on show actions)
11+
Settings.SlowMotionDelay = 1.5
12+
#set this lower if cpu usage is too high
13+
Settings.WaitScanRate = 6
14+
#must be 0.8 to 1, in order to maintain accuracy, MAY NOT affect pixel matching operations besides find()
15+
Settings.MinSimilarity = 0.9
16+
#min pixel change to trigger onChange
17+
Settings.ObserveMinChangedPixels = 200
18+
#all find operations which don't use other regions should use this one

model/CardPricesDAL$py.class

1.09 KB
Binary file not shown.

model/CardPricesDAL.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
1+
import sys
2+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/model")
3+
import ProductPriceModel
14

25
class CardPricesDAL(object):
36
#DAL layer for pricelist for buying and selling single cards
4-
57
def __init__(self):
6-
price_model = ProductPriceModel()
7-
self.pack_buy = price_model.get_prices("cards_buy")
8-
self.pack_sell = price_model.get_prices("cards_sell")
8+
price_model = ProductPriceModel.ProductPriceModel()
9+
self.buy = price_model.get_prices("cards_buy")
10+
self.sell = price_model.get_prices("cards_sell")
11+
12+
#set prices is to be done in gui bot settings prior to transaction
13+
def set_buy_price(self, name, price):
14+
self.buy[name.upper()] = price
15+
def set_sell_price(self, name, price):
16+
self.sell[name.upper()] = price
17+
18+
def get_buy_price(self, name):
19+
return self.buy[name.upper()]
20+
def get_sell_price(self, name):
21+
return self.sell[name.upper()]

model/CardsList$py.class

4.4 KB
Binary file not shown.

model/CardsList.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import sys
2+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/model")
3+
from List import *
4+
5+
class CardsList(List):
6+
# is list of cards wanted and cards for sale
7+
def __init__(self):
8+
super(CardsList, self).__init__()
9+
10+
def add_card_to_have(self, cardname, amount):
11+
self._have[cardname] = amount

model/DataStorage$py.class

6.39 KB
Binary file not shown.

model/DataStorage.py

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import sikuli.Sikuli
2+
3+
class DataStorage(object):
4+
#object that will handle exporting transaction history
5+
#you must have the program that you want to send the transaction to, open
6+
#methods of storage being considered, xml, excel, mysql
7+
8+
def __init__(self, program):
9+
""" program parameter is the format to write the file in, e.g. Notepad, or Excel"""
10+
self._program = program
11+
12+
def write(self, transaction):
13+
record_app = App("Notepad")
14+
if not record_app.window():
15+
App.open("Notepad"); wait(1)
16+
record_app.focus()
17+
type(self.convert_trans_to_string(transaction))
18+
wait(0.5)
19+
App.focus("Magic Online")
20+
21+
def convert_trans_to_string(self, transaction):
22+
"""takes the transaction variable created in Session class and converts it to string"""
23+
#note, repr will not work because it doesn't remove curly brackets and colons
24+
record_list = []
25+
for mode, trans in transaction.iteritems():
26+
record_list.append(str("mode: " + mode + " "))
27+
for product,quantity in trans.iteritems():
28+
record_list.append(str(product + ":"))
29+
record_list.append(str(quantity) + " ")
30+
31+
record_string = "".join(record_list) + "\n"
32+
return record_string

model/ImagesModel$py.class

12 Bytes
Binary file not shown.

model/List$py.class

3.9 KB
Binary file not shown.

model/List.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class List(object):
2+
#parent class for cards and packs wanted classes
3+
def __init__(self):
4+
#change to private variables later
5+
self._wanted = {}
6+
self._have = {}
7+
8+
def get_wanted(self):
9+
return self._wanted
10+
def get_have(self):
11+
return self._have

model/PackPricesDAL$py.class

-132 Bytes
Binary file not shown.

model/PackPricesDAL.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import sys
2+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/model")
3+
import ProductPriceModel
4+
15

26
class PackPricesDAL(object):
37
#DAL layer for pricelist for buying and selling packs
48
def __init__(self):
5-
price_model = ProductPriceModel()
9+
price_model = ProductPriceModel.ProductPriceModel()
610
self.buy = price_model.get_prices("packs_buy")
711
self.sell = price_model.get_prices("packs_sell")
812

model/PacksList$py.class

5.09 KB
Binary file not shown.

model/PacksList.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import sys
2+
sys.path.append("c:/users/darkray16/desktop/my dropbox/mtgo bot/model")
3+
from List import *
4+
5+
class PacksList(List):
6+
def __init__(self):
7+
super(PacksList, self).__init__()
8+
buylist = ["SOM", "ZEN", "WWK", "ME4", "M11", "ROE"]
9+
10+
def get_buy_list(self):
11+
#returns a prioritized list of packs wanted, starting with most wanted
12+
return self._buy_list
13+
14+
def add_pack_to_have(self, packname, amount):
15+
self._have[packname] = amount

model/Product$py.class

4 KB
Binary file not shown.

model/Product.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Product(object):
2+
#an object which holds all the information for a single product in a trade
3+
def __init__(self, name, quantity, buy, sell):
4+
self.__stats = {"quantity": quantity, "buy":buy, "sell":sell, "name":name}
5+
6+
def __getitem__(self, index):
7+
return self.__stats[index]

model/ProductPriceModel$py.class

437 Bytes
Binary file not shown.

model/ProductPriceModel.py

+23-13
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
1-
#handles reading and writing to files
1+
#handles reading and writing to pricelist files
22

33
from sys import *
44

55
class ProductPriceModel(object):
66

77
def __init__(self):
88

9-
self.pricelist = {}
9+
self.pricelist_files = {}
1010
try:
11-
self.pricelist["packs_buy"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/packs/buy.txt", "r")
11+
self.pricelist_files["packs_buy"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/packs/buy.txt", "r")
1212
except IOError:
13-
sys.exit("Pack buy price file not found at pricelist/packs/buy/")
13+
print("Pack buy price file not found at pricelist/packs/buy/")
1414
try:
15-
self.pricelist["packs_sell"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/packs/sell.txt", "r")
15+
self.pricelist_files["packs_sell"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/packs/sell.txt", "r")
1616
except IOError:
17-
sys.exit("Pack sell price file not found at pricelist/packs/sell/")
17+
print("Pack sell price file not found at pricelist/packs/sell/")
1818
try:
19-
self.pricelist["cards_buy"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/cards/buy.txt", "r")
19+
self.pricelist_files["cards_buy"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/cards/buy.txt", "r")
2020
except IOError:
21-
sys.exit("Card buy price file not found at pricelist/packs/buy/")
21+
print("Card buy price file not found at pricelist/cards/buy/")
2222
try:
23-
self.pricelist["cards_sell"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/cards/sell.txt", "r")
23+
self.pricelist_files["cards_sell"] = open("c:/users/darkray16/desktop/my dropbox/mtgo bot/pricelist/cards/sell.txt", "r")
2424
except IOError:
25-
sys.exit("Card sell price file not found at pricelist/packs/buy/")
25+
print("Card sell price file not found at pricelist/cards/buy/")
2626

2727
def get_prices(self, pricelist):
2828
"""valid strings for pricelist = "packs_buy", "packs_sell", "cards_buy", "cards_sell" """
2929
#this will return a dictionary containg all the buy or sell prices for requested products
3030

3131
pricelist_dict = {}
3232

33-
raw_feed = self.pricelist[pricelist]
33+
raw_feed = self.pricelist_files[pricelist]
3434

3535
while True:
3636
newline = raw_feed.readline()
@@ -41,7 +41,17 @@ def get_prices(self, pricelist):
4141
int(single_product[1])
4242
except ValueError:
4343
sys.exit("A non-number found as a price for " + single_product[0] + " in in response to a " + pricelist + " request")
44-
45-
pricelist_dict[single_product[0]] = int(single_product[1])
44+
product_name = str(single_product[0])
45+
46+
#if there is no price next to the name of the product, then
47+
try:
48+
product_price = int(single_product[1])
49+
except IndexError:
50+
pass
51+
except ValueError:
52+
pass
53+
else:
54+
pricelist_dict[product_name.upper()] = product_price
4655

56+
pricelist_dict["Rack"] = 15
4757
return pricelist_dict

model/Session$py.class

6.07 KB
Binary file not shown.

0 commit comments

Comments
 (0)