Advertisement
Guest User

Untitled

a guest
Dec 8th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.78 KB | None | 0 0
  1. """Pokemon."""
  2. import requests
  3. from os import path
  4. import json
  5.  
  6.  
  7. class World:
  8. """World class."""
  9.  
  10. def __init__(self, name, offset, limit):
  11. """Class constructor.
  12.  
  13. Check if f"{name}_{offset}_{limit}.txt" file exists, if it does, read pokemons in from that file, if not,
  14. then make an api
  15. request to f"https://pokeapi.co/api/v2/pokemon?offset={offset}&limit={limit}" to get pokemons and dump them to
  16. f"{name}_{offset}_{limit}.txt" file
  17. """
  18. self.name = name
  19. self.offset = offset
  20. self.limit = limit
  21. self.pokemons = []
  22. if path.exists(f"{name}_{offset}_{limit}.txt") is False:
  23. poke_file = self.dump_pokemons_to_file_as_json(f"{name}_{offset}_{limit}.txt")
  24. poke_file = open(f"{name}_{offset}_{limit}.txt").read().split('\n')
  25. for i in range(len(poke_file) - 1):
  26. line = json.loads(poke_file[i])
  27. line = json.dumps(line)
  28. poke = Pokemon(line) # object
  29. self.pokemons.append(poke)
  30.  
  31. def dump_pokemons_to_file_as_json(self, name):
  32. """
  33. :param name: name of the .txt file
  34. Write all self.pokemons separated by a newline to the given filename(if it doesnt exist, then create one)
  35. PS: Write the pokemon.__str__() version, not __repr__() as only name is useless :)
  36. """
  37. response = requests.get(f"https://pokeapi.co/api/v2/pokemon?offset={self.offset}&limit={self.limit}")
  38. json_object = response.json()
  39. poke_file = open(name, 'w')
  40. for result in json_object['results']:
  41. url = result['url']
  42. pokemon = Pokemon(url)
  43. poke_file.write(f'{pokemon.__str__()}\n')
  44. return open(name).read()
  45.  
  46. def fight(self):
  47. """
  48. A wild brawl between all pokemons where points are assigned to winners
  49. Note, every pokemon fights another pokemon only once
  50. Fight lasts until one pokemon runs out of hp.
  51. every pokemon hits only 1 time per turn and they take turns when they attack.
  52. Call choose_which_pokemon_hits_first(pokemon1, pokemon2): to determine which pokemon hits first
  53. Call pokemon_duel function in this method with the aforementioned pokemons.
  54. every exception thrown by called sub methods must be caught and dealt with.
  55. """
  56. pass
  57.  
  58. @staticmethod
  59. def pokemon_duel(pokemon1, pokemon2):
  60. """
  61. :param pokemon1: pokemon, who attacks first.
  62. :param pokemon2: pokemon, who attacks second.
  63. :return winner: pokemon, who won.
  64.  
  65. Here 2 pokemons fight.
  66. To get the attack and defense of the pokemon, call pokemon1.get_pokemon_attack()
  67. and pokemon1.get_pokemon_defense() respectively.
  68. Attack is multiplied by the pokemon1.get_attack_multiplier(list(second.data['types'])) multiplier
  69. Total attack is
  70. pokemon1.get_pokemon_attack(turn_counter) * multiplier1 - second.get_pokemon_defense(turn_counter)
  71. [turn counter starts from 1]
  72. Total attack is subtracted from other pokemons hp.
  73. Pokemons can not heal during the fight. (when total attack is negative, no damage is dealt)
  74. If the fight between 2 pokemons lasts more than 100 turns, then PokemonFightResultsInATieException() is thrown.
  75. If one pokemon runs out of hp, fight ends and the winner gets 1 point, (self.score += 1)
  76. then both pokemons are healed to full hp.
  77. """
  78.  
  79.  
  80. @staticmethod
  81. def choose_which_pokemon_hits_first(pokemon1, pokemon2):
  82. """
  83. :param pokemon1:
  84. :param pokemon2:
  85. Pokemon who's speed is higher, goes first. if both pokemons have the same speed, then pokemon who's weight
  86. is lower goes first, if both pokemons have same weight, then pokemon who's height is lower goes first,
  87. if both pokemons have the same height, then the pokemon with more abilities goes first, if they have the same
  88. amount of abilities, then the pokemon with more moves goes first, if the pokemons have the same amount of
  89. moves, then the pokemon with higher base_experience goes first, if the pokemons have the same
  90. base_experience then SamePokemonFightException() is thrown
  91. :return pokemon1 who goes first and pokemon2 who goes second (return pokemon1, pokemon2)
  92. """
  93. speed1 = pokemon1
  94. pass
  95.  
  96. def get_leader_board(self):
  97. """
  98. Get Pokemons by given format in a list sorted by the pokemon.score.
  99.  
  100. In case of the same score, order pokemons by their name (ascending).
  101.  
  102. :return: List of leader board. where winners are first
  103. """
  104. pass
  105.  
  106. def get_pokemons_sorted_by_attribute(self, attribute: str):
  107. """
  108. Get Pokemons by given format in a list sorted by the pokemon.data[attribute]
  109. :param attribute: pokemon data attribute to sort by
  110. :return: sorted List of pokemons
  111. """
  112. pass
  113.  
  114.  
  115. class Pokemon:
  116. """Class for Pokemon."""
  117.  
  118. def __init__(self, url_or_path_name: str):
  119. """Class constructor.
  120.  
  121. If it is url, then parse information from request to proper
  122. json file and save it to self.data.
  123. If it is a string representation of a json object, then parse it into json object and save to self.data
  124. """
  125. self.url_or_path_name = url_or_path_name # url or json object
  126. self.data = {}
  127. try:
  128. json_object = json.loads(self.url_or_path_name) # converts a JSON string to a Python dictionary
  129. self.data = json_object # TODO kas vaja muuta veel?
  130. except ValueError as e:
  131. json_object = self.parse_json_to_pokemon_information(self.url_or_path_name)
  132. self.find_data(json_object)
  133. self.score = 0
  134.  
  135. def parse_json_to_pokemon_information(self, url):
  136. """
  137. :param url: url where the information is requested.
  138. Called from constructor and this method requests data from url to parse it into proper json object
  139. and then saved under self.data example done previously
  140. """
  141. response = requests.get(url)
  142. json_object = response.json()
  143. return json_object
  144.  
  145. def find_data(self, json_object):
  146. """Find necessary information about pokemon and add it to self.data."""
  147. # name
  148. self.data["name"] = json_object["name"]
  149. # stats
  150. self.get_data_from_stats(json_object)
  151. # types
  152. self.get_more_data(json_object, "type", "types")
  153. # abilities
  154. self.get_more_data(json_object, "ability", "abilities")
  155. # forms
  156. for form in json_object["forms"]:
  157. if "forms" not in self.data:
  158. self.data["forms"] = []
  159. self.data["forms"].append(form["name"])
  160. # moves
  161. self.get_more_data(json_object, "move", "moves")
  162. # height
  163. self.data["height"] = json_object["height"]
  164. # base experience
  165. self.data["base_experience"] = json_object["base_experience"]
  166. # weight
  167. self.data["weight"] = json_object["weight"]
  168.  
  169. def get_data_from_stats(self, json_object):
  170. """Add necessary data from pokemon's stats to self.data."""
  171. for base_stat in json_object["stats"]:
  172. stat_type = base_stat["stat"]
  173. if stat_type["name"] == "speed":
  174. self.data["speed"] = base_stat["base_stat"]
  175. if stat_type["name"] == "special-defense":
  176. self.data["special-defense"] = base_stat["base_stat"]
  177. if stat_type["name"] == "special-attack":
  178. self.data["special-attack"] = base_stat["base_stat"]
  179. if stat_type["name"] == "defense":
  180. self.data["defense"] = base_stat["base_stat"]
  181. if stat_type["name"] == "attack":
  182. self.data["attack"] = base_stat["base_stat"]
  183. if stat_type["name"] == "hp":
  184. self.data["hp"] = base_stat["base_stat"]
  185.  
  186. def get_more_data(self, json_object, string1, string2):
  187. """Add more pokemon's data to self.data."""
  188. for poke_data in json_object[string2]:
  189. data = poke_data[string1]
  190. if string2 not in self.data:
  191. self.data[string2] = []
  192. self.data[string2].append(data["name"])
  193.  
  194. def get_attack_multiplier(self, other: list):
  195. """
  196. self.pokemon is attacking, other is defending
  197. :param other: list of other pokemon2.data['types']
  198. Calculate Pokemons attack multiplier against others types and take the best result.
  199. get the initial multiplier from Fighting Multiplier matrix.
  200. For example if self.type == ['fire'] and other == ['ground']: return fighting_multipliers['fire']['ground']
  201. if the defendant has dual types, then multiply the multipliers together.
  202. if the attacker has dual-types, then the best option is
  203. chosen(attack can only be of 1 type, choose better[higher multiplier])
  204. :return: Multiplier.
  205. """
  206. pass
  207.  
  208. def get_pokemon_attack(self, turn_counter):
  209. """
  210. :param turn_counter: every third round the attack is empowered. (return self.data['special-attack'])
  211. otherwise basic attack is returned (self.data['attack'])
  212. """
  213. # TODO special-attack ja turn_counter
  214. if turn_counter == 3:
  215. return self.data["special-attack"]
  216. return self.data["attack"]
  217.  
  218. def get_pokemon_defense(self, turn_counter):
  219. """
  220. Note: whatever the result is returned, return half of it instead (for example return self.data['defense'] / 2)
  221. :param turn_counter: every second round the defense is empowered. (return self.data['special-defense'])
  222. otherwise basic defense is returned (self.data['defense'])
  223. """
  224. # TODO special-defense ja turn:counter
  225. if turn_counter == 2:
  226. return self.data["special-defense"] / 2
  227. return self.data["defense"] / 2
  228.  
  229. def __str__(self):
  230. """
  231. String representation of json(self.data) object.
  232. One way to accomplish this is to use json.dumps functionality
  233. :return: string version of json file with necessary information
  234. """
  235. return f'{json.dumps(self.data)}'
  236.  
  237. def __repr__(self):
  238. """
  239. Object representation.
  240. :return: Pokemon's name in string format and his score, for example: "garchomp-mega 892"
  241. """
  242. name = self.data["name"]
  243. return f'{name} {self.score}'
  244.  
  245.  
  246. class SamePokemonFightException(Exception):
  247. """Custom exception thrown when same pokemons are fighting."""
  248. pass
  249.  
  250.  
  251. class PokemonFightResultsInATieException(Exception):
  252. """Custom exception thrown when the fight lasts longer than 100 rounds."""
  253. pass
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement