You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
5.7 KiB

  1. import sys
  2. import re
  3. ITEMS = {}
  4. ################################################################################################################################
  5. # file operations #
  6. # this section is dedicated to operations that save, load, and parse data stored to disk #
  7. # || || || || || || || || || || || #
  8. # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ #
  9. ################################################################################################################################
  10. ################################################################################################################################
  11. # user input #
  12. # this section is dedicated to operations that will not have any other purpose other than collecting data #
  13. # || || || || || || || || || || || #
  14. # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ #
  15. ################################################################################################################################
  16. class user_input:
  17. def __init__(self,comp_name):
  18. valid = ('raw','compound')
  19. error = True
  20. while not error:
  21. try:
  22. type = int(input("~{}~\ntype (0. {} | 1. {}): ".format(comp_name,*valid)))
  23. error = False
  24. except ValueError:
  25. pass
  26. self.type = valid[type]
  27. if self.type == 'compound':
  28. self.subs = {}
  29. i = 1
  30. while True:
  31. inp = input('sub #{} ({{comp_name}} * {{count}}): '.format(i))
  32. if inp == 'end':
  33. break
  34. sr = re.split(r' *\* *',inp)
  35. name = sr[0]
  36. if len(sr) == 1:
  37. count = 1
  38. else:
  39. count = int(sr[1])
  40. self.subs[name] = count
  41. i += 1
  42. def recursive_fill_in(comp_name):
  43. global ITEMS
  44. if not comp_name in ITEMS.keys():
  45. res = user_input(comp_name)
  46. if res.type == 'raw':
  47. ITEMS[comp_name] = raw_material(comp_name)
  48. else:
  49. ITEMS[comp_name] = complex_item(comp_name,res.subs)
  50. for sub in res.subs.keys():
  51. recursive_fill_in(sub)
  52. ################################################################################################################################
  53. # complexity #
  54. # this section is dedicated to operations that involve all processing and understanding of the input data #
  55. # || || || || || || || || || || || #
  56. # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ #
  57. ################################################################################################################################
  58. class item:
  59. def __init__(self,name):
  60. self.name = name
  61. global ITEMS
  62. ITEMS[name] = self
  63. class raw_material(item):
  64. def __init__(self,name):
  65. super().__init__(name)
  66. self.complexity = 0
  67. class complex_item(item):
  68. def __init__(self,name,sub_components):
  69. super().__init__(name)
  70. self.sub_components = sub_components
  71. self.naive_complexity = True
  72. self.all_sub = set(self.sub_components.keys())
  73. def recalculate_total_completixy(self):
  74. for name in self.sub_components.keys():
  75. component = ITEMS[name]
  76. if isinstance(component,complex_item):
  77. if component.naive_complexity:
  78. component.recalculate_total_completixy()
  79. component.naive_complexity = False
  80. self.all_sub.update(component.all_sub)
  81. @property
  82. def complexity(self):
  83. if self.naive_complexity:
  84. self.recalculate_total_completixy()
  85. self.naive_complexity = False
  86. return len(self.all_sub)
  87. def get_raw_material_cost(self,ret = {}):
  88. for name,count in self.sub_components.items():
  89. component = ITEMS[name]
  90. if isinstance(component,raw_material):
  91. prev = ret.get(name,0)
  92. ret[name] = prev + count
  93. elif isinstance(component,complex_item):
  94. component.get_raw_material_cost(ret)
  95. return ret
  96. def get_component_cost(self,ret = {}):
  97. for name,count in self.sub_components.items():
  98. component = ITEMS[name]
  99. if isinstance(component,complex_item):
  100. prev = ret.get(name,0)
  101. ret[name] = prev + count
  102. component.get_component_cost(ret)
  103. return ret
  104. def get_build_info(self):
  105. component_view = self.get_raw_material_cost()
  106. material_view = self.get_component_cost()
  107. build_order = component_view.items()
  108. build_order = sorted(build_order,key = lambda item: ITEMS[item[0]].complexity)
  109. return material_view,build_order
  110. def main():
  111. name = sys.argv[1]
  112. recursive_fill_in(name)
  113. print(ITEMS[name].get_build_info())
  114. if __name__ == "__main__":
  115. main()