def hide(self): super().hide() self.is_visible = False for pr in self.properties.widgets(): pr.hide() flag = Systems.get_current() is not None flag = not len(Systems.get_current().asteroids + Systems.get_current().satellites) if flag else False self.parent.set_skippable('Planetary Orbit', flag)
def suggest(self, planet, orbit, star): data = None planets_in_system = len(Systems.get_current().planets) e = round(0.584 * pow(planets_in_system, -1.2), 3) if planets_in_system > 1 else None if planet.habitable and orbit.temperature == 'habitable': data = recomendation['habitable'] if e is not None and e <= 0.2: data.update({'e': e}) elif planet.clase == 'Terrestial Planet': data = recomendation['inner'] if e is not None and e <= 0.2: data.update({'e': e}) elif planet.clase in ('Gas Giant', 'Super Jupiter', 'Puffy Giant', 'Gas Dwarf'): data = recomendation['giant'] data.update(self.analyze_giants(planet, orbit, star)) if data.get('eccentric', False): pass elif e is not None and 0.001 <= e <= 0.09: data.update({'e': e}) self.format = data
def show(self): system = Systems.get_current() if system is not None: planets = [i for i in system.planets if i.orbit is None] if not len( self.listed_objects.get_widgets_from_layer( Systems.get_current_idx())): self.populate(planets) super().show()
def show_name(self): self.image.fill(COLOR_BOX, (0, 21, self.rect.w, 16)) planet = self.curr_planet if planet is not None: text = 'Atmosphere of planet' idx = Systems.get_current().planets.index(planet) text += ' #' + str(idx) + ' (' + planet.clase + ')' self.write(text, self.f2, centerx=self.rect.centerx, y=21)
def show_mass(self): try: mass = Systems.get_current().get_available_mass() except AttributeError: mass = q(0, 'jupiter_mass') if not self.show_jovian_mass: mass = mass.to('earth_mass') attr = '{:,g~}'.format((round(mass, 4))) return attr
def analyze_giants(planet, orbit, star): planets_in_system = len(Systems.get_current().planets) e = round(0.584 * pow(planets_in_system, -1.2), 3) if planets_in_system > 1 else None # average eccentricity clase = planet.clase in ('Puffy Giant', 'Gas Giant') orbita = 0.04 <= orbit.a.m <= 0.5 period = q(sqrt(pow(orbit.a.m, 3) / star.mass.m), 'year').to('day').m >= 3 if all([clase, orbita, period]) is True: return recomendation['hot'] clase = planet.clase == 'Super Jupiter' orbita = 0.04 <= orbit.a.m <= 1.2 * star.frost_line.m if all([clase, orbita]) is True: # this is more of a warning than a suggestion, since a super jupiter # can't be placed too far away from the star, and there is no special # consideration about it's eccentricity or inclination. return recomendation['giant'] elif clase: # Is the planet still a Super Jupiter? raise AssertionError( "A super jupiter can't orbit so far away from it's star.") # needs an "undo" after this. clase = planet.clase in ('Gas Dwarf', 'Gas Giant') orbita = 1.2 * star.frost_line.m <= orbit.a.m < star.outer_boundry.m if all([clase, orbita]) is True: return recomendation['giant'] clase = planet.clase == 'Gas Giant' habitable = any([i.habitable for i in Systems.get_current().planets]) data = recomendation['giant'] data.update({'eccentric': True}) error = f'An eccentric Jupiter must have an orbital eccentricity of 0.1 or greater, up to 0.2 if there is a ' error += f'habitable world in the system. However, there are {planets_in_system} planets in this system, so ' error += f'the eccentricity should be {e} which falls ouside of those parameters.' assert all([habitable, planets_in_system not in (3, 4), e > 0.1]), error if all([clase, habitable]) is True: data.update(recomendation['eccentric_2']) elif not habitable: data.update(recomendation['eccentric_1']) return data
def show(self): system = Systems.get_current() if system is not None: bodies = [ body for body in system.astro_bodies if body.hill_sphere != 0 ] if not len( self.listed_objects.get_widgets_from_layer( Systems.get_current_idx())): self.populate(bodies) super().show()
def add_button(self, planet): button = CreatedPlanet(self.current, planet, self.curr_x, self.curr_y) if planet.system_id is not None: layer_number = Systems.get_system_idx_by_id(planet.system_id) else: layer_number = Systems.get_current_idx() planet.system_id = Systems.get_current().id self.planet_buttons.add(button, layer=layer_number) self.planets.append(planet) self.sort_buttons() self.properties.add(button, layer=3)
def calculate(self): data = {'composition': None} if self.current is None: data['composition'] = {} else: data['composition'] = self.current.composition for item in self.properties.get_widgets_from_layer(2): if item.text_area.value: data[item.text.lower()] = float(item.text_area.value) for item in self.properties.get_widgets_from_layer(3): if item.text_area.value: data[item.text.lower()] = float(item.text_area.value) for material in self.properties.get_widgets_from_layer(4): if material.text_area.value: # not empty data['composition'][material.text.lower()] = float( material.text_area.value) if self.current is not None: data['a axis'] = self.current.a_axis.m data['b axis'] = self.current.b_axis.m data['c axis'] = self.current.c_axis.m data['id'] = self.current.id data['system'] = self.current.system_id moon = minor_moon_by_composition(data) if self.current is None: if Systems.get_current().add_astro_obj(moon): self.current = moon self.parent.button_add.enable() else: Systems.get_current().remove_astro_obj(self.current) if Systems.get_current().add_astro_obj(moon): self.current = moon if self.current.system_id is None: self.current.system_id = Systems.get_current().id self.fill()
def calculate(self): data = {'composition': None} if self.current is None: data['composition'] = {} else: data['composition'] = self.current.composition for material in self.properties.get_sprites_from_layer(2): if material.text_area.value: # not empty text = material.text_area.value.strip(' %') data['composition'][material.text.lower()] = float(text) for item in self.properties.get_widgets_from_layer(1): text = item.text_area.value if type(text) is not str: data[item.text.lower()] = float(text) elif text != '' and not text.isalpha(): data[item.text.lower()] = float(text) else: data[item.text.lower()] = text if self.current is not None: data['radius'] = self.current.radius.m data['id'] = self.current.id data['system'] = self.current.system_id self.has_values = True moon = major_moon_by_composition(data) if self.current is None: if Systems.get_current().add_astro_obj(moon): self.current = moon else: Systems.get_current().remove_astro_obj(self.current) if Systems.get_current().add_astro_obj(moon): self.current = moon if self.current.system_id is None: self.current.system_id = Systems.get_current().id self.parent.button_add.enable() self.fill()
def show(self): system = Systems.get_current() if system is not None: pop = [ planet for planet in system.planets if not len(planet.atmosphere) and planet.orbit is not None ] if not len( self.listed_objects.get_widgets_from_layer( Systems.get_current_idx())): self.populate(pop) super().show()
def add_button(self): button = AsteroidButton(self.current, self.current.current, self.curr_x, self.curr_y) if self.current.current.system_id is not None: layer_number = Systems.get_system_idx_by_id( self.current.current.system_id) else: layer_number = Systems.get_current_idx() self.current.current.system_id = Systems.get_current().id self.moons.append(self.current.current) self.asteroids.add(button, layer=layer_number) self.properties.add(button) self.sort_buttons() self.current.erase() self.button_add.disable()
def create_button(self, planet=None): if planet is None: planet = self.current system = Systems.get_current() else: system = Systems.get_system_by_id(planet.system_id) if system.add_astro_obj(planet): for button in self.properties.get_widgets_from_layer(1): button.text_area.clear() self.parent.button_add.disable() self.parent.add_button(planet) self.has_values = False self.parent.image.fill(COLOR_BOX, self.hab_rect) if self.current is not None and self.current.sprite is not None: self.current.sprite.hide()
def fill(self, tos=None): tos = { 'mass': 'kg', 'radius': 'km', 'luminosity': 'W', 'lifetime': 'year', 'temperature': 'kelvin' } super().fill(tos) system = Systems.get_current() if system is not None: system.update() if self.current.sprite is None: self.current.sprite = StarSprite(self, self.current, 460, 100) self.properties.add(self.current.sprite) self.current.sprite.show()
def add_objects(self): system = Systems.get_current() if system is not None: for obj in system.satellites + system.asteroids: if obj not in self.objects: self.objects.append(obj) btn = ObjectButton(self, obj, self.curr_x, self.curr_y) if obj.orbit is not None: btn.update_text(obj.orbit.a) markers = self._markers[obj.orbit.star.id] marker_idx = [ i for i in range(len(markers)) if markers[i].obj == obj ][0] marker = markers[marker_idx] btn.link_marker(marker) self.buttons.add(btn, layer=Systems.get_current_idx()) self.properties.add(btn) self.sort_buttons()
def add_new(self, obj): if obj not in self.added: self.added.append(obj) obj_name = obj.cls pln_habitable = Systems.get_current().is_habitable(self.current) pln_hill = self.current.hill_sphere.m obj_type = obj.celestial_type roches = self.create_roches_marker(obj) text = "A satellite's mass must be less than or equal to the\nmass of the planet." text += '\n\nConsider using a less massive satellite for this planet.' assert self.current.mass.to('earth_mass').m >= obj.mass.to( 'earth_mass').m, text pos = q( round( roll(self.current.roches_limit.m, self.current.hill_sphere.m / 2), 3), 'earth_radius') orbit = RawOrbit(Systems.get_current_star(), pos) obj_marker = Marker(self, obj_name, pos, color=COLOR_SELECTED, lock=False) max_value = pln_hill if pln_habitable and obj_type != 'asteroid': max_value /= 2 obj_marker.set_max_value(max_value) obj_marker.set_min_value(roches.m) obj_marker.links(orbit, obj) self.markers.append(obj_marker) self.properties.add(obj_marker, layer=3) self.sort_markers() return orbit, obj_marker
def check_values(self, composition): attrs = {} for button in self.properties.get_sprites_from_layer(1): attr = '' if button in self.relatives: idx = self.relatives.widgets().index(button) attr = self.relative_args[idx] elif button in self.absolutes: idx = self.absolutes.widgets().index(button) attr = self.absolute_args[idx] if button.text_area.value: # not empty string = str(button.text_area.value).split(' ')[0] try: setattr(self, attr, float(string)) attrs[attr] = float(string) except ValueError: setattr(self, attr, button.text_area.value) attrs[attr] = button.text_area.value if len(attrs) > 1: unit = self.parent.unit.name.lower() attrs['unit'] = 'jupiter' if unit == 'gas giant' else 'earth' attrs['idx'] = len( self.parent.planet_buttons.get_widgets_from_layer( Systems.get_current_idx())) if composition is not None: attrs['composition'] = composition self.current = Planet(attrs) self.toggle_habitable() if self.current.mass <= Systems.get_current().body_mass: self.parent.button_add.enable() self.parent.mass_number.mass_color = COLOR_TEXTO else: self.parent.button_add.disable() self.parent.mass_number.mass_color = 200, 0, 0 self.fill()
def on_mousebuttondown(self, event): not_enough_mass = 'There is not enough mass in the system to create new bodies of this type.' if event.button == 1: p = self.parent if p.parent.name == 'Planet': data = None system = Systems.get_current() self.active = True available_mass = system.get_available_mass() if p.parent.unit.name == 'Habitable' and not p.has_values: available_mass = available_mass.to('earth_mass').m m_low, m_high, r_low, r_high = Terrestial if available_mass < m_high: m_high = available_mass assert m_high >= 3.5, not_enough_mass data = graph_loop(mass_lower_limit=m_low, mass_upper_limit=m_high, radius_lower_limit=r_low, radius_upper_limit=r_high) elif p.parent.unit.name == 'Terrestial' and not p.has_values: available_mass = available_mass.to('earth_mass').m m_high = 10 if available_mass < m_high: m_high = available_mass assert m_high > 0.1, not_enough_mass data = graph_loop(mass_upper_limit=m_high) elif p.parent.unit.name == 'Gas Dwarf' and not p.has_values: m_low, m_high, r_low, r_high = GasDwarf if available_mass.to('earth_mass').m < m_high: m_high = available_mass.m assert m_high > 0.2, not_enough_mass data = graph_loop(mass_lower_limit=m_low, mass_upper_limit=m_high, radius_lower_limit=r_low, radius_upper_limit=r_high, is_gas_drwaf=True) elif p.parent.unit.name == 'Gas Giant' and not p.has_values: assert available_mass.m >= 0.03, not_enough_mass data = gasgraph_loop(round(available_mass.m, 2)) elif p.parent.unit.name == 'Dwarf Planet' and not p.has_values: available_mass = round( available_mass.to('earth_mass').m, 4) assert available_mass > 0.0001, not_enough_mass data = dwarfgraph_loop( available_mass if available_mass < 0.1 else None) Renderer.reset() if data is not None: for elemento in self.parent.properties.get_sprites_from_layer( 1): attr = '' if elemento in self.parent.relatives: idx = self.parent.relatives.widgets().index( elemento) attr = self.parent.relative_args[idx] elif elemento in self.parent.absolutes: idx = self.parent.absolutes.widgets().index( elemento) attr = self.parent.absolute_args[idx] if attr in data: elemento.value = str(data[attr]) elemento.text_area.show() self.parent.check_values(data.get('composition', None)) elif self.text == 'Axial tilt': data = axial_loop() self.parent.update_value(self, data) elif p.parent.name == 'Orbit' and p.has_values: text = self.text_area if text.unit == 'year' and text.value < 0.01: attr = q(text.value, text.unit).to('day') if attr.m < 0.1: attr = attr.to('hour') text.set_value(attr) text.update() elif self.editable: self.active = True self.text_area.enable() elif p.parent.name == 'Naming' and not p.has_values: p.parent.set_current(self) self.active = True self.text_area.enable() else: self.active = True self.text_area.enable() return self.text
def destroy_button(self): destroyed = Systems.get_current().remove_astro_obj(self.current) if destroyed: self.parent.del_button(self.current) self.erase()