def __init__(self, parent=None): super(OverviewWidget, self).__init__(parent) # objects, sub-windows self.ui = None self._btn_reload = None self._aswidget = None self.world = XNovaWorld_instance() # build progress widgets self.bp_widgets = dict() # build progress widgets self.bp_widgets_sy = dict() # shipyard build progress widgets self.bp_widgets_res = dict() # researches build progress widgets
def printer_thread(): import time from ui.xnova.xn_data import XNPlanet from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova import xn_logger logger = xn_logger.get('test01', debug=True) world = XNovaWorld_instance() planets = world.get_planets() world.script_test01_command = 'running' logger.info('Started.') # logger.info('Planets:') # for planet in planets: # logger.info('{0}'.format(str(planet))) # logger.info('End planets.') while True: time.sleep(1) # print(' test01 running...') if world.script_test01_command == 'stop': break if world.script_test01_command == 'pn': planet_id = planets[0].planet_id post_url = '?set=overview&mode=renameplanet&pl={0}'.format( planet_id) post_data = dict() # post_data['action'] = 'Покинуть колонию' post_data['action'] = 'Сменить название' post_data['newname'] = 'XX9-WV' referer = 'http://uni4.xnova.su/?set=overview&mode=renameplanet' world._page_downloader.post(post_url, post_data=post_data, referer=referer) logger.debug('Rename planet complete to [{0}]'.format( post_data['newname'])) # clear command world.script_test01_command = 'running' del world.script_test01_command logger.info('Stopped.')
def printer_thread(): import time from ui.xnova.xn_data import XNPlanet from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova import xn_logger logger = xn_logger.get('test01', debug=True) world = XNovaWorld_instance() planets = world.get_planets() world.script_test01_command = 'running' logger.info('Started.') # logger.info('Planets:') # for planet in planets: # logger.info('{0}'.format(str(planet))) # logger.info('End planets.') while True: time.sleep(1) # print(' test01 running...') if world.script_test01_command == 'stop': break if world.script_test01_command == 'pn': planet_id = planets[0].planet_id post_url = '?set=overview&mode=renameplanet&pl={0}'.format(planet_id) post_data = dict() # post_data['action'] = 'Покинуть колонию' post_data['action'] = 'Сменить название' post_data['newname'] = 'XX9-WV' referer = 'http://uni4.xnova.su/?set=overview&mode=renameplanet' world._page_downloader.post(post_url, post_data=post_data, referer=referer) logger.debug('Rename planet complete to [{0}]'.format(post_data['newname'])) # clear command world.script_test01_command = 'running' del world.script_test01_command logger.info('Stopped.')
def __init__(self, parent: QWidget): super(GalaxyView, self).__init__(parent) self.world = XNovaWorld_instance() # # setup frame self.setFrameShadow(QFrame.Raised) self.setFrameShape(QFrame.StyledPanel) # self._layout = QVBoxLayout() self.setLayout(self._layout) # temp self._layout.addWidget(QLabel('galaxy view', self))
def __init__(self, parent: QWidget): super(GalaxyOwnPlanetSelectorWidget, self).__init__(parent) self.world = XNovaWorld_instance() # setup frame self.setFrameShadow(QFrame.Raised) self.setFrameShape(QFrame.StyledPanel) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(6, 6, 6, 6) self._layout.setSpacing(0) self.setLayout(self._layout) # label self._lbl = QLabel(self.tr('Select planet:'), self) # combo self._cb = QComboBox(self) self._cb.setEditable(False) self._cb.setInsertPolicy(QComboBox.InsertAtBottom) self._cb.currentIndexChanged.connect(self.on_cb_currentChanged) # finalize layout self._layout.addWidget(self._lbl, 0, Qt.AlignHCenter) self._layout.addWidget(self._cb, 0, Qt.AlignCenter) # ... self.fill_planets()
def __init__(self, parent: QWidget): super(GalaxyCoordsSelectorWidget, self).__init__(parent) # data self._coords = [1, 1] # galaxy, system self.world = XNovaWorld_instance() # # setup frame self.setFrameShape(QFrame.NoFrame) self.setFrameShadow(QFrame.Raised) # self._layout = QHBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # self._planet_selector = GalaxyOwnPlanetSelectorWidget(self) self._planet_selector.planetSelected.connect(self.on_planet_selected) # self._galaxy_selector = GalaxyCoordSingleSelectorWidget(self) self._galaxy_selector.setCoordRange(1, 5) self._galaxy_selector.setTitle(self.tr('Galaxy')) self._galaxy_selector.coordChanged.connect(self.on_gal_changed) self._system_selector = GalaxyCoordSingleSelectorWidget(self) self._system_selector.setCoordRange(1, 499) self._system_selector.setTitle(self.tr('Solar system')) self._system_selector.coordChanged.connect(self.on_sys_changed) # self._btn_navigate = QPushButton(self) self._btn_navigate.setText(self.tr('Navigate')) self._btn_navigate.clicked.connect(self.on_btn_navigate) # self._layout.addWidget(self._planet_selector, 0) self._layout.addWidget(self._galaxy_selector, 0) self._layout.addWidget(self._system_selector, 0) self._layout.addWidget(self._btn_navigate, 0) self._layout.addStretch(1)
class GalaxyOwnPlanetSelectorWidget(QFrame): planetSelected = pyqtSignal(int) def __init__(self, parent: QWidget): super(GalaxyOwnPlanetSelectorWidget, self).__init__(parent) self.world = XNovaWorld_instance() # setup frame self.setFrameShadow(QFrame.Raised) self.setFrameShape(QFrame.StyledPanel) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(6, 6, 6, 6) self._layout.setSpacing(0) self.setLayout(self._layout) # label self._lbl = QLabel(self.tr('Select planet:'), self) # combo self._cb = QComboBox(self) self._cb.setEditable(False) self._cb.setInsertPolicy(QComboBox.InsertAtBottom) self._cb.currentIndexChanged.connect(self.on_cb_currentChanged) # finalize layout self._layout.addWidget(self._lbl, 0, Qt.AlignHCenter) self._layout.addWidget(self._cb, 0, Qt.AlignCenter) # ... self.fill_planets() def fill_planets(self): planets = self.world.get_planets() for pl in planets: st = '{0} {1}'.format(pl.name, pl.coords.coords_str()) dt = QVariant(pl.planet_id) self._cb.addItem(st, dt) @pyqtSlot(int) def on_cb_currentChanged(self, index: int): if index == -1: return planet_id = int(self._cb.currentData(Qt.UserRole)) self.planetSelected.emit(planet_id)
def __init__(self, parent: QWidget): super(GalaxyWidget, self).__init__(parent) self.world = XNovaWorld_instance() # main layout self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(2) self.setLayout(self._layout) # sub-widgets self._galaxy_coords = GalaxyCoordsSelectorWidget(self) self._galaxy_coords.setGalaxyRange(1, 5) self._galaxy_coords.setSystemRange(1, 499) self._galaxy_coords.coordsChanged.connect(self.on_coords_cahnged) self._galaxyview = GalaxyView(self) # scrollarea self._sa_galaxy = QScrollArea(self) self._sa_galaxy.setMinimumWidth(400) self._sa_galaxy.setMinimumHeight(300) self._sa_galaxy.setWidget(self._galaxyview) # self._layout.addWidget(self._galaxy_coords) self._layout.addWidget(self._sa_galaxy)
class PlanetWidget(QFrame): """ Provides view of galaxy/solarsystem contents as table widget """ requestOpenGalaxy = pyqtSignal(XNCoords) def __init__(self, parent: QWidget): super(PlanetWidget, self).__init__(parent) # self.world = XNovaWorld_instance() self._planet = XNPlanet() # setup frame self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # basic info panel self._bipanel = Planet_BasicInfoPanel(self) self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy) self._bipanel.requestRefreshPlanet.connect( self.on_request_refresh_planet) self._bipanel.requestRenamePlanet.connect( self.on_request_rename_planet) # build progress widgets self._bpw_buildings = BuildProgressWidget(self) self._bpw_buildings.hide() self._bpw_buildings.hide_planet_name() self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2) self._bpw_shipyard = BuildProgressWidget(self) self._bpw_shipyard.hide() self._bpw_shipyard.hide_planet_name() self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2) self._bpw_research = BuildProgressWidget(self) self._bpw_research.hide() self._bpw_research.hide_planet_name() self._bpw_research.layout().setContentsMargins(5, 2, 5, 2) # buildings self._cf_buildings = CollapsibleFrame(self) self._cf_buildings.setTitle(self.tr('Buildings')) self._sa_buildings = QScrollArea(self._cf_buildings) self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings) self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS) self._bip_buildings.show() self._sa_buildings.setWidget(self._bip_buildings) self._cf_buildings.addWidget(self._sa_buildings) # shipyard self._cf_shipyard = CollapsibleFrame(self) self._cf_shipyard.setTitle(self.tr('Shipyard')) self._sa_shipyard = QScrollArea(self._cf_shipyard) self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard) self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD) self._sa_shipyard.setWidget(self._bip_shipyard) self._cf_shipyard.addWidget(self._sa_shipyard) # research self._cf_research = CollapsibleFrame(self) self._cf_research.setTitle(self.tr('Research')) self._sa_research = QScrollArea(self._cf_research) self._bip_research = Planet_BuildItemsPanel(self._cf_research) self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES) self._sa_research.setWidget(self._bip_research) self._cf_research.addWidget(self._sa_research) # layout finalize self._layout.addWidget(self._bipanel) self._layout.addWidget(self._bpw_buildings) self._layout.addWidget(self._bpw_shipyard) self._layout.addWidget(self._bpw_research) self._layout.addWidget(self._cf_buildings) self._layout.addWidget(self._cf_shipyard) self._layout.addWidget(self._cf_research) # expand buildings frame by default self._cf_buildings.expand() # # connect signals self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded) self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed) self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded) self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed) self._cf_research.expanded.connect(self.on_frame_research_expanded) self._cf_research.collapsed.connect(self.on_frame_research_collapsed) # self._bpw_buildings.requestCancelBuild.connect( self.on_request_cancel_build) self._bpw_research.requestCancelBuild.connect( self.on_request_cancel_build) # self._bip_buildings.requestBuildItem.connect( self.on_request_build_item) self._bip_buildings.requestDowngradeItem.connect( self.on_request_downgrade_item) self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item) self._bip_research.requestBuildItem.connect(self.on_request_build_item) # # create timer self._timer = QTimer(self) self._timer.timeout.connect(self.on_timer) def get_tab_type(self) -> str: return 'planet' def setPlanet(self, planet: XNPlanet): self._planet = planet # setup basic info panel self._bipanel.setup_from_planet(self._planet) # setup build progress widgets self._bpw_buildings.update_from_planet(planet, typ='') self._bpw_shipyard.update_from_planet( planet, typ=BuildProgressWidget.BPW_TYPE_SHIPYARD) self._bpw_research.update_from_planet( planet, typ=BuildProgressWidget.BPW_TYPE_RESEARCH) # setup build items panels (in collapsible frames) self._bip_buildings.set_planet(planet) self._bip_shipyard.set_planet(planet) self._bip_research.set_planet(planet) # # start/restart timer self._timer.stop() self._timer.setInterval(1000) self._timer.setSingleShot(False) self._timer.start() def planet(self) -> XNPlanet: return self._planet @pyqtSlot() def on_timer(self): # update basic info panel - refresh resources self._bipanel.update_resources() # update build progress widgets - tick builds self._bpw_buildings.update_from_planet(self._planet) self._bpw_shipyard.update_from_planet( self._planet, BuildProgressWidget.BPW_TYPE_SHIPYARD) self._bpw_research.update_from_planet( self._planet, BuildProgressWidget.BPW_TYPE_RESEARCH) @pyqtSlot(XNCoords) def on_request_open_galaxy(self, coords: XNCoords): self.requestOpenGalaxy.emit(coords) @pyqtSlot() def on_request_refresh_planet(self): self.world.signal(self.world.SIGNAL_RELOAD_PLANET, planet_id=self._planet.planet_id) @pyqtSlot(int, str) def on_request_rename_planet(self, planet_id: int, planet_name: str): self.world.signal(self.world.SIGNAL_RENAME_PLANET, planet_id=planet_id, new_name=planet_name) @pyqtSlot(XNPlanetBuildingItem) def on_request_cancel_build(self, bitem: XNPlanetBuildingItem): if bitem is None: return if (bitem.remove_link is None) or (bitem.remove_link == ''): return self.world.signal(XNovaWorld.SIGNAL_BUILD_CANCEL, planet_id=self._planet.planet_id, bitem=bitem) @pyqtSlot(XNPlanetBuildingItem, int) def on_request_build_item(self, bitem: XNPlanetBuildingItem, quantity: int): if bitem is None: return self.world.signal(XNovaWorld.SIGNAL_BUILD_ITEM, planet_id=self._planet.planet_id, bitem=bitem, quantity=quantity) @pyqtSlot(XNPlanetBuildingItem) def on_request_downgrade_item(self, bitem: XNPlanetBuildingItem): if bitem is None: return if not bitem.is_building_item: logger.warn('Cannot dismantle item that is ' 'not building: {0}'.format(bitem)) return downgrade_price = '{0} {3}, {1} {4}, {2} {5}'.format( self.tr('Metal'), self.tr('Crystal'), self.tr('Deit'), int(bitem.cost_met // 2), int(bitem.cost_cry // 2), int(bitem.cost_deit // 2)) btn = QMessageBox.question( self, self.tr('Downgrade building'), self.tr('Are you sure you want to downgrade this building?') + '\n' + '{0} {1} {2}\n{3}: {4}'.format( bitem.name, self.tr('lv.'), bitem.level, self.tr('Cost'), downgrade_price), QMessageBox.Yes | QMessageBox.No) if btn == QMessageBox.Yes: self.world.signal(XNovaWorld.SIGNAL_BUILD_DISMANTLE, planet_id=self._planet.planet_id, bitem=bitem) @pyqtSlot() def on_frame_buildings_collapsed(self): pass @pyqtSlot() def on_frame_buildings_expanded(self): # collapse other frames self._cf_shipyard.collapse() self._cf_research.collapse() @pyqtSlot() def on_frame_shipyard_collapsed(self): pass @pyqtSlot() def on_frame_shipyard_expanded(self): # collapse other frames self._cf_buildings.collapse() self._cf_research.collapse() @pyqtSlot() def on_frame_research_collapsed(self): pass @pyqtSlot() def on_frame_research_expanded(self): # collapse other frames self._cf_buildings.collapse() self._cf_shipyard.collapse()
class GalaxyCoordsSelectorWidget(QFrame): """ Groups together two controls to select galaxy and system coordinates with a button to navigate there. TODO: it can also show maybe bookmarks? :D """ coordsChanged = pyqtSignal(int, int) def __init__(self, parent: QWidget): super(GalaxyCoordsSelectorWidget, self).__init__(parent) # data self._coords = [1, 1] # galaxy, system self.world = XNovaWorld_instance() # # setup frame self.setFrameShape(QFrame.NoFrame) self.setFrameShadow(QFrame.Raised) # self._layout = QHBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # self._planet_selector = GalaxyOwnPlanetSelectorWidget(self) self._planet_selector.planetSelected.connect(self.on_planet_selected) # self._galaxy_selector = GalaxyCoordSingleSelectorWidget(self) self._galaxy_selector.setCoordRange(1, 5) self._galaxy_selector.setTitle(self.tr('Galaxy')) self._galaxy_selector.coordChanged.connect(self.on_gal_changed) self._system_selector = GalaxyCoordSingleSelectorWidget(self) self._system_selector.setCoordRange(1, 499) self._system_selector.setTitle(self.tr('Solar system')) self._system_selector.coordChanged.connect(self.on_sys_changed) # self._btn_navigate = QPushButton(self) self._btn_navigate.setText(self.tr('Navigate')) self._btn_navigate.clicked.connect(self.on_btn_navigate) # self._layout.addWidget(self._planet_selector, 0) self._layout.addWidget(self._galaxy_selector, 0) self._layout.addWidget(self._system_selector, 0) self._layout.addWidget(self._btn_navigate, 0) self._layout.addStretch(1) def coordGalaxy(self) -> int: return self._coords[0] def coordSystem(self) -> int: return self._coords[1] def coords(self) -> list: return self._coords def setCoords(self, galaxy: int, system: int, do_emit: bool = True): prev_coords = self._coords self._galaxy_selector.setCoord(galaxy) # does all range-checking self._system_selector.setCoord(system) # does all range-checking # get actual fixed coords self._coords[0] = self._galaxy_selector.coord() self._coords[1] = self._system_selector.coord() # compare and emit if do_emit: if (prev_coords[0] != self._coords[0]) or (prev_coords[1] != self._coords[1]): self.coordsChanged.emit(self._coords[0], self._coords[1]) def setGalaxyRange(self, gal_min: int, gal_max: int): self._galaxy_selector.setCoordRange(gal_min, gal_max) def setSystemRange(self, sys_min: int, sys_max: int): self._system_selector.setCoordRange(sys_min, sys_max) @pyqtSlot(int) def on_gal_changed(self, c: int): self._coords[0] = c self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot(int) def on_sys_changed(self, c: int): self._coords[1] = c self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot() def on_btn_navigate(self): # get actual coords self._coords[0] = self._galaxy_selector.coord() self._coords[1] = self._system_selector.coord() # just force refresh like coords changed self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot(int) def on_planet_selected(self, planet_id: int): planet = self.world.get_planet(planet_id) if planet is None: return logger.debug(' navigating to: {0}'.format(planet.coords.coords_str())) self.setCoords(planet.coords.galaxy, planet.coords.system)
from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova import xn_logger logger = xn_logger.get("test01_stopper", debug=True) world = XNovaWorld_instance() try: existing = world.script_command # if this fails, no such member exists, an exception will be raised # else, continue # world.script_test01_command = 'stop' world.script_command = "stop" # world.script_test01_command = 'pn' logger.info('sent "stop" command to scripts.') except AttributeError as ea: logger.info("probably script is not running.") pass
from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova.xn_data import XNPlanet, XNPlanetBuildingItem from ui.xnova import xn_logger logger = xn_logger.get('test01_stopper', debug=True) world = XNovaWorld_instance() def energy_need_for_gid(gid: int, level: int) -> int: if (gid == 1) or (gid == 2) or (gid == 12): e = (10 * level) * (1.1**level) return round(e) if gid == 3: e = (30 * level) * (1.1**level) return round(e) return -1 try: planets = world.get_planets() if len(planets) > 0: planet = planets[0] for bitem in planet.buildings_items: e = energy_need_for_gid(bitem.gid, bitem.level) if e != -1: print('{0} lv {1} need {2} energy'.format( bitem.name, bitem.level, e)) except Exception as ex: logger.exception('Exception happened')
class PlanetWidget(QFrame): """ Provides view of galaxy/solarsystem contents as table widget """ requestOpenGalaxy = pyqtSignal(XNCoords) def __init__(self, parent: QWidget): super(PlanetWidget, self).__init__(parent) # self.world = XNovaWorld_instance() self._planet = XNPlanet() # setup frame self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # basic info panel self._bipanel = Planet_BasicInfoPanel(self) self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy) self._bipanel.requestRefreshPlanet.connect( self.on_request_refresh_planet) self._bipanel.requestRenamePlanet.connect(self.on_request_rename_planet) # build progress widgets self._bpw_buildings = BuildProgressWidget(self) self._bpw_buildings.hide() self._bpw_buildings.hide_planet_name() self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2) self._bpw_shipyard = BuildProgressWidget(self) self._bpw_shipyard.hide() self._bpw_shipyard.hide_planet_name() self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2) self._bpw_research = BuildProgressWidget(self) self._bpw_research.hide() self._bpw_research.hide_planet_name() self._bpw_research.layout().setContentsMargins(5, 2, 5, 2) # buildings self._cf_buildings = CollapsibleFrame(self) self._cf_buildings.setTitle(self.tr('Buildings')) self._sa_buildings = QScrollArea(self._cf_buildings) self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings) self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS) self._bip_buildings.show() self._sa_buildings.setWidget(self._bip_buildings) self._cf_buildings.addWidget(self._sa_buildings) # shipyard self._cf_shipyard = CollapsibleFrame(self) self._cf_shipyard.setTitle(self.tr('Shipyard')) self._sa_shipyard = QScrollArea(self._cf_shipyard) self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard) self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD) self._sa_shipyard.setWidget(self._bip_shipyard) self._cf_shipyard.addWidget(self._sa_shipyard) # research self._cf_research = CollapsibleFrame(self) self._cf_research.setTitle(self.tr('Research')) self._sa_research = QScrollArea(self._cf_research) self._bip_research = Planet_BuildItemsPanel(self._cf_research) self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES) self._sa_research.setWidget(self._bip_research) self._cf_research.addWidget(self._sa_research) # layout finalize self._layout.addWidget(self._bipanel) self._layout.addWidget(self._bpw_buildings) self._layout.addWidget(self._bpw_shipyard) self._layout.addWidget(self._bpw_research) self._layout.addWidget(self._cf_buildings) self._layout.addWidget(self._cf_shipyard) self._layout.addWidget(self._cf_research) # expand buildings frame by default self._cf_buildings.expand() # # connect signals self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded) self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed) self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded) self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed) self._cf_research.expanded.connect(self.on_frame_research_expanded) self._cf_research.collapsed.connect(self.on_frame_research_collapsed) # self._bpw_buildings.requestCancelBuild.connect( self.on_request_cancel_build) self._bpw_research.requestCancelBuild.connect( self.on_request_cancel_build) # self._bip_buildings.requestBuildItem.connect(self.on_request_build_item) self._bip_buildings.requestDowngradeItem.connect( self.on_request_downgrade_item) self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item) self._bip_research.requestBuildItem.connect(self.on_request_build_item) # # create timer self._timer = QTimer(self) self._timer.timeout.connect(self.on_timer) def get_tab_type(self) -> str: return 'planet' def setPlanet(self, planet: XNPlanet): self._planet = planet # setup basic info panel self._bipanel.setup_from_planet(self._planet) # setup build progress widgets self._bpw_buildings.update_from_planet(planet, typ='') self._bpw_shipyard.update_from_planet(planet, typ=BuildProgressWidget.BPW_TYPE_SHIPYARD) self._bpw_research.update_from_planet(planet, typ=BuildProgressWidget.BPW_TYPE_RESEARCH) # setup build items panels (in collapsible frames) self._bip_buildings.set_planet(planet) self._bip_shipyard.set_planet(planet) self._bip_research.set_planet(planet) # # start/restart timer self._timer.stop() self._timer.setInterval(1000) self._timer.setSingleShot(False) self._timer.start() def planet(self) -> XNPlanet: return self._planet @pyqtSlot() def on_timer(self): # update basic info panel - refresh resources self._bipanel.update_resources() # update build progress widgets - tick builds self._bpw_buildings.update_from_planet(self._planet) self._bpw_shipyard.update_from_planet(self._planet, BuildProgressWidget.BPW_TYPE_SHIPYARD) self._bpw_research.update_from_planet(self._planet, BuildProgressWidget.BPW_TYPE_RESEARCH) @pyqtSlot(XNCoords) def on_request_open_galaxy(self, coords: XNCoords): self.requestOpenGalaxy.emit(coords) @pyqtSlot() def on_request_refresh_planet(self): self.world.signal(self.world.SIGNAL_RELOAD_PLANET, planet_id=self._planet.planet_id) @pyqtSlot(int, str) def on_request_rename_planet(self, planet_id: int, planet_name: str): self.world.signal(self.world.SIGNAL_RENAME_PLANET, planet_id=planet_id, new_name=planet_name) @pyqtSlot(XNPlanetBuildingItem) def on_request_cancel_build(self, bitem: XNPlanetBuildingItem): if bitem is None: return if (bitem.remove_link is None) or (bitem.remove_link == ''): return self.world.signal(XNovaWorld.SIGNAL_BUILD_CANCEL, planet_id=self._planet.planet_id, bitem=bitem) @pyqtSlot(XNPlanetBuildingItem, int) def on_request_build_item(self, bitem: XNPlanetBuildingItem, quantity: int): if bitem is None: return self.world.signal(XNovaWorld.SIGNAL_BUILD_ITEM, planet_id=self._planet.planet_id, bitem=bitem, quantity=quantity) @pyqtSlot(XNPlanetBuildingItem) def on_request_downgrade_item(self, bitem: XNPlanetBuildingItem): if bitem is None: return if not bitem.is_building_item: logger.warn('Cannot dismantle item that is ' 'not building: {0}'.format(bitem)) return downgrade_price = '{0} {3}, {1} {4}, {2} {5}'.format( self.tr('Metal'), self.tr('Crystal'), self.tr('Deit'), int(bitem.cost_met//2), int(bitem.cost_cry // 2), int(bitem.cost_deit // 2)) btn = QMessageBox.question(self, self.tr('Downgrade building'), self.tr('Are you sure you want to downgrade this building?') + '\n' + '{0} {1} {2}\n{3}: {4}'.format( bitem.name, self.tr('lv.'), bitem.level, self.tr('Cost'), downgrade_price), QMessageBox.Yes | QMessageBox.No) if btn == QMessageBox.Yes: self.world.signal(XNovaWorld.SIGNAL_BUILD_DISMANTLE, planet_id=self._planet.planet_id, bitem=bitem) @pyqtSlot() def on_frame_buildings_collapsed(self): pass @pyqtSlot() def on_frame_buildings_expanded(self): # collapse other frames self._cf_shipyard.collapse() self._cf_research.collapse() @pyqtSlot() def on_frame_shipyard_collapsed(self): pass @pyqtSlot() def on_frame_shipyard_expanded(self): # collapse other frames self._cf_buildings.collapse() self._cf_research.collapse() @pyqtSlot() def on_frame_research_collapsed(self): pass @pyqtSlot() def on_frame_research_expanded(self): # collapse other frames self._cf_buildings.collapse() self._cf_shipyard.collapse()
class GalaxyCoordsSelectorWidget(QFrame): """ Groups together two controls to select galaxy and system coordinates with a button to navigate there. TODO: it can also show maybe bookmarks? :D """ coordsChanged = pyqtSignal(int, int) def __init__(self, parent: QWidget): super(GalaxyCoordsSelectorWidget, self).__init__(parent) # data self._coords = [1, 1] # galaxy, system self.world = XNovaWorld_instance() # # setup frame self.setFrameShape(QFrame.NoFrame) self.setFrameShadow(QFrame.Raised) # self._layout = QHBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # self._planet_selector = GalaxyOwnPlanetSelectorWidget(self) self._planet_selector.planetSelected.connect(self.on_planet_selected) # self._galaxy_selector = GalaxyCoordSingleSelectorWidget(self) self._galaxy_selector.setCoordRange(1, 5) self._galaxy_selector.setTitle(self.tr('Galaxy')) self._galaxy_selector.coordChanged.connect(self.on_gal_changed) self._system_selector = GalaxyCoordSingleSelectorWidget(self) self._system_selector.setCoordRange(1, 499) self._system_selector.setTitle(self.tr('Solar system')) self._system_selector.coordChanged.connect(self.on_sys_changed) # self._btn_navigate = QPushButton(self) self._btn_navigate.setText(self.tr('Navigate')) self._btn_navigate.clicked.connect(self.on_btn_navigate) # self._layout.addWidget(self._planet_selector, 0) self._layout.addWidget(self._galaxy_selector, 0) self._layout.addWidget(self._system_selector, 0) self._layout.addWidget(self._btn_navigate, 0) self._layout.addStretch(1) def coordGalaxy(self) -> int: return self._coords[0] def coordSystem(self) -> int: return self._coords[1] def coords(self) -> list: return self._coords def setCoords(self, galaxy: int, system: int, do_emit: bool = True): prev_coords = self._coords self._galaxy_selector.setCoord(galaxy) # does all range-checking self._system_selector.setCoord(system) # does all range-checking # get actual fixed coords self._coords[0] = self._galaxy_selector.coord() self._coords[1] = self._system_selector.coord() # compare and emit if do_emit: if (prev_coords[0] != self._coords[0]) or (prev_coords[1] != self._coords[1]): self.coordsChanged.emit(self._coords[0], self._coords[1]) def setGalaxyRange(self, gal_min: int, gal_max: int): self._galaxy_selector.setCoordRange(gal_min, gal_max) def setSystemRange(self, sys_min: int, sys_max: int): self._system_selector.setCoordRange(sys_min, sys_max) @pyqtSlot(int) def on_gal_changed(self, c: int): self._coords[0] = c self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot(int) def on_sys_changed(self, c: int): self._coords[1] = c self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot() def on_btn_navigate(self): # get actual coords self._coords[0] = self._galaxy_selector.coord() self._coords[1] = self._system_selector.coord() # just force refresh like coords changed self.coordsChanged.emit(self._coords[0], self._coords[1]) @pyqtSlot(int) def on_planet_selected(self, planet_id: int): planet = self.world.get_planet(planet_id) if planet is None: return logger.debug(' navigating to: {0}'.format( planet.coords.coords_str())) self.setCoords(planet.coords.galaxy, planet.coords.system)
def __init__(self, parent: QWidget): super(PlanetWidget, self).__init__(parent) # self.world = XNovaWorld_instance() self._planet = XNPlanet() # setup frame self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # basic info panel self._bipanel = Planet_BasicInfoPanel(self) self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy) self._bipanel.requestRefreshPlanet.connect( self.on_request_refresh_planet) self._bipanel.requestRenamePlanet.connect( self.on_request_rename_planet) # build progress widgets self._bpw_buildings = BuildProgressWidget(self) self._bpw_buildings.hide() self._bpw_buildings.hide_planet_name() self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2) self._bpw_shipyard = BuildProgressWidget(self) self._bpw_shipyard.hide() self._bpw_shipyard.hide_planet_name() self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2) self._bpw_research = BuildProgressWidget(self) self._bpw_research.hide() self._bpw_research.hide_planet_name() self._bpw_research.layout().setContentsMargins(5, 2, 5, 2) # buildings self._cf_buildings = CollapsibleFrame(self) self._cf_buildings.setTitle(self.tr('Buildings')) self._sa_buildings = QScrollArea(self._cf_buildings) self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings) self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS) self._bip_buildings.show() self._sa_buildings.setWidget(self._bip_buildings) self._cf_buildings.addWidget(self._sa_buildings) # shipyard self._cf_shipyard = CollapsibleFrame(self) self._cf_shipyard.setTitle(self.tr('Shipyard')) self._sa_shipyard = QScrollArea(self._cf_shipyard) self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard) self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD) self._sa_shipyard.setWidget(self._bip_shipyard) self._cf_shipyard.addWidget(self._sa_shipyard) # research self._cf_research = CollapsibleFrame(self) self._cf_research.setTitle(self.tr('Research')) self._sa_research = QScrollArea(self._cf_research) self._bip_research = Planet_BuildItemsPanel(self._cf_research) self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES) self._sa_research.setWidget(self._bip_research) self._cf_research.addWidget(self._sa_research) # layout finalize self._layout.addWidget(self._bipanel) self._layout.addWidget(self._bpw_buildings) self._layout.addWidget(self._bpw_shipyard) self._layout.addWidget(self._bpw_research) self._layout.addWidget(self._cf_buildings) self._layout.addWidget(self._cf_shipyard) self._layout.addWidget(self._cf_research) # expand buildings frame by default self._cf_buildings.expand() # # connect signals self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded) self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed) self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded) self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed) self._cf_research.expanded.connect(self.on_frame_research_expanded) self._cf_research.collapsed.connect(self.on_frame_research_collapsed) # self._bpw_buildings.requestCancelBuild.connect( self.on_request_cancel_build) self._bpw_research.requestCancelBuild.connect( self.on_request_cancel_build) # self._bip_buildings.requestBuildItem.connect( self.on_request_build_item) self._bip_buildings.requestDowngradeItem.connect( self.on_request_downgrade_item) self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item) self._bip_research.requestBuildItem.connect(self.on_request_build_item) # # create timer self._timer = QTimer(self) self._timer.timeout.connect(self.on_timer)
class OverviewWidget(QWidget): def __init__(self, parent=None): super(OverviewWidget, self).__init__(parent) # objects, sub-windows self.ui = None self._btn_reload = None self._aswidget = None self.world = XNovaWorld_instance() # build progress widgets self.bp_widgets = dict() # build progress widgets self.bp_widgets_sy = dict() # shipyard build progress widgets self.bp_widgets_res = dict() # researches build progress widgets def load_ui(self): # layout self._layout = QVBoxLayout() self._layout_topbuttons = QHBoxLayout() self.setLayout(self._layout) self._layout.addLayout(self._layout_topbuttons) # sub-windows # reload button self._btn_reload = QPushButton(self.tr('Refresh overview'), self) self._btn_reload.setIcon(QIcon(':i/reload.png')) self._btn_reload.clicked.connect(self.on_btn_refresh_overview) self._layout_topbuttons.addWidget(self._btn_reload) self._layout_topbuttons.addStretch() # group box to hold builds info self._gb_builds = CollapsibleFrame(self) self._gb_builds.setTitle(self.tr('Building Jobs')) self._layout.addWidget(self._gb_builds) # groupbox to hold shipyard builds info self._gb_shipyard = CollapsibleFrame(self) self._gb_shipyard.setTitle(self.tr('Shipyard Jobs')) self._layout.addWidget(self._gb_shipyard) # groupbox to hold researches in progress info self._gb_research = CollapsibleFrame(self) self._gb_research.setTitle(self.tr('Researches')) self._layout.addWidget(self._gb_research) # groupbox to hold account stats widget self._gb_accstats = CollapsibleFrame(self) self._gb_accstats.setTitle(self.tr('Statistics')) self._layout.addWidget(self._gb_accstats) # account stats widget self._aswidget = Overview_AccStatsWidget(self) self._aswidget.load_ui() self._aswidget.show() self._gb_accstats.addWidget(self._aswidget) self._gb_accstats.expand() # staticstics expanded by default # add final spacer self._layout.addStretch() def update_account_info(self): a = self.world.get_account_info() if self._aswidget is not None: self._aswidget.update_account_info(a) def get_bpw_for_planet(self, planet_id: int, typ: str='') -> BuildProgressWidget: if typ == '': if planet_id in self.bp_widgets: return self.bp_widgets[planet_id] # create BPW for planet bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet) self._gb_builds.addWidget(bpw) self.bp_widgets[planet_id] = bpw bpw.hide() return bpw elif typ == BuildProgressWidget.BPW_TYPE_SHIPYARD: if planet_id in self.bp_widgets_sy: return self.bp_widgets_sy[planet_id] # create BPW for planet shipyard bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet) self._gb_shipyard.addWidget(bpw) self.bp_widgets_sy[planet_id] = bpw bpw.hide() return bpw elif typ == BuildProgressWidget.BPW_TYPE_RESEARCH: if planet_id in self.bp_widgets_res: return self.bp_widgets_res[planet_id] # create BPW for planet shipyard bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect(self.on_request_build_cancel_with_planet) self._gb_research.addWidget(bpw) self.bp_widgets_res[planet_id] = bpw bpw.hide() return bpw else: logger.error('get_bpw_for_planet(): unknown typre requested: {0}'.format(typ)) def update_builds(self): self.setUpdatesEnabled(False) # big visual changes may follow, stop screen flicker # delete existing build progress widgets (do not do it, just hide) for bpw in self.bp_widgets.values(): bpw.hide() for bpw in self.bp_widgets_sy.values(): bpw.hide() planets = self.world.get_planets() for pl in planets: # buildings bpw = self.get_bpw_for_planet(pl.planet_id) bpw.update_from_planet(pl) # shipyard if len(pl.shipyard_progress_items) > 0: bpw = self.get_bpw_for_planet(pl.planet_id, BuildProgressWidget.BPW_TYPE_SHIPYARD) bpw.show() bpw.update_from_planet(pl, BuildProgressWidget.BPW_TYPE_SHIPYARD) # researches bpw = self.get_bpw_for_planet(pl.planet_id, BuildProgressWidget.BPW_TYPE_RESEARCH) bpw.update_from_planet(pl, BuildProgressWidget.BPW_TYPE_RESEARCH) # make equal widths (this is not working, why?) # self._equalize_builds_widths() self.setUpdatesEnabled(True) def _equalize_builds_widths(self): maxwidth = -1 for bpw in self.bp_widgets: w = bpw.get_els_widths() if w > maxwidth: maxwidth = w for bpw in self.bp_widgets: w = bpw.make_as_wide_as(maxwidth) logger.debug('got max width: {0}'.format(maxwidth)) @pyqtSlot() def on_btn_refresh_overview(self): self.world.signal(self.world.SIGNAL_RELOAD_PAGE, page_name='overview') @pyqtSlot(XNPlanetBuildingItem, int) def on_request_build_cancel_with_planet(self, bitem: XNPlanetBuildingItem, planet_id: int): self.world.signal(self.world.SIGNAL_BUILD_CANCEL, planet_id=planet_id, bitem=bitem)
class OverviewWidget(QWidget): def __init__(self, parent=None): super(OverviewWidget, self).__init__(parent) # objects, sub-windows self.ui = None self._btn_reload = None self._aswidget = None self.world = XNovaWorld_instance() # build progress widgets self.bp_widgets = dict() # build progress widgets self.bp_widgets_sy = dict() # shipyard build progress widgets self.bp_widgets_res = dict() # researches build progress widgets def load_ui(self): # layout self._layout = QVBoxLayout() self._layout_topbuttons = QHBoxLayout() self.setLayout(self._layout) self._layout.addLayout(self._layout_topbuttons) # sub-windows # reload button self._btn_reload = QPushButton(self.tr('Refresh overview'), self) self._btn_reload.setIcon(QIcon(':i/reload.png')) self._btn_reload.clicked.connect(self.on_btn_refresh_overview) self._layout_topbuttons.addWidget(self._btn_reload) self._layout_topbuttons.addStretch() # group box to hold builds info self._gb_builds = CollapsibleFrame(self) self._gb_builds.setTitle(self.tr('Building Jobs')) self._layout.addWidget(self._gb_builds) # groupbox to hold shipyard builds info self._gb_shipyard = CollapsibleFrame(self) self._gb_shipyard.setTitle(self.tr('Shipyard Jobs')) self._layout.addWidget(self._gb_shipyard) # groupbox to hold researches in progress info self._gb_research = CollapsibleFrame(self) self._gb_research.setTitle(self.tr('Researches')) self._layout.addWidget(self._gb_research) # groupbox to hold account stats widget self._gb_accstats = CollapsibleFrame(self) self._gb_accstats.setTitle(self.tr('Statistics')) self._layout.addWidget(self._gb_accstats) # account stats widget self._aswidget = Overview_AccStatsWidget(self) self._aswidget.load_ui() self._aswidget.show() self._gb_accstats.addWidget(self._aswidget) self._gb_accstats.expand() # staticstics expanded by default # add final spacer self._layout.addStretch() def update_account_info(self): a = self.world.get_account_info() if self._aswidget is not None: self._aswidget.update_account_info(a) def get_bpw_for_planet(self, planet_id: int, typ: str = '') -> BuildProgressWidget: if typ == '': if planet_id in self.bp_widgets: return self.bp_widgets[planet_id] # create BPW for planet bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect( self.on_request_build_cancel_with_planet) self._gb_builds.addWidget(bpw) self.bp_widgets[planet_id] = bpw bpw.hide() return bpw elif typ == BuildProgressWidget.BPW_TYPE_SHIPYARD: if planet_id in self.bp_widgets_sy: return self.bp_widgets_sy[planet_id] # create BPW for planet shipyard bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect( self.on_request_build_cancel_with_planet) self._gb_shipyard.addWidget(bpw) self.bp_widgets_sy[planet_id] = bpw bpw.hide() return bpw elif typ == BuildProgressWidget.BPW_TYPE_RESEARCH: if planet_id in self.bp_widgets_res: return self.bp_widgets_res[planet_id] # create BPW for planet shipyard bpw = BuildProgressWidget(self) bpw.requestCancelBuildWithPlanet.connect( self.on_request_build_cancel_with_planet) self._gb_research.addWidget(bpw) self.bp_widgets_res[planet_id] = bpw bpw.hide() return bpw else: logger.error( 'get_bpw_for_planet(): unknown typre requested: {0}'.format( typ)) def update_builds(self): self.setUpdatesEnabled( False) # big visual changes may follow, stop screen flicker # delete existing build progress widgets (do not do it, just hide) for bpw in self.bp_widgets.values(): bpw.hide() for bpw in self.bp_widgets_sy.values(): bpw.hide() planets = self.world.get_planets() for pl in planets: # buildings bpw = self.get_bpw_for_planet(pl.planet_id) bpw.update_from_planet(pl) # shipyard if len(pl.shipyard_progress_items) > 0: bpw = self.get_bpw_for_planet( pl.planet_id, BuildProgressWidget.BPW_TYPE_SHIPYARD) bpw.show() bpw.update_from_planet(pl, BuildProgressWidget.BPW_TYPE_SHIPYARD) # researches bpw = self.get_bpw_for_planet( pl.planet_id, BuildProgressWidget.BPW_TYPE_RESEARCH) bpw.update_from_planet(pl, BuildProgressWidget.BPW_TYPE_RESEARCH) # make equal widths (this is not working, why?) # self._equalize_builds_widths() self.setUpdatesEnabled(True) def _equalize_builds_widths(self): maxwidth = -1 for bpw in self.bp_widgets: w = bpw.get_els_widths() if w > maxwidth: maxwidth = w for bpw in self.bp_widgets: w = bpw.make_as_wide_as(maxwidth) logger.debug('got max width: {0}'.format(maxwidth)) @pyqtSlot() def on_btn_refresh_overview(self): self.world.signal(self.world.SIGNAL_RELOAD_PAGE, page_name='overview') @pyqtSlot(XNPlanetBuildingItem, int) def on_request_build_cancel_with_planet(self, bitem: XNPlanetBuildingItem, planet_id: int): self.world.signal(self.world.SIGNAL_BUILD_CANCEL, planet_id=planet_id, bitem=bitem)
def auto_builder_thread(): import time from enum import IntEnum from ui.xnova.xn_data import XNPlanet, XNPlanetBuildingItem from ui.xnova.xn_world import XNovaWorld_instance, XNovaWorld from ui.xnova.xn_techtree import XNTechTree_instance from ui.xnova import xn_logger class BGid(IntEnum): METAL_FACTORY = 1 CRYSTAL_FACTORY = 2 DEIT_FACTORY = 3 SOLAR_STATION = 4 FACTORY = 14 NANITES = 15 SHIPYARD = 21 METAL_SILO = 22 CRYSTAL_SILO = 23 DEIT_SILO = 24 LAB = 31 ROCKET_SILO = 44 logger = xn_logger.get('auto_builder', debug=True) world = XNovaWorld_instance() world.script_command = 'running' WORK_INTERVAL = 145 # seconds IMPERIUM_REFRESH_INTERVAL = 300 # seconds def check_bonus(world: XNovaWorld): bonus_url = world.get_bonus_url() if bonus_url is not None: logger.info('Detected that bonus is available, get it!') world.signal(world.SIGNAL_GET_URL, url=bonus_url, referer='?set=overview') time.sleep(10) world.clear_bonus_url() time.sleep(2) def energy_need_for_gid(gid: int, level: int) -> int: if (gid == 1) or (gid == 2) or (gid == 12): e = (10 * level) * (1.1**level) return round(e) if gid == 3: e = (30 * level) * (1.1**level) return round(e) # error! incorrect gid supplied? tt = XNTechTree_instance() item = tt.find_item_by_gid(gid) s = 'Don\'t know how to calculate energy need for gid={0} "{1}" ({2})'.format( gid, item.name, item.category) logger.error(s) raise RuntimeError(s) def calc_planet_next_building(planet: XNPlanet) -> XNPlanetBuildingItem: if planet.is_moon or planet.is_base: return None met_level = 0 cry_level = 0 deit_level = 0 ss_level = 0 # met_bitem = planet.find_bitem_by_gid(int(BGid.METAL_FACTORY)) if met_bitem is not None: met_level = met_bitem.level cry_bitem = planet.find_bitem_by_gid(int(BGid.CRYSTAL_FACTORY)) if cry_bitem is not None: cry_level = cry_bitem.level deit_bitem = planet.find_bitem_by_gid(int(BGid.DEIT_FACTORY)) if deit_bitem is not None: deit_level = deit_bitem.level ss_bitem = planet.find_bitem_by_gid(int(BGid.SOLAR_STATION)) if ss_bitem is not None: ss_level = ss_bitem.level free_energy = planet.energy.energy_left # # first, check energy if free_energy <= 1: logger.info('Planet [{0}] has too low energy ({1}), must ' 'build solar station!'.format(planet.name, free_energy)) return ss_bitem # second, check robotics factory, if it is below level 10 factory_level = 0 factory_bitem = planet.find_bitem_by_gid(int(BGid.FACTORY)) if factory_bitem is not None: factory_level = factory_bitem.level if factory_bitem.level < 10: # check resources, this will build factory before any # any other building only if enough resources NOW, do not wait if (planet.res_current.met >= factory_bitem.cost_met) and \ (planet.res_current.cry >= factory_bitem.cost_cry) and \ (planet.res_current.deit >= factory_bitem.cost_deit): logger.info( 'Planet [{0}] Factory level < 10 and have res for it,' ' build Factory!'.format(planet.name)) return factory_bitem # maybe build shipyard? :) shipyard_bitem = planet.find_bitem_by_gid(int(BGid.SHIPYARD)) if shipyard_bitem is not None: if shipyard_bitem.level < factory_level: if (planet.res_current.met >= shipyard_bitem.cost_met) and \ (planet.res_current.cry >= shipyard_bitem.cost_cry) and \ (planet.res_current.deit >= shipyard_bitem.cost_deit): logger.info( 'Planet [{0}] Shipyard level < {1} and have res for it,' ' build Factory!'.format(planet.name, factory_level)) return shipyard_bitem # maybe build nanites factory? :) if factory_level >= 10: nanites_bitem = planet.find_bitem_by_gid(int(BGid.NANITES)) if nanites_bitem is not None: if (planet.res_current.met >= nanites_bitem.cost_met) and \ (planet.res_current.cry >= nanites_bitem.cost_cry) and \ (planet.res_current.deit >= nanites_bitem.cost_deit): logger.info('Planet [{0}] can build NANITES!'.format( planet.name)) return nanites_bitem # maybe build rocket silo? rs_bitem = planet.find_bitem_by_gid(int(BGid.ROCKET_SILO)) if rs_bitem is not None: if rs_bitem.level < 2: if (planet.res_current.met >= rs_bitem.cost_met) and \ (planet.res_current.cry >= rs_bitem.cost_cry) and \ (planet.res_current.deit >= rs_bitem.cost_deit): logger.info( 'Planet [{0}] can build rocket silo lv {1}'.format( planet.name, rs_bitem.level + 1)) return rs_bitem # # other resources buildings logger.info( 'Planet [{0}] m/c/d/e levels: {1}/{2}/{3}/{4} free_en: {5}'.format( planet.name, met_level, cry_level, deit_level, ss_level, free_energy)) if ss_level < met_level: return ss_bitem # # calc energy needs met_eneed = energy_need_for_gid(int(BGid.METAL_FACTORY), met_level+1) \ - energy_need_for_gid(int(BGid.METAL_FACTORY), met_level) cry_eneed = energy_need_for_gid(int(BGid.CRYSTAL_FACTORY), cry_level+1) \ - energy_need_for_gid(int(BGid.CRYSTAL_FACTORY), cry_level) deit_eneed = energy_need_for_gid(int(BGid.DEIT_FACTORY), deit_level+1) \ - energy_need_for_gid(int(BGid.DEIT_FACTORY), deit_level) logger.info('Planet [{0}] needed en: {1}/{2}/{3}'.format( planet.name, met_eneed, cry_eneed, deit_eneed)) # try to fit in energy some buildings if (met_level < ss_level) and (met_eneed <= free_energy): return met_bitem if (cry_level < (ss_level - 2)) and (cry_eneed <= free_energy): return cry_bitem if (deit_level < (ss_level - 4)) and (deit_eneed <= free_energy): return deit_bitem # # check resources storage capacity if planet.res_max_silos.met > 0: if planet.res_current.met / planet.res_max_silos.met >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.METAL_SILO)) logger.info('Planet [{0}] needs metal silo!'.format( planet.name)) return silo_bitem if planet.res_max_silos.cry > 0: if planet.res_current.cry / planet.res_max_silos.cry >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.CRYSTAL_SILO)) logger.info('Planet [{0}] needs crystal silo!'.format( planet.name)) return silo_bitem if planet.res_max_silos.deit > 0: if planet.res_current.deit / planet.res_max_silos.deit >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.DEIT_SILO)) logger.info('Planet [{0}] needs deit silo!'.format( planet.name)) return silo_bitem # # default - build solar station logger.warn( 'Planet [{0}] for some reason cannot decide what to build, ' 'will build solar station by default'.format(planet.name)) return ss_bitem def check_planet_buildings(world: XNovaWorld, planet: XNPlanet): # is there any building in progress on planet now? build_in_progress = False bitem = XNPlanetBuildingItem() for bitem_ in planet.buildings_items: if bitem_.is_in_progress(): build_in_progress = True bitem = bitem_ break if build_in_progress: logger.info( 'Planet [{0}] has still build in progress {1} lv {2}'.format( planet.name, bitem.name, bitem.level + 1)) return # no builds in progress, we can continue bitem = calc_planet_next_building(planet) if bitem is None: logger.error( 'Planet [{0}]: for some reason could not calculate ' 'next building, some internal error? Try to relogin and ' 'refresh all world.'.format(planet.name)) return logger.info('Planet [{0}] Next building will be: {1} lv {2}'.format( planet.name, bitem.name, bitem.level + 1)) logger.info('Planet [{0}] Its price: {1}m {2}c {3}d'.format( planet.name, bitem.cost_met, bitem.cost_cry, bitem.cost_deit)) logger.info('Planet [{0}] We have: {1}m {2}c {3}d'.format( planet.name, int(planet.res_current.met), int(planet.res_current.cry), int(planet.res_current.deit))) # do we have enough resources to build it? if (planet.res_current.met >= bitem.cost_met) and \ (planet.res_current.cry >= bitem.cost_cry) and \ (planet.res_current.deit >= bitem.cost_deit): logger.info( 'Planet [{0}] We have enough resources to build it, trigger!'. format(planet.name)) world.signal(world.SIGNAL_BUILD_ITEM, planet_id=planet.planet_id, bitem=bitem, quantity=0) logger.info( 'Planet [{0}] Signal to build this item has been sent to world thread, wait 10s...' .format(planet.name)) time.sleep(10) # actually wait else: logger.warn( 'Planet [{0}] We DO NOT have enough resources to build [{1} lv {2}]...' .format(planet.name, bitem.name, bitem.level + 1)) last_work_time = time.time() - WORK_INTERVAL last_imperium_refresh_time = time.time() logger.info('Started.') while True: time.sleep(1) if world.script_command == 'stop': break cur_time = time.time() if cur_time - last_work_time >= WORK_INTERVAL: last_work_time = cur_time # logger.debug('{0} seconds have passed, working...'.format(WORK_INTERVAL)) check_bonus(world) planets = world.get_planets() if len(planets) < 1: continue for planet in planets: check_planet_buildings(world, planet) time.sleep(1) if world.script_command == 'stop': break # if we didn't sleep long enough for a work_interval # refresh imperium from time to time if cur_time - last_imperium_refresh_time >= IMPERIUM_REFRESH_INTERVAL: logger.info('Time to refresh imperium...') last_imperium_refresh_time = cur_time world.signal(world.SIGNAL_RELOAD_PAGE, page_name='imperium') # while True del world.script_command logger.info('Stopped.')
def __init__(self, parent: QWidget): super(PlanetWidget, self).__init__(parent) # self.world = XNovaWorld_instance() self._planet = XNPlanet() # setup frame self.setFrameShape(QFrame.StyledPanel) self.setFrameShadow(QFrame.Raised) # layout self._layout = QVBoxLayout() self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(3) self.setLayout(self._layout) # basic info panel self._bipanel = Planet_BasicInfoPanel(self) self._bipanel.requestOpenGalaxy.connect(self.on_request_open_galaxy) self._bipanel.requestRefreshPlanet.connect( self.on_request_refresh_planet) self._bipanel.requestRenamePlanet.connect(self.on_request_rename_planet) # build progress widgets self._bpw_buildings = BuildProgressWidget(self) self._bpw_buildings.hide() self._bpw_buildings.hide_planet_name() self._bpw_buildings.layout().setContentsMargins(5, 2, 5, 2) self._bpw_shipyard = BuildProgressWidget(self) self._bpw_shipyard.hide() self._bpw_shipyard.hide_planet_name() self._bpw_shipyard.layout().setContentsMargins(5, 2, 5, 2) self._bpw_research = BuildProgressWidget(self) self._bpw_research.hide() self._bpw_research.hide_planet_name() self._bpw_research.layout().setContentsMargins(5, 2, 5, 2) # buildings self._cf_buildings = CollapsibleFrame(self) self._cf_buildings.setTitle(self.tr('Buildings')) self._sa_buildings = QScrollArea(self._cf_buildings) self._bip_buildings = Planet_BuildItemsPanel(self._sa_buildings) self._bip_buildings.set_type(Planet_BuildItemsPanel.TYPE_BUILDINGS) self._bip_buildings.show() self._sa_buildings.setWidget(self._bip_buildings) self._cf_buildings.addWidget(self._sa_buildings) # shipyard self._cf_shipyard = CollapsibleFrame(self) self._cf_shipyard.setTitle(self.tr('Shipyard')) self._sa_shipyard = QScrollArea(self._cf_shipyard) self._bip_shipyard = Planet_BuildItemsPanel(self._cf_shipyard) self._bip_shipyard.set_type(Planet_BuildItemsPanel.TYPE_SHIPYARD) self._sa_shipyard.setWidget(self._bip_shipyard) self._cf_shipyard.addWidget(self._sa_shipyard) # research self._cf_research = CollapsibleFrame(self) self._cf_research.setTitle(self.tr('Research')) self._sa_research = QScrollArea(self._cf_research) self._bip_research = Planet_BuildItemsPanel(self._cf_research) self._bip_research.set_type(Planet_BuildItemsPanel.TYPE_RESEARCHES) self._sa_research.setWidget(self._bip_research) self._cf_research.addWidget(self._sa_research) # layout finalize self._layout.addWidget(self._bipanel) self._layout.addWidget(self._bpw_buildings) self._layout.addWidget(self._bpw_shipyard) self._layout.addWidget(self._bpw_research) self._layout.addWidget(self._cf_buildings) self._layout.addWidget(self._cf_shipyard) self._layout.addWidget(self._cf_research) # expand buildings frame by default self._cf_buildings.expand() # # connect signals self._cf_buildings.expanded.connect(self.on_frame_buildings_expanded) self._cf_buildings.collapsed.connect(self.on_frame_buildings_collapsed) self._cf_shipyard.expanded.connect(self.on_frame_shipyard_expanded) self._cf_shipyard.collapsed.connect(self.on_frame_shipyard_collapsed) self._cf_research.expanded.connect(self.on_frame_research_expanded) self._cf_research.collapsed.connect(self.on_frame_research_collapsed) # self._bpw_buildings.requestCancelBuild.connect( self.on_request_cancel_build) self._bpw_research.requestCancelBuild.connect( self.on_request_cancel_build) # self._bip_buildings.requestBuildItem.connect(self.on_request_build_item) self._bip_buildings.requestDowngradeItem.connect( self.on_request_downgrade_item) self._bip_shipyard.requestBuildItem.connect(self.on_request_build_item) self._bip_research.requestBuildItem.connect(self.on_request_build_item) # # create timer self._timer = QTimer(self) self._timer.timeout.connect(self.on_timer)
def auto_builder_thread(): import time from enum import IntEnum from ui.xnova.xn_data import XNPlanet, XNPlanetBuildingItem from ui.xnova.xn_world import XNovaWorld_instance, XNovaWorld from ui.xnova.xn_techtree import XNTechTree_instance from ui.xnova import xn_logger class BGid(IntEnum): METAL_FACTORY = 1 CRYSTAL_FACTORY = 2 DEIT_FACTORY = 3 SOLAR_STATION = 4 FACTORY = 14 NANITES = 15 SHIPYARD = 21 METAL_SILO = 22 CRYSTAL_SILO = 23 DEIT_SILO = 24 LAB = 31 ROCKET_SILO = 44 logger = xn_logger.get("auto_builder", debug=True) world = XNovaWorld_instance() world.script_command = "running" WORK_INTERVAL = 145 # seconds IMPERIUM_REFRESH_INTERVAL = 300 # seconds def check_bonus(world: XNovaWorld): bonus_url = world.get_bonus_url() if bonus_url is not None: logger.info("Detected that bonus is available, get it!") world.signal(world.SIGNAL_GET_URL, url=bonus_url, referer="?set=overview") time.sleep(10) world.clear_bonus_url() time.sleep(2) def energy_need_for_gid(gid: int, level: int) -> int: if (gid == 1) or (gid == 2) or (gid == 12): e = (10 * level) * (1.1 ** level) return round(e) if gid == 3: e = (30 * level) * (1.1 ** level) return round(e) # error! incorrect gid supplied? tt = XNTechTree_instance() item = tt.find_item_by_gid(gid) s = 'Don\'t know how to calculate energy need for gid={0} "{1}" ({2})'.format(gid, item.name, item.category) logger.error(s) raise RuntimeError(s) def calc_planet_next_building(planet: XNPlanet) -> XNPlanetBuildingItem: if planet.is_moon or planet.is_base: return None met_level = 0 cry_level = 0 deit_level = 0 ss_level = 0 # met_bitem = planet.find_bitem_by_gid(int(BGid.METAL_FACTORY)) if met_bitem is not None: met_level = met_bitem.level cry_bitem = planet.find_bitem_by_gid(int(BGid.CRYSTAL_FACTORY)) if cry_bitem is not None: cry_level = cry_bitem.level deit_bitem = planet.find_bitem_by_gid(int(BGid.DEIT_FACTORY)) if deit_bitem is not None: deit_level = deit_bitem.level ss_bitem = planet.find_bitem_by_gid(int(BGid.SOLAR_STATION)) if ss_bitem is not None: ss_level = ss_bitem.level free_energy = planet.energy.energy_left # # first, check energy if free_energy <= 1: logger.info( "Planet [{0}] has too low energy ({1}), must " "build solar station!".format(planet.name, free_energy) ) return ss_bitem # second, check robotics factory, if it is below level 10 factory_level = 0 factory_bitem = planet.find_bitem_by_gid(int(BGid.FACTORY)) if factory_bitem is not None: factory_level = factory_bitem.level if factory_bitem.level < 10: # check resources, this will build factory before any # any other building only if enough resources NOW, do not wait if ( (planet.res_current.met >= factory_bitem.cost_met) and (planet.res_current.cry >= factory_bitem.cost_cry) and (planet.res_current.deit >= factory_bitem.cost_deit) ): logger.info( "Planet [{0}] Factory level < 10 and have res for it," " build Factory!".format(planet.name) ) return factory_bitem # maybe build shipyard? :) shipyard_bitem = planet.find_bitem_by_gid(int(BGid.SHIPYARD)) if shipyard_bitem is not None: if shipyard_bitem.level < factory_level: if ( (planet.res_current.met >= shipyard_bitem.cost_met) and (planet.res_current.cry >= shipyard_bitem.cost_cry) and (planet.res_current.deit >= shipyard_bitem.cost_deit) ): logger.info( "Planet [{0}] Shipyard level < {1} and have res for it," " build Factory!".format(planet.name, factory_level) ) return shipyard_bitem # maybe build nanites factory? :) if factory_level >= 10: nanites_bitem = planet.find_bitem_by_gid(int(BGid.NANITES)) if nanites_bitem is not None: if ( (planet.res_current.met >= nanites_bitem.cost_met) and (planet.res_current.cry >= nanites_bitem.cost_cry) and (planet.res_current.deit >= nanites_bitem.cost_deit) ): logger.info("Planet [{0}] can build NANITES!".format(planet.name)) return nanites_bitem # maybe build rocket silo? rs_bitem = planet.find_bitem_by_gid(int(BGid.ROCKET_SILO)) if rs_bitem is not None: if rs_bitem.level < 2: if ( (planet.res_current.met >= rs_bitem.cost_met) and (planet.res_current.cry >= rs_bitem.cost_cry) and (planet.res_current.deit >= rs_bitem.cost_deit) ): logger.info("Planet [{0}] can build rocket silo lv {1}".format(planet.name, rs_bitem.level + 1)) return rs_bitem # # other resources buildings logger.info( "Planet [{0}] m/c/d/e levels: {1}/{2}/{3}/{4} free_en: {5}".format( planet.name, met_level, cry_level, deit_level, ss_level, free_energy ) ) if ss_level < met_level: return ss_bitem # # calc energy needs met_eneed = energy_need_for_gid(int(BGid.METAL_FACTORY), met_level + 1) - energy_need_for_gid( int(BGid.METAL_FACTORY), met_level ) cry_eneed = energy_need_for_gid(int(BGid.CRYSTAL_FACTORY), cry_level + 1) - energy_need_for_gid( int(BGid.CRYSTAL_FACTORY), cry_level ) deit_eneed = energy_need_for_gid(int(BGid.DEIT_FACTORY), deit_level + 1) - energy_need_for_gid( int(BGid.DEIT_FACTORY), deit_level ) logger.info("Planet [{0}] needed en: {1}/{2}/{3}".format(planet.name, met_eneed, cry_eneed, deit_eneed)) # try to fit in energy some buildings if (met_level < ss_level) and (met_eneed <= free_energy): return met_bitem if (cry_level < (ss_level - 2)) and (cry_eneed <= free_energy): return cry_bitem if (deit_level < (ss_level - 4)) and (deit_eneed <= free_energy): return deit_bitem # # check resources storage capacity if planet.res_max_silos.met > 0: if planet.res_current.met / planet.res_max_silos.met >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.METAL_SILO)) logger.info("Planet [{0}] needs metal silo!".format(planet.name)) return silo_bitem if planet.res_max_silos.cry > 0: if planet.res_current.cry / planet.res_max_silos.cry >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.CRYSTAL_SILO)) logger.info("Planet [{0}] needs crystal silo!".format(planet.name)) return silo_bitem if planet.res_max_silos.deit > 0: if planet.res_current.deit / planet.res_max_silos.deit >= 0.7: silo_bitem = planet.find_bitem_by_gid(int(BGid.DEIT_SILO)) logger.info("Planet [{0}] needs deit silo!".format(planet.name)) return silo_bitem # # default - build solar station logger.warn( "Planet [{0}] for some reason cannot decide what to build, " "will build solar station by default".format(planet.name) ) return ss_bitem def check_planet_buildings(world: XNovaWorld, planet: XNPlanet): # is there any building in progress on planet now? build_in_progress = False bitem = XNPlanetBuildingItem() for bitem_ in planet.buildings_items: if bitem_.is_in_progress(): build_in_progress = True bitem = bitem_ break if build_in_progress: logger.info( "Planet [{0}] has still build in progress {1} lv {2}".format(planet.name, bitem.name, bitem.level + 1) ) return # no builds in progress, we can continue bitem = calc_planet_next_building(planet) if bitem is None: logger.error( "Planet [{0}]: for some reason could not calculate " "next building, some internal error? Try to relogin and " "refresh all world.".format(planet.name) ) return logger.info("Planet [{0}] Next building will be: {1} lv {2}".format(planet.name, bitem.name, bitem.level + 1)) logger.info( "Planet [{0}] Its price: {1}m {2}c {3}d".format( planet.name, bitem.cost_met, bitem.cost_cry, bitem.cost_deit ) ) logger.info( "Planet [{0}] We have: {1}m {2}c {3}d".format( planet.name, int(planet.res_current.met), int(planet.res_current.cry), int(planet.res_current.deit) ) ) # do we have enough resources to build it? if ( (planet.res_current.met >= bitem.cost_met) and (planet.res_current.cry >= bitem.cost_cry) and (planet.res_current.deit >= bitem.cost_deit) ): logger.info("Planet [{0}] We have enough resources to build it, trigger!".format(planet.name)) world.signal(world.SIGNAL_BUILD_ITEM, planet_id=planet.planet_id, bitem=bitem, quantity=0) logger.info( "Planet [{0}] Signal to build this item has been sent to world thread, wait 10s...".format(planet.name) ) time.sleep(10) # actually wait else: logger.warn( "Planet [{0}] We DO NOT have enough resources to build [{1} lv {2}]...".format( planet.name, bitem.name, bitem.level + 1 ) ) last_work_time = time.time() - WORK_INTERVAL last_imperium_refresh_time = time.time() logger.info("Started.") while True: time.sleep(1) if world.script_command == "stop": break cur_time = time.time() if cur_time - last_work_time >= WORK_INTERVAL: last_work_time = cur_time # logger.debug('{0} seconds have passed, working...'.format(WORK_INTERVAL)) check_bonus(world) planets = world.get_planets() if len(planets) < 1: continue for planet in planets: check_planet_buildings(world, planet) time.sleep(1) if world.script_command == "stop": break # if we didn't sleep long enough for a work_interval # refresh imperium from time to time if cur_time - last_imperium_refresh_time >= IMPERIUM_REFRESH_INTERVAL: logger.info("Time to refresh imperium...") last_imperium_refresh_time = cur_time world.signal(world.SIGNAL_RELOAD_PAGE, page_name="imperium") # while True del world.script_command logger.info("Stopped.")
from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova import xn_logger logger = xn_logger.get('test01_stopper', debug=True) world = XNovaWorld_instance() try: existing = world.script_command # if this fails, no such member exists, an exception will be raised # else, continue # world.script_test01_command = 'stop' world.script_command = 'stop' # world.script_test01_command = 'pn' logger.info('sent "stop" command to scripts.') except AttributeError as ea: logger.info('probably script is not running.') pass
from ui.xnova.xn_world import XNovaWorld_instance from ui.xnova.xn_data import XNPlanet, XNPlanetBuildingItem from ui.xnova import xn_logger logger = xn_logger.get('test01_stopper', debug=True) world = XNovaWorld_instance() def energy_need_for_gid(gid: int, level: int) -> int: if (gid == 1) or (gid == 2) or (gid == 12): e = (10 * level) * (1.1 ** level) return round(e) if gid == 3: e = (30 * level) * (1.1 ** level) return round(e) return -1 try: planets = world.get_planets() if len(planets) > 0: planet = planets[0] for bitem in planet.buildings_items: e = energy_need_for_gid(bitem.gid, bitem.level) if e != -1: print('{0} lv {1} need {2} energy'.format(bitem.name, bitem.level, e)) except Exception as ex: logger.exception('Exception happened')