Python, adding a "cashback" for every third iteration - python

Our professor gave us a problem of adding a "cashback" mechanism for an online store setting. We are tasked to use a parent class and a child class to use inheritance.
Goal: to add 50 after every third purchase
What I have so far:
Parent:
class Shop:
def __init__(self):
self.__balance = 0
def getBalance(self):
return self.__balance
def loadWallet(self, amount):
self.__balance += amount
def purchase(self, amount_val):
if amount_val <= self.__balance:
self.__balance -= amount_val
else:
print("Insufficient Funds")
Child:
class ShopCashBack(Shop):
def __init__(self, base_val=0):
self.__numpurchase = base_val
Shop.__init__(self)
def getPurch(self):
return self.__numpurchase
def purchase(self, amount_val):
self.__numpurchase += 1
Shop.purchase(self, amount_val)
if self.__numpurchase % 3 == 0:
result = self.getBalance() + 50
print(result)
Input:
user = ShopCashBack()
user.loadWallet(5000)
user.purchase(299)
print(user.getBalance())
user.loadWallet(3000)
print(user.getBalance())
user.purchase(4990)
print(user.getBalance())
user.purchase(1607)
print(user.getBalance())
Result:
4701
7701
2711
1154
1104
Desired Result:
where 1154 is 1104 + 50 (the balance after the third purchase)
4701
7701
2711
1154

you need to change child perchase method
from this:
if self.__numpurchase % 3 == 0:
result = self.getBalance() + 50
print(result)
to this:
if self.__numpurchase % 3 == 0:
self.loadWallet(50)
because you don't do anything to balance with result = self.getBalance() + 50 balance stays the same after this line

Related

How to calculate total price with discount by the products in Python

I created two classes. In class Cart i need to implement the method get_total_price that calculate total price with discount.
Discount depends on count product:
count discount
at least 5 5%
at least 7 10%
at least 10 20%
at least 20 30%
more than 20 50%
class Product:
def __init__(self, name, price, count):
self.name = name
self.price = price
self.count = count
class Cart:
def __init__(self, *products_list):
self.products_list = products_list
def get_total_price(self):
pass
products = (Product('p1',10,4),
Product('p2',100,5),
Product('p3',200,6),
Product('p4',300,7),
Product('p5',400,9),
Product('p6',500,10),
Product('p7',1000,20))
cart = Cart(products)
print(cart.get_total_price())
The result of running the program should be 24785.0
Can someone help, because I can not figure out how to get the attributes(price, count) to calculate the discount.
It seems cart.products_list returns a tuple containing the products list (so, a tuple in another tuple). If it's not intended, remove the '*'.
Here is a working solution for the current structure; if you remove '*', remove [0] in the get_total_price method.
def discount_mult(q):
if q > 20:
return .5
elif q >= 20:
return .7
elif q >= 10:
return .8
elif q >= 7:
return .9
elif q >= 5:
return .95
else:
return 1
class Product:
def __init__(self, name, price, count):
self.name = name
self.price = price
self.count = count
class Cart:
def __init__(self, *products_list):
self.products_list = products_list
def get_total_price(self):
return sum([i.price*i.count*discount_mult(i.count) for i in self.products_list[0]])
products = (Product('p1',10,4),Product('p2',100,5),Product('p3',200,6),Product('p4',300,7),
Product('p5',400,9),Product('p6',500,10),Product('p7',1000,20))
cart = Cart(products)
print(cart.get_total_price())

How to print an object?? - FreeCodeCamp Project

I'm doing the budget project in python. If I got it right, my class Category should return a value that when casted as a string, could be printed like this:
*************Food*************
initial deposit 1000.00
groceries -10.15
restaurant and more foo -15.89
Transfer to Clothing -50.00
Total: 923.96
The problem is if I make my object return something different of None, I get this error message:
TypeError: __init__() should return None, not 'str'
English isn't my first language, so it's quite possible that I messed up trying to understand what the projects want and what the test_module.py (test_to_string) really expects. Can you clarify for me?
My code:
class Category():
def __init__(self, c):
self.category = c
self.ledger = list()
length = len(self.category)
temp = int((30-length)/2)
n = temp if length <= 30 else 0
title = '*'* n + self.category + '*'*n
amount_f = []
amount_s = []
descr = []
for dic in self.ledger:
for info in dic.values():
if type(info) is int or type(info) is float:
info = float(info)
amount_f.append(info)
temp = '{0:>7.2f}'.format(info)
amount_s.append(temp)
elif type(info) is str:
descr.append(f'{info[:23]:<23}')
recipe = ''
for i in range(len(amount_s)):
recipe = f'{recipe}\n{descr[i]} {amount_s[i]}'
botton = '\nTotal: {:.2f}'.format(sum(amount_f))
self.category = (title + recipe + botton)
return self.category
def get_balance(self):
balance = []
for dictionary in self.ledger:
for value in dictionary.values():
if type(value) is int or type(value) is float:
balance.append(value)
return sum(balance)
def check_funds(self, amount):
if amount > self.get_balance():
return False
else:
return True
def deposit(self, amount, description=''):
self.ledger.append({'amount': amount, 'description': description})
def withdraw(self, amount, description=''):
if self.check_funds(amount) == False:
return False
self.ledger.append({'amount': -(amount), 'description': description})
return True
def transfer(self, amount, department):
if self.check_funds(amount) == False:
return False
self.withdraw(amount, 'Transfer to ' + department.category)
department.deposit(amount, 'Transfer from ' + self.category)
return True
def create_spend_chart(categories):
return 'aaaaaaaaaaa'
#####################################
#####################################
# Testing - Based in the test_module.py from FCC
entertaiment = Category('entertaiment')
food = Category('food')
food.deposit(900, "deposit")
food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
food.transfer(20, entertaiment)
actual = str(food)
print(actual)
#####################################
#####################################
The __init__ method isn't supposed to return a value at all. And that's what the error is telling you: should return None. You are trying to return a value from it.
So what you could do? Modify the code, so that the __init__ does not return any value :)
Feel free to copy and paste this in your project, it work's perfectly. So your code would be:
class Category():
def __init__(self, c):
self.category = c
self.ledger = list()
length = len(self.category)
temp = int((30-length)/2)
n = temp if length <= 30 else 0
title = '*'* n + self.category + '*'*n
amount_f = []
amount_s = []
descr = []
for dic in self.ledger:
for info in dic.values():
if type(info) is int or type(info) is float:
info = float(info)
amount_f.append(info)
temp = '{0:>7.2f}'.format(info)
amount_s.append(temp)
elif type(info) is str:
descr.append(f'{info[:23]:<23}')
recipe = ''
for i in range(len(amount_s)):
recipe = f'{recipe}\n{descr[i]} {amount_s[i]}'
botton = '\nTotal: {:.2f}'.format(sum(amount_f))
self.category = (title + recipe + botton)
print(self.category)
def get_balance(self):
balance = []
for dictionary in self.ledger:
for value in dictionary.values():
if type(value) is int or type(value) is float:
balance.append(value)
return sum(balance)
def check_funds(self, amount):
if amount > self.get_balance():
return False
else:
return True
def deposit(self, amount, description=''):
self.ledger.append({'amount': amount, 'description': description})
def withdraw(self, amount, description=''):
if self.check_funds(amount) == False:
return False
self.ledger.append({'amount': -(amount), 'description': description})
return True
def transfer(self, amount, department):
if self.check_funds(amount) == False:
return False
self.withdraw(amount, 'Transfer to ' + department.category)
department.deposit(amount, 'Transfer from ' + self.category)
return True
def create_spend_chart(categories):
return 'aaaaaaaaaaa'
entertaiment = Category('entertaiment')
food = Category('food')
food.deposit(900, "deposit")
food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
food.transfer(20, entertaiment)
actual = str(food)
print(actual)

I got some errors for implementation of GeneticAlgo

I am trying to make a time table scheduling program but found some errors. Please watch the following code and solve that error please.
Errors
These are the following errors
Traceback (most recent call last):
File "C:/Users/Muhammad Abbas/Downloads/ga02ClassScheduling.py", line 367, in <module>
population.get_schedules().sort(key=lambda x: x.get_fitness(), reverse=True)
File "C:/Users/Muhammad Abbas/Downloads/ga02ClassScheduling.py", line 367, in <lambda>
population.get_schedules().sort(key=lambda x: x.get_fitness(), reverse=True)
File "C:/Users/Muhammad Abbas/Downloads/ga02ClassScheduling.py", line 84, in get_fitness
self._fitness = self.calculate_fitness()
File "C:/Users/Muhammad Abbas/Downloads/ga02ClassScheduling.py", line 106, in calculate_fitness
if classes[i].get_room().get_seatingCapacity() < classes[i].get_course().get_maxNumbOfStudnets():
AttributeError: 'NoneType' object has no attribute 'get_seatingCapacity'
Source Code of the Program
Variables:
These are the variables which i declare for this program
import prettytable as prettytable
import random as rnd
POPULATION_SIZE = 9
NUMB_OF_ELITE_SCHEDULES = 1
TOURNAMENT_SELECTION_SIZE = 3
MUTATION_RATE = 0.1
Data Class
That is the first class which name is DATA
class Data:
ROOMS = [["R1", 25], ["R2", 45], ["R3", 35]]
MEETING_TIMES = [
["MT1", "MWF 09:00 - 10:00"],
["MT2", "MWF 10:00 - 11:00"],
["MT3", "TTH 09:00 - 10:30"],
["MT4", "TTH 10:30 - 12:00"]
]
INSTRUCTORS = [
["T1", "Dr James Web"],
["T2", "Mr Mike Brown"],
["T3", "Dr Steve Day"],
["T4", "Mrs Jane Doe"]
]
def __init__(self):
self._rooms = []
self._meetingTimes = []
self._instructors = []
for i in range(0, len(self.ROOMS)):
self._rooms.append(Room(self.ROOMS[i][0], self.ROOMS[i][1]))
for i in range(0, len(self.MEETING_TIMES)):
self._meetingTimes.append(MeetingTime(self.MEETING_TIMES[i][0], self.MEETING_TIMES[i][1]))
for i in range(0, len(self.INSTRUCTORS)):
self._instructors.append(Instructor(self.INSTRUCTORS[i][0], self.INSTRUCTORS[i][1]))
course1 = Course("C1", "325k", [self._instructors[0], self._instructors[1]], 25)
course2 = Course("C2", "319k", [self._instructors[0], self._instructors[1], self._instructors[2]], 35)
course3 = Course("C3", "462k", [self._instructors[0], self._instructors[1]], 25)
course4 = Course("C4", "464k", [self._instructors[2], self._instructors[3]], 30)
course5 = Course("C5", "360C", [self._instructors[3]], 35)
course6 = Course("C6", "303k", [self._instructors[0], self._instructors[2]], 45)
course7 = Course("C7", "303L", [self._instructors[1], self._instructors[3]], 45)
self._courses = [course1, course2, course3, course4, course5, course6, course7]
dept1 = Department("MATH", [course1, course3])
dept2 = Department("EE", [course2, course4, course5])
dept3 = Department("PHY", [course6, course7])
self._depts = [dept1, dept2, dept3]
self._numberOfClasses = 0
for i in range(0, len(self._depts)):
self._numberOfClasses += len(self._depts[i].get_courses())
def get_rooms(self):
return self._rooms
def get_instructors(self):
return self._instructors
def get_courses(self):
return self._courses
def get_depts(self):
return self._depts
def get_meetingTimes(self):
return self._meetingTimes
def get_numberOfClasses(self):
return self._numberOfClasses
Schedule Class
That is the second class which name is Schedule
class Schedule:
def __init__(self):
self._data = data
self._classes = []
self._numberOfConflicts = 0
self._fitness = -1
self._classNumb = 0
self._isFitnessChanged = True
def get_classes(self):
self._isFitnessChanged = True
return self._classes
def get_numberOfConflicts(self):
return self._numberOfConflicts
def get_fitness(self):
if(self._isFitnessChanged == True):
self._fitness = self.calculate_fitness()
self._isFitnessChanged = False
return self._fitness
def initialize(self):
depts = self._data.get_depts()
for i in range(0, len(depts)):
courses = depts[i].get_courses() #courses in each departments
for j in range(0, len(courses)):
newClass = Class(self._classNumb, depts[i], courses[j])
self._classNumb += 1
newClass.set_meetingTime(data.get_meetingTimes()[rnd.randrange(0, len(data.get_meetingTimes()))])
newClass.set_room(data.get_rooms()[rnd.randrange(0, len(data.get_rooms()))])
newClass.set_instructor(courses[j].get_instructors()[rnd.randrange(0, len(courses[j].get_instructors()))])
self._classes.append(newClass)
return self
def calculate_fitness(self):
self._numberOfConflicts = 0
classes = self.get_classes()
for i in range(0, len(classes)):
if classes[i].get_room().get_seatingCapacity() < classes[i].get_course().get_maxNumbOfStudnets():
self._numberOfConflicts += 1
for j in range(0, len(classes)):
if(j >= i):
if(classes[i].get_meetingTime() == classes[j].get_meetingTime() and
classes[i].get_id() != classes[j].get_id()):
if(classes[i].get_room() == classes[j].get_room()):
self._numberOfConflicts += 1
if(classes[i].get_instructor() == classes[j].get_instructor()):
self._numberOfConflicts += 1
return 1 / ((1.0*self._numberOfConflicts + 1))
def __str__(self):
# it returns all the classes of schedule separated by comas
returnValue = ""
for i in range(0, len(self._classes)):
returnValue += str(self._classes[i]) + ", "
returnValue += str(self._classes[len(self._classes)-1])
return returnValue
Population Class
Thats the third class which is Population class
class Population:
def __init__(self, size):
self._size = size
self._data = data
self._schedules = []
for i in range(0, size):
self._schedules.append(Schedule().initialize())
def get_schedules(self):
return self._schedules
GeneticAlgorithm Class
Thats the fourth class which is the GeneticAlgorithm class
class GeneticAlgorithm:
def evolve(self, population):
return self._mutate_population(self._crossover_population(population))
def _crossover_population(self, pop):
crossover_pop = Population(0)
for i in range(NUMB_OF_ELITE_SCHEDULES):
crossover_pop.get_schedules().append(pop.get_schedules()[i])
i = NUMB_OF_ELITE_SCHEDULES
while i < POPULATION_SIZE:
schedule1 = self._select_tournament_population(pop).get_schedules()[0]
schedule2 = self._select_tournament_population(pop).get_schedules()[0]
crossover_pop.get_schedules().append(self._crossover_schedule(schedule1, schedule2))
i += 1
return crossover_pop
def _mutate_population(self, population):
for i in range(NUMB_OF_ELITE_SCHEDULES, POPULATION_SIZE):
self._mutate_schedule(population.get_schedules()[i])
return population
def _crossover_schedule(self, schedule1, schedule2):
crossoverSchedule = Schedule().initialize()
for i in range(0, len(crossoverSchedule.get_classes())):
if (rnd.random() > 0.5):
crossoverSchedule.get_classes()[i] = schedule1.get_classes()[i]
else:
crossoverSchedule.get_classes()[i] = schedule2.get_classes()[i]
return crossoverSchedule
def _mutate_schedule(self,mutateSchedule):
schedule = Schedule().initialize()
for i in range(0, len(mutateSchedule.get_classes())):
if(MUTATION_RATE > rnd.random()):
mutateSchedule.get_classes()[i] = schedule.get_classes()[i]
return mutateSchedule
def _select_tournament_population(self, pop):
tournament_pop = Population(0)
i = 0
while i < TOURNAMENT_SELECTION_SIZE:
tournament_pop.get_schedules().append(pop.get_schedules()[rnd.randrange(0, POPULATION_SIZE)])
i += 1
tournament_pop.get_schedules().sort(key=lambda x:x.get_fitness(), reverse=True)
return tournament_pop
Course Class
Thats the fifth class which is the Course class
class Course:
def __init__(self, number, name, instructors, maxNumbOfStudents):
self._number = number
self._name = name
self._instructors = instructors
self._maxNumbOfStudents = maxNumbOfStudents
def get_name(self):
return self._name
def get_number(self):
return self._number
def get_instructors(self):
return self._instructors
def get_maxNumbOfStudents(self):
return self._maxNumbOfStudents
def __str__(self):
return self._name
Instructor Class
Thats the sixth class which is Instructor class
class Instructor:
def __init__(self, id, name):
self._id = id
self._name = name
def get_id(self):
return self._id
def get_name(self):
return self._name
def __str__(self):
return self._name
Room Class
Thats the seventh class which is the Room Class
class Room:
def __init__(self, number, seatingCapacity):
self._number = number
self._seatingCapacity = seatingCapacity
def get_number(self):
return self._number
def get_seatingCapacity(self):
return self._seatingCapacity
MeetingTime Class
Thats the eighth class which is MeetingTime class
class MeetingTime:
def __init__(self, id, time):
self._time = time
self._id = id
def get_id(self):
return self._id
def get_time(self):
return self._time
Department Class
Thats the ninth class which is the Department class
class Department:
# Batch for my case
def __init__(self, name, courses):
self._name = name
self._courses = courses # Courses that department offers
def get_name(self): return self._name
def get_courses(self): return self._courses
Class class
Thats is the tenth class which name is Class
class Class:
# Course to be scheduled at specific room of department host by an instructor at specific Meeting Time
def __init__(self, id, dept, course):
self._id = id
self._dept = dept
self._course = course
self._instructor = None
self._meetingTime = None
self._room = None
def get_id(self):
return self._id
def get_dept(self):
return self._dept
def get_room(self):
return self._room
def get_course(self):
return self._course
def get_instructor(self):
return self._instructor
def get_meetingTime(self):
return self._meetingTime
def set_instructor(self, instructor):
self._instructor = instructor
def set_meetingTime(self, meetingTime):
self._meetingTime = meetingTime
def set_room(self, room):
self_room = room
def __str__(self):
return str(self._dept.get_name()) + "," + str(self._course.get_number()) + "," + \
str(self._room.get_number()) + "," + str(self._instructor.get_id()) + "," + str(self._meetingTime.get_id())
DisplayMgr Class Plus End Code
Thats the eleventh class which is DisplayMgr Class and the end code of that program.
class DisplayMgr:
def print_available_data(self):
print("> All Available Data")
self.print_dept()
self.print_course()
self.print_room()
self.print_instructor()
self.print_meeting_times()
def print_dept(self):
depts = data.get_depts()
availableDeptsTable = prettytable.PrettyTable(['dept', 'courses'])
for i in range(0, len(depts)):
courses = depts.__getitem__(i).get_courses()
tempStr = "["
for j in range(0, len(courses) - 1):
tempStr += courses[j].__str__() + ", "
tempStr += courses[len(courses) - 1].__str__() + "]"
availableDeptsTable.add_row([depts.__getitem__(i).get_name(), tempStr])
print(availableDeptsTable)
def print_course(self):
availabelCoursesTable = prettytable.PrettyTable(['id', 'course # ', 'max # of students', 'instructors'])
courses = data.get_courses()
for i in range(0, len(courses)):
instructors = courses[i].get_instructors()
tempStr = ""
for j in range(0, len(instructors)-1):
tempStr += instructors[j].__str__() + ", "
tempStr += instructors[len(instructors) - 1].__str__()
availabelCoursesTable.add_row(
[courses[i].get_number(), courses[i].get_name(), str(courses[i].get_maxNumbOfStudents()), tempStr]
)
print(availabelCoursesTable)
def print_instructor(self):
availableInstructorsTable = prettytable.PrettyTable(['id', 'instructor'])
instructors = data.get_instructors()
for i in range(0, len(instructors)):
availableInstructorsTable.add_row([instructors[i].get_id(), instructors[i].get_name()])
print(availableInstructorsTable)
def print_room(self):
availableRoomsTable = prettytable.PrettyTable(['room #', 'max seating capacity'])
rooms = data.get_rooms()
for i in range(0, len(rooms)):
availableRoomsTable.add_row([str(rooms[i].get_number()), str(rooms[i].get_seatingCapacity())])
print(availableRoomsTable)
def print_meeting_times(self):
availableMeetingTimeTable = prettytable.PrettyTable(['id', 'Meeting Time'])
meetingTimes = data.get_meetingTimes()
for i in range(0, len(meetingTimes)):
availableMeetingTimeTable.add_row([meetingTimes[i].get_id(), meetingTimes[i].get_time()])
print(availableMeetingTimeTable)
def print_generation(self, population):
table1 = prettytable.PrettyTable(['schedule # ', 'fitness', '# of Conflicts','classes [dept, class, room, instructor'])
schedules = population.get_schedules()
for i in range(0, len(schedules)):
table1.add_row([str(i), round(schedules[i].get_fitness(),3), schedules[i].get_numberOfConflicts(), schedules[i]])
print(table1)
def print_schedule_as_table(self, schedule):
classes = schedule.get_classes()
table = prettytable.PrettyTable(['Class # ', 'Dept', 'Course (number, max # of students)', 'Room (Capacity', 'Instructor'])
for i in range(0, len(classes)):
table.add_row([str(i), classes[i].get_dept().get_name(), classes[i].get_course().get_name() + " (" +
classes[i].get_course().get_number() + ", " +
str(classes[i].get_course().get_maxNumbOfStudents()) + ")",
classes[i].get_room().get_number() + " (" + str(classes[i].get_room().get_seatingCapacity()) +
classes[i].get_instructor().get_name() + " (" + str(classes[i].get_instructor().get_id()) +")",
classes[i].get_meatingTime().get_time() + " (" + str(classes[i].get_meatingTime().get_id()) +")"
])
print(table)
data = Data()
displayMgr = DisplayMgr()
displayMgr.print_available_data()
generationNumber = 0
print("\n> Generation # " + str(generationNumber))
population = Population(POPULATION_SIZE)
population.get_schedules().sort(key=lambda x: x.get_fitness(), reverse=True)
displayMgr.print_generation(population)
displayMgr.print_schedule_as_table(population.get_schedules()[0]) # it will print fittest generation of schedule
geneticAlgorithm = GeneticAlgorithm()
while (population.get_schedules()[0].get_fitness() != 1.0):
generationNumber += 1
print("\n> Generation # " + str(generationNumber))
population = geneticAlgorithm.evolve(population)
population.get_schedules().sort(key=lambda x: x.get_fitness(), reverse=True)
displayMgr.print_generation(population)
displayMgr.print_schedule_as_table(population.get_schedules()[0])
print("\n\n")
def set_room(self, room):
self_room = room
you have missing . in set_room(self,room) function . Change it to self._room=room so that it will set the room value and objectType=None will be solved
Look into your the class DisplayMgr/def print_schedule_as_table
Change classes[i].get_meatingTime().get_time() to meetingTime

Simple Class --> Class property updation

I have a simple class. This is the output I got:
>>> print(Customer.total_amount)
1300
but I expected the output to be:
>>> print(Customer.total_amount)
1000
What am I doing wrong?
class Customer:
total_amount = 0
def __init__(self, name, mob, email, amount=None):
self.name = name
self.mob = mob
self.eamil = email
self.amount = 0
def add_amount(self, amount):
self.amount += amount
Customer.total_amount += self.amount
cust1 = Customer("cust1", "8892398598", "ritheshb1#gmail.com")
cust2 = Customer("cust2", "8892498598", "ritheshb2#gmail.com")
cust1.add_amount(100)
cust2.add_amount(200)
cust1.add_amount(300)
cust2.add_amount(400)
print(cust1.amount)
print(cust2.amount)
print(Customer.total_amount)
Change :
Customer.total_amount += self.amount
to
Customer.total_amount += amount

Does instantiating a class redefine the class including all of its methods?

I'm making a program that will go through at least 1,016,064 gear permutations on Diablo 3. I've been experimenting with different theoretical implementations and I decided that I wanted to use classes to represent each permutation rather than having to deal with massive and convoluted dictionaries. With this method I can store an instance and then replace it when a new permutation is superior to the former.
In any case it takes my computer (i7-3632QM) about 40 seconds go through all of the permutations just doing about 30 flops per permutation, and I cant even imagine how long it'll take if it has to define all 50 methods each time a class is instantiated. Anyway, this is what I think it'll look like:
class perm:
def __init__(self, *args):
self.x = 10
self.y = 5
self.z = 100
for item in args:
if hasattr(self, item):
getattr(self, item)()
self.val_1 = self.x * 2
self.val_2 = self.y * 5
self.val_3 = self.z/(self.z+300)
def head_1(self):
self.x += 5
self.z + 200
def head_2(self):
self.x += 10
self.y += 10
def feet_1(self):
self.y += 5
self.z += 250
def feet_2(self):
self.x += 10
self.z += 500
current_best = perm('head_1','feet_2')
It seems like the correct way to do this is to make objects for each of the gear options you have, then a function that calculates them all.
import itertools
class Gear(object):
def __init__(self, *args, **kwargs):
# I have no idea what Gear should do...
class Headpiece(Gear):
...
class Legs(Gear):
...
# etc
def calculate_perm(gear_tuple):
result = do_some_calculation_over(gear_tuple)
return result
best = max(itertools.permutations(all_your_gear), key=calculate_perm)
You could even create one class that's analogous to your perm, though I'd give it a more descriptive name:
class EquipmentSet(object):
slots = ['head', 'legs', ... ]
def __init__(self, head=None, legs=None, ...)
self.head = head
self.legs = legs
...
self.equipment = [getattr(self, item) for item in self.slots]
#property
def x(self)
return sum(item.x for item in self.equipment)
# similar for y and z
#property
def val_1(self):
return self.x * 2
# similar for val_2, val_3
# implement dunder rich comparison methods?
result = max(EquipmentSet(*gearset) for \
gearset in itertools.permutations(all_your_gear))
Strings are just as a example. These lists should contain Gear class, which instances knows what type of 'bonuses' gear gives.
import itertools
headpieces = ['headpiece1', 'headpiece2', 'headpiece3']
armors = ['armor1', 'armor2']
weapons = ['weapon1', 'weapon2']
print list(itertools.product(headpieces, armors, weapons))
# result:
[('headpiece1', 'armor1', 'weapon1'),
('headpiece1', 'armor1', 'weapon2'),
('headpiece1', 'armor2', 'weapon1'),
('headpiece1', 'armor2', 'weapon2'),
('headpiece2', 'armor1', 'weapon1'),
('headpiece2', 'armor1', 'weapon2'),
('headpiece2', 'armor2', 'weapon1'),
('headpiece2', 'armor2', 'weapon2'),
('headpiece3', 'armor1', 'weapon1'),
('headpiece3', 'armor1', 'weapon2'),
('headpiece3', 'armor2', 'weapon1'),
('headpiece3', 'armor2', 'weapon2')]
This code gives you all possible gears in lazy way (without passing it to list() it returns generator), is optimized (itertools are implemented in C) as is elegant. Note that in each element there is only one headpiece / weapon / armor. May be generalized to additional piece of gears.
After that you'll just have to write some kind of aggregator which takes input gear and returns 'score'.
Well I decided to use itertools, a module I have no experience with (but that will change after this!), and I've already half made the script making a test. It works so I might as well finish it even if it isn't the most efficient way, although I'm open to suggestions...
import time, itertools
class Barb:
def __init__(_, args):
_.elements = ['arcane','cold','fire','lightning','poison','physical']
_.strength = 5460 # max ancient str
_.vitality = 140
_.armor = 10188
_.all_res = 250
_.resistances = {element:7.7 for element in _.elements}
_.dodge = 0
_.armor_bonus_percent = .25
_.all_res_bonus_percent = 0
_.life_bonus_percent = .25
_.elemental_damage_reduction = 1
_.regen = 10730
_.life_on_hit = 8035
_.life_per_fury_spent = 0
_.life_percent_per_second_regen = 0
_.damage_mod = 1
_.cc = .05
_.cd = 2.8
_.ias = .25
_.attacks_per_second = 1.69
_.ww_damage_percent = 0
_.dibs = 0
_.cdr = 1
_.elemental_damage_bonus = .2
_.bastions = False
# apply gear bonuses
for arg in args:
getattr(_, arg)()
def helm_1(_):
_.cc += .06
_.ww_damage_percent += .15
_.life_bonus_percent += .23
_.resistances['arcane'] += 210
def helm_2(_):
_.cc += .06
_.vitality += 1000
_.life_bonus_percent += .23
_.resistances['arcane'] += 210
def torso_1(_):
_.vitality += 650
_.life_bonus_percent += .15
_.resistances['fire'] += 210
def torso_2(_):
_.all_res += 120
_.vitality += 650
def pants_1(_):
_.vitality += 650
_.armor += 700
_.resistances['physical'] += 210
def pants_2(_):
_.vitality += 650
_.all_res += 120
def bastions_1(_):#ring set
_.strength += 1000
_.cc += .12
_.cd += 1
_.resistances['physical'] += 210
_.resistances['poison'] += 210
_.bastions = True
def bastions_2(_):
_.strength += 500
_.cc += .12
_.cd += 1
_.cdr *= .92
_.resistances['physical'] += 210
_.resistances['poison'] += 210
_.bastions = True
def bk_1(_): # (str, dmg, cdr) + (str, cdr, vit)
_.strength += 2000
_.damage_mod *= 1.05
_.cdr *= .9 * .9
_.vitality += 1000
def bk_2(_): # (str, dmg, cdr) + (str, dmg, loh)
_.strength += 2000
_.damage_mod *= 1.1
_.cdr *= .9
_.life_on_hit += 18000
def best_score():
def available_items(prefix):
#automagically check barb for possible item variants of the item slot 'prefix'
# so more can be added at a later time
r = []
i = 1
while True:
name = '%s_%s'%(prefix, i)
if hasattr(Barb, name):
r.append(name)
else: return r
i += 1
gear_slots = [
'helm','torso','pants','bastions','bk']
helms, torso, pants, bastions, bk = [available_items(i) for i in gear_slots]
gears = itertools.product(helms, torso, pants, bastions, bk)
bestOffense = {'gear':[],
'health':0,
'mitigation':0,
'damage':0}
elapsed = time.time()
while True:
try:
args = next(gears)
barb = Barb(args)
armor = barb.armor * (1 + barb.armor_bonus_percent)
damage_reduction = armor / (armor + 3500)
resistances = {res:(barb.resistances[res] + barb.all_res) \
* (1 + barb.all_res_bonus_percent) for \
res in barb.resistances}
elemental_dr = {res:resistances[res]/(resistances[res] + 350) \
for res in resistances}
health = barb.vitality * 100 * (1 + barb.life_bonus_percent)
aps = barb.attacks_per_second * (1 + barb.ias)
damage_mod = barb.damage_mod * (1 + (barb.strength / 100))
damage_mod *= (1 - barb.cc) + (barb.cc * barb.cd)
damage_mod *= 2.25 if barb.bastions else 1
damage_mod *= 1 + barb.elemental_damage_bonus
dust_devils = 25 * damage_mod * (1 + barb.dibs + barb.ww_damage_percent)
min_elemental_dr = elemental_dr[min(elemental_dr)]
mitigation = 1 - ((1-damage_reduction) * (1-min_elemental_dr))
if dust_devils > bestOffense['damage']:
bestOffense = {'gear':args,
'health':health,
'mitigation':mitigation,
'damage':dust_devils}
except: return bestOffense, time.time() - elapsed
Python static methods will stop the interpreter making a new function in memory for every instance of a class. You can only use it for functions that don't need an instance to operate on though, i.e. functions that don't use self.

Categories