How to do OOP and MVC properly - oop

This afternoon I wrote this but it feels dirty to me. Since I'm learning OOP and MVC, I would like to know if there is a proper way to change nested object's attributes.
For example what is the cleanest way to modify an attribute from an object contained in an object, etc ?
The whole code is here https://github.com/Meezouney/Chess_tournament
If you have any advise, I'll take it :)
Thanks
def enter_match_results(self, nth_round, nth_match):
n_round = self.tournament.get_list_of_rounds()[nth_round]
game = n_round.get_list_of_match()[nth_match]
players = game.get_players()
for i, player in enumerate(players):
if i == 0:
valid_input = 0
while not valid_input:
score = self.view.ask_results(player)
if score == "0" or score == "0,5" or score == "0.5" or score == "1":
if ',' in score:
score = score.replace(',', '.')
valid_input = 1
self.tournament.get_list_of_rounds()[nth_round].get_list_of_match()[nth_match].set_score_player_1(float(score))
else:
self.view.display_score_error()
elif i == 1:
valid_input = 0
while not valid_input:
score = self.view.ask_results(player)
if score == "0" or score == "0,5" or score == "0.5" or score == "1":
if ',' in score:
score = score.replace(',', '.')
valid_input = 1
self.tournament.get_list_of_rounds()[nth_round].get_list_of_match()[nth_match].set_score_player_2(float(score))
else:
self.view.display_score_error()
I am trying to figure out the philosophy of OOP by practicing.

Related

Pandas .loc[] method is too slow, how can I speed it up

I have a dataframe with 40 million rows,and I want to change some colums by
age = data[data['device_name'] == 12]['age'].apply(lambda x : x if x != -1 else max_age)
data.loc[data['device_name'] == 12,'age'] = age
but this method is too slow, how can I speed it up.
Thanks for all reply!
you might wanna change the first part to :
age = data[data['device_name'] == 12]['age']
age[age == -1] = max_age
data.loc[data['device_name'] == 12,'age'] = age
you could use, to me more concise(this could gain you a little speed)
cond = data['device_name'] == 12
age = data.loc[cond, age]
data.loc[cond,'age'] = age.where(age != -1, max_age)

What is wrong with my while loop (Python)?

I am quite new to programming and I face a strange issue with the below while-loop in Python. When I manually run the code below the loop (i.e. starting with "time now..." to "t += 1"), I get the output I want:
The time is now: 13:31:01
Your current position is -1
This is iteration: 1
The time is now: 13:32:01
Your current position is -1
This is iteration: 2
However, when I run the full loop, I get double, triple or multiple prints of the same minute (see output below the while-loop code).
Do you see the issue with this loop? Its as if the "t += 1" increment is running several times per loop (i.e. for each minute several prints). I dont get it.
Thanks for your help!
Blockquote
t=1
while t < 2000:
time_now = (time.strftime('%H:%M:%S', time.localtime(int(time.time()))))
if time_now[6:8] == str('00'):
sleep(1)
elif time_now[6:8] == str('01'):
sleep(0)
else:
x = 61 - int(time_now[6:8])
sleep(x)
time_now = (time.strftime('%H:%M:%S', time.localtime(int(time.time()))))
print("The time is now: " + time_now)
#+1 is the middle bar
totalBars = leftBars + rightBars + 1
swing_candles = client.Trade.Trade_getBucketed(symbol=symbol, binSize="1m", count=totalBars, reverse=True).result()[0]
last_highs = []
last_lows = []
i=0
while i <= (len(swing_candles)-1):
last_highs.append(swing_candles[i]["high"])
last_lows.append(swing_candles[i]["low"])
i += 1
#get the highest high and the lowest low
highest_high = max(last_highs)
lowest_low = min(last_lows)
#check if there are existing positions & orders
positions_quantity = client.Position.Position_get().result()[0][0]["currentQty"]
#check existing orders
buy_orders_quantity = []
sell_orders_quantity = []
orders_quantity = client.Order.Order_getOrders(filter=json.dumps({"open": True})).result()[0]
h=0
while h <= len(orders_quantity)-1:
if orders_quantity[h]["side"] == "Sell":
sell_orders_quantity.append(orders_quantity[h])
elif orders_quantity[h]["side"] == "Buy":
buy_orders_quantity.append(orders_quantity[h])
h += 1
if highest_high == last_highs[rightBars] and positions_quantity == 0:
if buy_orders_quantity == []:
client.Order.Order_new(symbol = symbol, orderQty = orderQty*1, side = "Buy", ordType = 'Stop', stopPx = highest_high, execInst ='LastPrice' ).result()
elif buy_orders_quantity != []:
orderID = buy_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*1, stopPx = highest_high).result()
else:
pass
elif highest_high == last_highs[rightBars] and positions_quantity > 0:
#dont place any additional long
pass
elif highest_high == last_highs[rightBars] and positions_quantity < 0:
if buy_orders_quantity != []:
orderID = buy_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*2, stopPx = highest_high).result()
else:
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*2, side = "Buy", ordType = 'Stop', stopPx = highest_high, execInst ='LastPrice' ).result()
elif lowest_low == last_lows[rightBars] and positions_quantity == 0:
if sell_orders_quantity == []:
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*-1, side = "Sell", ordType = 'Stop', stopPx = lowest_low, execInst ='LastPrice' ).result()
elif sell_orders_quantity != []:
orderID = sell_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*-1, stopPx = lowest_low ).result()
else:
pass
elif lowest_low == last_lows[rightBars] and positions_quantity < 0:
#dont place any additional shorts
pass
elif lowest_low == last_lows[rightBars] and positions_quantity > 0:
if sell_orders_quantity != []:
orderID = sell_orders_quantity[0]["orderID"]
client.Order.Order_amend(orderID=orderID, orderQty=orderQty*-2, stopPx = lowest_low).result()
else:
#if there is no order, place new order with double amount
client.Order.Order_new(symbol = symbol, orderQty = (orderQty)*-2, side = "Sell", ordType = 'Stop', stopPx = lowest_low, execInst ='LastPrice' ).result()
positions_quantity = client.Position.Position_get().result()[0][0]["currentQty"]
print("Your current position is " + str(positions_quantity))
print("This is iteration: " + str(t))
t += 1
This is the output when I run the while-loop above (however each minute there should be just one print, but starting with iteration two there are several prints for the same minute (loop)):
The time is now: 13:39:01
Your current position is -1
This is iteration: 1
The time is now: 13:39:01
Your current position is -1
This is iteration: 2
The time is now: 13:40:01
Your current position is -1
This is iteration: 3
The time is now: 13:40:01
Your current position is -1
This is iteration: 4
The time is now: 13:40:01
Your current position is -1
This is iteration: 5
The time is now: 13:40:01
Your current position is -1
This is iteration: 6
The time is now: 13:40:01
Your current position is -1
This is iteration: 7
The time is now: 13:41:01
Your current position is -1
This is iteration: 8
The time is now: 13:41:01
Your current position is -1
This is iteration: 9
The time is now: 13:41:01
Your current position is -1
This is iteration: 10
The time is now: 13:41:01
Your current position is -1
This is iteration: 11
The time is now: 13:41:01
Your current position is -1
This is iteration: 12
Assuming that "running the full loop" (scenario A) is faster than when you "manually runtime code" (scenario B), what appears to be happening is that, when the # of seconds in time_now is "01", the scenario A is fast enough to complete a few iterations with the # of seconds in time_now staying at "01", while scenario B is not.
If you slept for at least 1 second when the # of seconds in time_now was "01", that should prevent this, as it would change the # of seconds in time_now.

Binary Search Template Leetcode, The meaning of it?

I Found a Binary Search Template here in leetcode
def binarySearch(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if len(nums) == 0:
return -1
left, right = 0, len(nums)
while left < right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid
# Post-processing:
# End Condition: left == right
if left != len(nums) and nums[left] == target:
return left
return -1
They say that "Template #2 is an advanced form of Binary Search. It is used to search for an element or condition which requires accessing the current index and its immediate right neighbor's index in the array."
I am struggling to understand what the information above means. In a usual binary search right would be
right = len(nums) - 1 # before while loop
right = mid - 1 # inside while loop
and the while loop would be
while left <= right:
You are performing a binary search on an array.
Lets say the array has 100 elements.
# left, right = 0, len(nums)
left = 0, right = 99
# mid = (left + right) // 2
mid = 49
# elif nums[mid] < target:
We need to move right.
# left = mid + 1
left = 50 and right = 99
# else:
We need to move left.
# right = mid
Left = 0, right = 49

How to declare constraints with variable as array index in Z3Py?

Suppose x,y,z are int variables and A is a matrix, I want to express a constraint like:
z == A[x][y]
However this leads to an error:
TypeError: object cannot be interpreted as an index
What would be the correct way to do this?
=======================
A specific example:
I want to select 2 items with the best combination score,
where the score is given by the value of each item and a bonus on the selection pair.
For example,
for 3 items: a, b, c with related value [1,2,1], and the bonus on pairs (a,b) = 2, (a,c)=5, (b,c) = 3, the best selection is (a,c), because it has the highest score: 1 + 1 + 5 = 7.
My question is how to represent the constraint of selection bonus.
Suppose CHOICE[0] and CHOICE[1] are the selection variables and B is the bonus variable.
The ideal constraint should be:
B = bonus[CHOICE[0]][CHOICE[1]]
but it results in TypeError: object cannot be interpreted as an index
I know another way is to use a nested for to instantiate first the CHOICE, then represent B, but this is really inefficient for large quantity of data.
Could any expert suggest me a better solution please?
If someone wants to play a toy example, here's the code:
from z3 import *
items = [0,1,2]
value = [1,2,1]
bonus = [[1,2,5],
[2,1,3],
[5,3,1]]
choices = [0,1]
# selection score
SCORE = [ Int('SCORE_%s' % i) for i in choices ]
# bonus
B = Int('B')
# final score
metric = Int('metric')
# selection variable
CHOICE = [ Int('CHOICE_%s' % i) for i in choices ]
# variable domain
domain_choice = [ And(0 <= CHOICE[i], CHOICE[i] < len(items)) for i in choices ]
# selection implication
constraint_sel = []
for c in choices:
for i in items:
constraint_sel += [Implies(CHOICE[c] == i, SCORE[c] == value[i])]
# choice not the same
constraint_neq = [CHOICE[0] != CHOICE[1]]
# bonus constraint. uncomment it to see the issue
# constraint_b = [B == bonus[val(CHOICE[0])][val(CHOICE[1])]]
# metric definition
constraint_sumscore = [metric == sum([SCORE[i] for i in choices ]) + B]
constraints = constraint_sumscore + constraint_sel + domain_choice + constraint_neq + constraint_b
opt = Optimize()
opt.add(constraints)
opt.maximize(metric)
s = []
if opt.check() == sat:
m = opt.model()
print [ m.evaluate(CHOICE[i]) for i in choices ]
print m.evaluate(metric)
else:
print "failed to solve"
Turns out the best way to deal with this problem is to actually not use arrays at all, but simply create integer variables. With this method, the 317x317 item problem originally posted actually gets solved in about 40 seconds on my relatively old computer:
[ 0.01s] Data loaded
[ 2.06s] Variables defined
[37.90s] Constraints added
[38.95s] Solved:
c0 = 19
c1 = 99
maxVal = 27
Note that the actual "solution" is found in about a second! But adding all the required constraints takes the bulk of the 40 seconds spent. Here's the encoding:
from z3 import *
import sys
import json
import sys
import time
start = time.time()
def tprint(s):
global start
now = time.time()
etime = now - start
print "[%ss] %s" % ('{0:5.2f}'.format(etime), s)
# load data
with open('data.json') as data_file:
dic = json.load(data_file)
tprint("Data loaded")
items = dic['items']
valueVals = dic['value']
bonusVals = dic['bonusVals']
vals = [[Int("val_%d_%d" % (i, j)) for j in items if j > i] for i in items]
tprint("Variables defined")
opt = Optimize()
for i in items:
for j in items:
if j > i:
opt.add(vals[i][j-i-1] == valueVals[i] + valueVals[j] + bonusVals[i][j])
c0, c1 = Ints('c0 c1')
maxVal = Int('maxVal')
opt.add(Or([Or([And(c0 == i, c1 == j, maxVal == vals[i][j-i-1]) for j in items if j > i]) for i in items]))
tprint("Constraints added")
opt.maximize(maxVal)
r = opt.check ()
if r == unsat or r == unknown:
raise Z3Exception("Failed")
tprint("Solved:")
m = opt.model()
print " c0 = %s" % m[c0]
print " c1 = %s" % m[c1]
print " maxVal = %s" % m[maxVal]
I think this is as fast as it'll get with Z3 for this problem. Of course, if you want to maximize multiple metrics, then you can probably structure the code so that you can reuse most of the constraints, thus amortizing the cost of constructing the model just once, and incrementally optimizing afterwards for optimal performance.

Help in optimizing a for loop in matlab

I have a 1 by N double array consisting of 1 and 0. I would like to map all the 1 to symbol '-3' and '3' and all the 0 to symbol '-1' and '1' equally. Below is my code. As my array is approx 1 by 8 million, it is taking a very long time. How to speed things up?
[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
if Data(loop,1) == 0
Data2(loop,1) = sym_zero;
if sym_zero == -1
sym_zero = 1;
else
sym_zero = -1;
end
else
Data2(loop,1) = sym_one;
if sym_one == -3
sym_zero = 3;
else
sym_zero = -3;
end
end
end
Here's a very important MATLAB optimization tip.
Preallocate!
Your code is much faster with a simple preallocation. Just add
Data2 = zeros(size(Data));
for loop = 1: row
...
before your for loop.
On my computer your code with preallocation terminated in 0.322s, and your original code is still running. I removed my original solution since yours is pretty fast with this optimization :).
Also since we're talking about MATLAB, it's faster to work on column vectors.
Hope you can follow this and I hope that I have understood your code correctly:
nOnes = sum(Data);
nZeroes = size(Data,2) - nOnes;
Data2(find(Data)) = repmat([-3 3],1,nOnes/2)
Data2(find(Data==0)) = repmat([-1 1],1,nZeroes/2)
I'll leave it to you to deal with the odd 1s and 0s.
So, disregarding negative signs, the equation for the output item Data2[loop,1] = Data[loop,1]*2 + 1. So why not first do that using a simple multiply-- that should be fast since it can be vectorized. Then create an array of half the original array length of 1s, half the original array length of -1s, call randperm on that. Then multiply by that. Everything's vectorized and should be much faster.
[row,ll] = size(Data);
sym_zero = -1;
sym_one = -3;
for loop = 1 : row
if ( Data(loop,1) ) // is 1
Data2(loop,1) = sym_one;
sym_one = sym_one * -1; // flip the sign
else
Data2(loop,1) = sym_zero;
sym_zero = sym_zero * -1; // flip the sign
end
end