def _update_manifest():
    logger.debug("Updating manifest.db")
    manifest_response = cgss_query.get_manifests()

    with storage.get_writer(MANIFEST_PATH, 'wb') as fwb:
        fwb.write(decompress(manifest_response.content))
    logger.info("manifest.db updated")
 def decorate(*args, **kwargs):
     res = f(*args, **kwargs)
     if not os.path.exists(TEMP_PATH):
         logger.info("Failed to run CGSS API")
     else:
         os.remove(TEMP_PATH)
     return res
Esempio n. 3
0
def update_potential(chara_id, pots):
    assert len(pots) == 5
    db.cachedb.execute(
        """
        INSERT OR REPLACE INTO potential_cache (chara_id, vo, vi, da, li, sk)
        VALUES (?,?,?,?,?,?)
    """, [int(chara_id)] + list(map(int, pots)))
    copy_card_data_from_master(update_all=False, chara_id=chara_id)
    logger.info("Updated character ID {} to pots {}".format(chara_id, pots))
Esempio n. 4
0
def main():
    logger.info("Starting virtual Chihiro...")

    sys.excepthook = excepthook
    initializer.setup(True)
    from gui.main import setup_gui

    app, main = setup_gui(sys.argv)
    main.show()
    app.exec_()
Esempio n. 5
0
 def set_unit(self, cards, row=None):
     if row is None:
         row = self.widget.rowCount() - 1
     for idx, card in enumerate(cards):
         if card is None:
             continue
         self.widget.cellWidget(row, 0).set_card(idx=idx, card=card)
     logger.info("Unit insert: {} - {} row {}".format(
         self.widget.cellWidget(row, 0).get_short_uuid(),
         " ".join(map(str, cards)), row))
Esempio n. 6
0
 def setup_ui(self):
     logger.info("Initializing UI")
     self.main.resize(1850, 1000)
     self.setup_base()
     self.setup_calculator_song_layout()
     self.setup_card_unit_layout()
     self.setup_tip_view()
     self.main.setCentralWidget(self.central_widget)
     self.retranslate_ui(self.main)
     QMetaObject.connectSlotsByName(self.main)
Esempio n. 7
0
    def setup_calculator_song_layout(self):
        logger.info("Setting up calculator and song layouts")

        self.calculator_song_layout = QHBoxLayout()
        self.calculator = QTabWidget(self.central_widget)
        self.calculator_view = MainView()
        self.calculator_model = MainModel(self.calculator_view)
        self.calculator_view.set_model(self.calculator_model)
        self.calculator_view.setup()
        self.potential_view = PotentialView()
        self.potential_model = PotentialModel(self.potential_view)
        self.potential_view.set_model(self.potential_model)
        self.potential_model.initialize_data()
        self.calculator.addTab(self.calculator_view.widget, "Simulator")
        self.calculator.addTab(self.potential_view.widget, "Potentials")
        self.calculator_song_layout.addWidget(self.calculator)
        self.song_layout = QVBoxLayout()

        self.import_layout = QHBoxLayout()
        self.import_text = QLineEdit(self.main)
        self.import_text.setPlaceholderText(
            "Input user ID (9 digits, e.g. 123456789)")
        self.import_text.setValidator(QIntValidator(
            0, 999999999, None))  # Only number allowed
        self.import_button = QPushButton("Import from ID", self.main)
        self.import_button.pressed.connect(
            lambda: self.import_from_id(self.import_text.text()))
        self.import_layout.addWidget(self.import_text)
        self.import_layout.addWidget(self.import_button)
        self.song_layout.addLayout(self.import_layout)

        self.song_view = SongView(self.central_widget)
        self.song_model = SongModel(self.song_view)
        self.song_model.initialize_data()
        self.song_view.set_model(self.song_model)
        self.song_layout.addWidget(self.song_view.widget)
        self.songsearch_view = SongQuickSearchView(self.central_widget,
                                                   self.song_model)
        self.songsearch_model = SongQuickSearchModel(self.songsearch_view,
                                                     self.song_view)
        self.songsearch_view.set_model(self.songsearch_model)
        hl = QHBoxLayout()
        hl.addWidget(self.songsearch_view.widget)
        chart_viewer_button = QPushButton("Popup Chart Viewer")
        hl.addWidget(chart_viewer_button)
        chart_viewer_button.pressed.connect(lambda: eventbus.eventbus.post(
            PopupChartViewerEvent(look_for_chart=True)))
        self.song_layout.addLayout(hl)

        self.calculator_song_layout.addLayout(self.song_layout)
        self.calculator_song_layout.setStretch(0, 3)
        self.calculator_song_layout.setStretch(1, 2)
        self.main_layout.addLayout(self.calculator_song_layout)
        self.calculator.setCurrentIndex(0)
 def __init__(self):
     if not PROFILE_PATH.exists():
         PROFILE_PATH.mkdir()
     db.cachedb.execute("""
         CREATE TABLE IF NOT EXISTS profiles (
             "name" TEXT UNIQUE
         )
     """)
     db.cachedb.commit()
     if not self.switch_profile('main'):
         logger.info("No profile found, creating default profile")
         self.add_profile('main')
         self.switch_profile('main')
     self.profile = 'main'
def update_all(sleep=0.1):
    logger.info("Updating images, please wait...")
    _try_extract_cache()
    if not IMAGE_PATH64.exists():
        IMAGE_PATH64.mkdir()
    if not IMAGE_PATH32.exists():
        IMAGE_PATH32.mkdir()
    card_data = _base_query("list/card_t")['result']
    logger.debug("Getting icons for {} cards".format(len(card_data)))
    card_ids = [int(card['id']) for card in card_data]
    card_ids_plus = [_ + 1 for _ in card_ids]
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        for card_id in card_ids + card_ids_plus:
            executor.submit(update_image, card_id, sleep)
Esempio n. 10
0
    def simulate(self, row=None):
        score_id, diff_id, live_detail_id, _, _ = eventbus.eventbus.post_and_get_first(
            GetSongDetailsEvent())
        if diff_id is None:
            logger.info("No chart loaded")
            return
        times = self.get_times()
        all_cards: List[
            CardsWithUnitUuid] = eventbus.eventbus.post_and_get_first(
                GetAllCardsEvent(self.get_current_model(), row),
                required_non_none=True)
        perfect_play = eventbus.eventbus.post_and_get_first(
            GetPerfectPlayFlagEvent())
        custom_pots = eventbus.eventbus.post_and_get_first(
            GetCustomPotsEvent())
        appeals = eventbus.eventbus.post_and_get_first(GetAppealsEvent())
        support = eventbus.eventbus.post_and_get_first(GetSupportEvent())
        mirror = eventbus.eventbus.post_and_get_first(GetMirrorFlagEvent())
        doublelife = eventbus.eventbus.post_and_get_first(
            GetDoublelifeFlagEvent())
        autoplay = eventbus.eventbus.post_and_get_first(GetAutoplayFlagEvent())
        autoplay_offset = eventbus.eventbus.post_and_get_first(
            GetAutoplayOffsetEvent())
        extra_bonus, special_option, special_value = eventbus.eventbus.post_and_get_first(
            GetCustomBonusEvent())
        left_inclusive, right_inclusive = eventbus.eventbus.post_and_get_first(
            GetSkillBoundaryEvent())
        theoretical_simulation = eventbus.eventbus.post_and_get_first(
            GetTheoreticalMaxFlagEvent())

        self.model.simulate_internal(
            perfect_play=perfect_play,
            left_inclusive=left_inclusive,
            right_inclusive=right_inclusive,
            theoretical_simulation=theoretical_simulation,
            score_id=score_id,
            diff_id=diff_id,
            times=times,
            all_cards=all_cards,
            custom_pots=custom_pots,
            appeals=appeals,
            support=support,
            extra_bonus=extra_bonus,
            special_option=special_option,
            special_value=special_value,
            mirror=mirror,
            autoplay=autoplay,
            autoplay_offset=autoplay_offset,
            doublelife=doublelife,
            row=row)
def _update_masterdb():
    logger.debug("Updating master.db")
    manifest_conn = sqlite3.connect(get_manifestdb_path())
    manifest_c = manifest_conn.cursor()

    manifest_c.execute('SELECT hash FROM manifests WHERE name="master.mdb"')
    master_hash = manifest_c.fetchone()[0]
    master_response = cgss_query.get_db(master_hash)

    with storage.get_writer(MASTERDB_PATH, 'wb') as fwb:
        fwb.write(decompress(master_response.content))
    manifest_c.close()
    manifest_conn.close()
    logger.info("master.db updated")
Esempio n. 12
0
 def keyPressEvent(self, event):
     key = event.key()
     if QApplication.keyboardModifiers(
     ) == Qt.ControlModifier and key == Qt.Key_F:
         self.ui.quicksearch_view.focus()
     if QApplication.keyboardModifiers(
     ) == Qt.ControlModifier and key == Qt.Key_S:
         logger.info("User data backed up")
         unit_storage.clean_all_units(grand=False)
         for r_idx in range(self.ui.unit_view.widget.count()):
             widget = self.ui.unit_view.widget.itemWidget(
                 self.ui.unit_view.widget.item(r_idx))
             widget.update_unit()
         profile_manager.cleanup()
Esempio n. 13
0
 def push_card(self, idx, skip_guest_push=False):
     count = 0
     cell_widget = None
     for row in range(self.view.widget.rowCount()):
         if self.view.widget.isRowHidden(row):
             continue
         if count == idx:
             cell_widget = self.view.widget.item(row, 2)
             break
         else:
             count += 1
     if cell_widget is None:
         logger.info("No card at index {}".format(idx))
         return
     eventbus.eventbus.post(PushCardEvent(int(cell_widget.text()), skip_guest_push))
Esempio n. 14
0
def setup_gui(*args):
    app = QApplication(*args)
    app.setApplicationName("Chihiro")
    icon = QIcon(str(ROOT_DIR / 'icon.png'))
    app.setWindowIcon(icon)
    app.lastWindowClosed.connect(lambda: cleanup())
    import ctypes
    myappid = 'mycompany.myproduct.subproduct.version'  # arbitrary string
    ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
    MainWindow = CustomMainWindow()
    ui = UiMainWindow(MainWindow)
    MainWindow.setui(ui)
    ui.setup_ui()
    ui.disable_auto_resize()
    logger.info("GUI setup successfully")
    return app, MainWindow
Esempio n. 15
0
def update_owned_cards(card_ids, numbers):
    logger.info("Updating cards: {}".format(card_ids))
    if not isinstance(card_ids, list) or not isinstance(numbers, list):
        card_ids = [card_ids]
        numbers = [numbers]
    assert len(card_ids) == len(numbers)
    for card_id, number in zip(card_ids, numbers):
        db.cachedb.execute(
            """
            INSERT OR REPLACE INTO owned_card (card_id, number)
            VALUES (?,?)
        """, [card_id, number])
    db.cachedb.commit()
    from logic.search import indexer, search_engine
    indexer.im.initialize_index_db(card_ids)
    indexer.im.reindex(card_ids)
    search_engine.engine.refresh_searcher()
Esempio n. 16
0
    def load_data(self, data, card_list=None):
        if card_list is None:
            self.widget.setColumnCount(len(data[0]) + 2)
            self.widget.horizontalHeader().setSectionResizeMode(1, 2)  # Not allow change icon column size
            self.widget.setRowCount(len(data))
            self.widget.setHorizontalHeaderLabels(['#', ''] + list(data[0].keys()))
            rows = range(len(data))
        else:
            data_dict = {int(_['ID']): _ for _ in data}
            rows = dict()
            for r_idx in range(self.widget.rowCount()):
                card_id = int(self.widget.item(r_idx, 2).text())
                if card_id not in data_dict:
                    continue
                else:
                    rows[card_id] = r_idx
            rows = [rows[card_id] for card_id in map(int, card_list)]
            data = [data_dict[card_id] for card_id in map(int, card_list)]

        # Turn off sorting to avoid indices changing mid-update
        self.widget.setSortingEnabled(False)
        for r_idx, card_data in zip(rows, data):
            row_count_item = NumericalTableWidgetItem(r_idx + 1)
            row_count_item.setFlags(row_count_item.flags() & ~Qt.ItemIsEditable)
            self.widget.setItem(r_idx, 0, row_count_item)
            for c_idx, (key, value) in enumerate(card_data.items()):
                if isinstance(value, int):
                    item = NumericalTableWidgetItem(value)
                elif value is None:
                    item = QTableWidgetItem("")
                else:
                    item = QTableWidgetItem(str(value))
                if c_idx != 1:
                    item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                else:
                    item = QTableWidgetItem()
                    item.setData(Qt.EditRole, value)
                if key == 'Skill' and value is not None:
                    item.setBackground(QColor(*SKILL_COLOR_BY_NAME[value], 135))
                if key == 'Color' and value is not None:
                    item.setBackground(QColor(*CARD_GUI_COLORS[value], 100))
                self.widget.setItem(r_idx, c_idx + 2, item)
        logger.info("Loaded {} cards".format(len(data)))
        self.widget.setSortingEnabled(True)
        # Turn on auto fit once to make it look better then turn it off to render faster during resize
        self.toggle_auto_resize(card_list is None)
Esempio n. 17
0
 def load_images(self, size=None):
     logger.info("Card list thumbnail size: {}".format(size))
     if size is None:
         self.images = dict()
         self.view.draw_icons(None, size)
         return
     if size is not None:
         assert size == 32 or size == 64 or size == 124
         if size == 32:
             path = IMAGE_PATH32
         elif size == 64:
             path = IMAGE_PATH64
         elif size == 124:
             path = IMAGE_PATH
         for image_path in path.iterdir():
             self.images[image_path.name.split(".")[0]] = image_path
         self.view.draw_icons(self.images, size)
def update_musicscores():
    logger.debug("Updating all musicscores")
    if not storage.exists(MANIFEST_PATH):
        logger.debug("manifest.db not found, updating metadata")
        meta_updater.update_database()
    with db.CustomDB(meta_updater.get_manifestdb_path()) as manifest_conn:
        all_musicscores = manifest_conn.execute_and_fetchall("""
            SELECT name,hash FROM manifests WHERE (name LIKE "musicscores\_m___.bdb" ESCAPE '\\')
            """)
        all_musicscores = {_[0].split(".")[0]: _[1] for _ in all_musicscores}

    if not _score_cache_db_exists():
        _initialize_score_cache_db()
        new_scores = all_musicscores.keys()
        updated_scores = set()
    else:
        scores_meta = db.cachedb.execute_and_fetchall(
            "SELECT score_id, score_hash FROM score_cache")
        scores_meta = {_: __ for _, __ in scores_meta}
        deleted_scores = set(scores_meta.keys()).difference(
            all_musicscores.keys())
        if len(deleted_scores) > 0:
            logger.info(
                "Found {} defunct musicscores, removing them...".format(
                    len(deleted_scores)))
            for deleted_score in deleted_scores:
                path = MUSICSCORES_PATH / "{}.db".format(deleted_score)
                path.unlink()
        new_scores = set(all_musicscores.keys()).difference(scores_meta.keys())
        updated_scores = [
            _ for _ in set(all_musicscores.keys()).intersection(
                scores_meta.keys()) if scores_meta[_] != all_musicscores[_]
        ]
    logger.info(
        "Found {} musicscores, {} of them are new, {} are updated...".format(
            len(all_musicscores), len(new_scores), len(updated_scores)))

    if len(new_scores) + len(updated_scores) > 50:
        logger.info("It will take some time to download, please wait...")

    for musicscore_name in set(new_scores).union(set(updated_scores)):
        musicscore_hash = all_musicscores[musicscore_name]
        musicscore_response = cgss_query.get_db(musicscore_hash)
        with storage.get_writer(
                MUSICSCORES_PATH / "{}.db".format(musicscore_name),
                'wb') as fwb:
            fwb.write(decompress(musicscore_response.content))
        db.cachedb.execute(
            """
            INSERT OR REPLACE INTO score_cache (score_id, score_hash)
            VALUES (?,?)
        """, [musicscore_name, musicscore_hash])
    db.cachedb.commit()
    logger.info("All musicscores updated")
Esempio n. 19
0
 def get_all_cards(self, event):
     if event.model is not self:
         return
     res = list()
     rows_to_search = range(
         self.view.widget.rowCount()) if event.row is None else [event.row]
     for r_idx in rows_to_search:
         unit_widget = self.view.widget.cellWidget(r_idx, 0)
         if unit_widget.running_simulation:
             logger.info("Simulation already running: {}".format(
                 unit_widget.get_uuid()))
             continue
         unit_widget.toggle_running_simulation(True)
         res.append(
             CardsWithUnitUuid(
                 self.view.widget.cellWidget(r_idx, 0).get_uuid(),
                 self.view.widget.cellWidget(r_idx, 0).get_short_uuid(),
                 self.view.widget.cellWidget(r_idx, 0).cards_internal))
     return res
Esempio n. 20
0
 def create_support_team(self, r):
     if not eventbus.eventbus.post_and_get_first(
             SetSupportCardsEvent(
                 self.widget.cellWidget(r, 0).cards_internal)):
         logger.info("Invalid unit to evaluate support team")
         return
     appeals, support, life = eventbus.eventbus.post_and_get_first(
         RequestSupportTeamEvent())
     self.widget.setItem(r, 2, NumericalTableWidgetItem(int(life)))
     total_appeals = eventbus.eventbus.post_and_get_first(GetAppealsEvent())
     if total_appeals is not None:
         self.widget.setItem(r, 1, NumericalTableWidgetItem(total_appeals))
         return
     custom_support = eventbus.eventbus.post_and_get_first(
         GetSupportEvent())
     if custom_support is not None:
         support = custom_support
     self.widget.setItem(r, 1,
                         NumericalTableWidgetItem(int(appeals + support)))
def import_from_gameid(game_id):
    try:
        assert len(str(game_id)) == 9
        z = int(game_id)
        assert 0 <= z <= 999999999
        logger.info(
            "Trying to import from ID {}, this might take a while".format(
                game_id))
        cards = list(map(int, get_cards(game_id)))
        for idx, card in enumerate(cards):
            if card % 2 == 1:
                cards[idx] += 1
        card_dict = defaultdict(int)
        for card in cards:
            card_dict[card] += 1
        for card_id, number in card_dict.items():
            z = list(
                zip(*db.cachedb.execute_and_fetchall(
                    "SELECT number FROM owned_card WHERE card_id = ? OR card_id = ?",
                    [card_id, card_id - 1])))[0]
            if z[0] + z[1] < number:
                db.cachedb.execute(
                    """
                    INSERT OR REPLACE INTO owned_card (card_id, number)
                    VALUES (?,?)
                """, [card_id, number - z[0]])
        db.cachedb.commit()
        logger.info("Imported {} cards successfully".format(len(card_dict)))
        return list(card_dict.keys())
    except:
        logger.debug(traceback.print_exc())
        logger.info("Failed to import cards")
Esempio n. 22
0
 def load_data(self, data):
     DATA_COLS = ["LDID", "LiveID", "DifficultyInt", "ID", "Name", "Color", "Difficulty", "Level", "Duration (s)",
                  "Note Count", "Tap", "Long", "Flick", "Slide", "Tap %", "Long %", "Flick %", "Slide %"]
     self.widget.setColumnCount(len(DATA_COLS))
     self.widget.setRowCount(len(data))
     self.widget.setHorizontalHeaderLabels(DATA_COLS)
     self.widget.setSortingEnabled(True)
     for r_idx, card_data in enumerate(data):
         for c_idx, (key, value) in enumerate(card_data.items()):
             if isinstance(value, int) and 13 >= c_idx >= 7 or c_idx == 1:
                 item = NumericalTableWidgetItem(value)
             elif value is None:
                 item = QTableWidgetItem("")
             else:
                 item = QTableWidgetItem(str(value))
             self.widget.setItem(r_idx, c_idx, item)
     logger.info("Loaded {} charts".format(len(data)))
     self.widget.setColumnHidden(0, True)
     self.widget.setColumnHidden(2, True)
     self.widget.setSortingEnabled(True)
     self.widget.sortItems(3, Qt.AscendingOrder)
     self.toggle_percentage(change=False)
     self.toggle_auto_resize(True)
Esempio n. 23
0
 def handle_simulation_request(self, event: SimulationEvent):
     event.live.set_unit(event.unit)
     if event.autoplay:
         logger.info("Simulation mode: Autoplay - {} - {}".format(
             event.short_uuid, event.unit))
         sim = Simulator(event.live, special_offset=0.075)
         result = sim.simulate_auto(appeals=event.appeals,
                                    extra_bonus=event.extra_bonus,
                                    support=event.support,
                                    special_option=event.special_option,
                                    special_value=event.special_value,
                                    time_offset=event.autoplay_offset,
                                    mirror=event.mirror,
                                    doublelife=event.doublelife)
     else:
         if event.perfect_play:
             logger.info("Simulation mode: Perfect - {} - {}".format(
                 event.short_uuid, event.unit))
         else:
             logger.info("Simulation mode: Normal - {} - {}".format(
                 event.short_uuid, event.unit))
         sim = Simulator(event.live,
                         left_inclusive=event.left_inclusive,
                         right_inclusive=event.right_inclusive)
         result = sim.simulate(perfect_play=event.perfect_play,
                               times=event.times,
                               appeals=event.appeals,
                               extra_bonus=event.extra_bonus,
                               support=event.support,
                               special_option=event.special_option,
                               special_value=event.special_value,
                               doublelife=event.doublelife)
         if event.theoretical_simulation:
             result.max_theoretical_result = sim.simulate_theoretical_max(
                 appeals=event.appeals,
                 extra_bonus=event.extra_bonus,
                 support=event.support,
                 special_option=event.special_option,
                 special_value=event.special_value,
                 doublelife=event.doublelife)
     self.process_simulation_results_signal.emit(
         BaseSimulationResultWithUuid(event.uuid, result, event.abuse_load))
Esempio n. 24
0
    def setup_card_unit_layout(self):
        logger.info("Setting up card and unit layouts")

        self.card_unit_layout = QHBoxLayout()
        self.card_layout = QVBoxLayout()
        self.card_quicksearch_layout = QHBoxLayout()

        self.quicksearch_layout = QHBoxLayout()

        # Set up card MV first
        self.card_view = CardView(self.central_widget)
        self.card_model = CardModel(self.card_view)
        self.card_view.set_model(self.card_model)
        self.card_model.initialize_cards()
        self.card_view.initialize_pics()
        self.card_view.connect_cell_change()
        self.card_layout.addWidget(self.card_view.widget)

        # Need card view
        self.quicksearch_view = QuickSearchView(self.central_widget,
                                                self.card_model)
        self.quicksearch_model = QuickSearchModel(self.quicksearch_view,
                                                  self.card_view)
        self.quicksearch_view.set_model(self.quicksearch_model)
        self.card_quicksearch_layout.addLayout(self.quicksearch_layout)
        self.quicksearch_layout.addWidget(self.quicksearch_view.widget)
        self.highlight_checkbox = QCheckBox(self.central_widget)
        self.highlight_checkbox.setText("Highlight Carnival Idols")
        self.highlight_checkbox.clicked.connect(
            lambda _: self.card_model.highlight_event_cards(_))
        self.quicksearch_layout.addWidget(self.highlight_checkbox)
        self.quicksearch_model.add_options(self.quicksearch_layout,
                                           self.central_widget)

        # Then icon loader MV since it makes use of the card model
        self.icon_loader_view = IconLoaderView(self.central_widget)
        self.icon_loader_model = IconLoaderModel(self.icon_loader_view,
                                                 self.card_model)
        self.icon_loader_view.set_model(self.icon_loader_model)
        self.icon_loader_view.widget.setToolTip(
            "Larger icons require more RAM to run.")
        self.icon_loader_model.load_image(0)
        self.card_quicksearch_layout.addWidget(self.icon_loader_view.widget)
        self.card_layout.addLayout(self.card_quicksearch_layout)

        self.card_layout.setStretch(1, 1)

        self.unit_layout = QVBoxLayout()
        self.unit_view = UnitView(self.central_widget)
        self.unit_model = UnitModel(self.unit_view)
        self.unit_view.set_model(self.unit_model)
        self.unit_model.initialize_units()
        self.unit_layout.addWidget(self.unit_view.widget)

        self.card_unit_layout.addLayout(self.unit_layout)
        self.card_unit_layout.addLayout(self.card_layout)

        self.add_unit_button = QPushButton()
        self.add_unit_button.setText("Add unit")
        self.add_unit_button.setToolTip(
            "Add an untitled unit. Untitled units are not saved upon exit!\n"
            "Make sure to give your units a name. Unit names must be different.\n"
            "First/Red card is the leader, last/blue card is the guest.")
        self.add_unit_button.clicked.connect(
            lambda: self.unit_view.add_empty_widget())
        self.unit_layout.addWidget(self.add_unit_button)

        self.card_unit_layout.setStretch(0, 1)
        self.card_unit_layout.setStretch(1, 2)
        self.main_layout.addLayout(self.card_unit_layout)
        self.grid_layout.addLayout(self.main_layout, 0, 0, 1, 1)
Esempio n. 25
0
    def setup_base(self):
        logger.info("Setting up UI base")

        self.central_widget = QWidget(self.main)
        self.grid_layout = QGridLayout(self.central_widget)
        self.main_layout = QVBoxLayout()
Esempio n. 26
0
    def simulate_internal(self,
                          perfect_play,
                          left_inclusive,
                          right_inclusive,
                          theoretical_simulation,
                          score_id,
                          diff_id,
                          times,
                          all_cards,
                          custom_pots,
                          appeals,
                          support,
                          extra_bonus,
                          special_option,
                          special_value,
                          mirror,
                          autoplay,
                          autoplay_offset,
                          doublelife,
                          row=None):
        """
        :type all_cards: List[CardsWithUnitUuid]
        """
        results = list()
        if len(all_cards) == 0:
            logger.info("Nothing to simulate")
            return
        extra_return = None

        # Initialize song first because SQLite DB thread lock
        # Live objects are mutable so create one for each simulation
        # TODO: Minor optimize by calling set_music only once then clone, but set_music shouldn't take too long to run so this is on low priority
        live_objects = list()
        for card_with_uuid in all_cards:
            cards = card_with_uuid.cards
            if len(cards) == 15:
                live = GrandLive()
            else:
                live = Live()
            live.set_music(score_id=score_id, difficulty=diff_id)
            groove_song_color = eventbus.eventbus.post_and_get_first(
                GetGrooveSongColor())
            if groove_song_color is not None:
                live.color = groove_song_color
            live_objects.append(live)

        # Load cards
        for live, card_with_uuid in zip(live_objects, all_cards):
            cards = card_with_uuid.cards
            try:
                if len(cards) == 15:
                    unit = GrandUnit.from_list(cards, custom_pots)
                else:
                    if cards[5] is None:
                        cards = cards[:5]
                    unit = Unit.from_list(cards, custom_pots)
            except InvalidUnit:
                logger.info("Invalid unit: {}".format(cards))
                results.append(None)
                continue

            eventbus.eventbus.post(SimulationEvent(
                card_with_uuid.uuid, card_with_uuid.short_uuid, row is not None
                and theoretical_simulation, appeals, autoplay, autoplay_offset,
                doublelife, extra_bonus, extra_return, live, mirror,
                perfect_play, results, special_option, special_value, support,
                times, unit, left_inclusive, right_inclusive,
                theoretical_simulation),
                                   high_priority=True,
                                   asynchronous=True)
Esempio n. 27
0
    def initialize_index_db(self, card_list=None):
        logger.info("Building quicksearch index, please wait...")

        carnival_idols = ",".join(
            map(str, Live.static_get_chara_bonus_set(get_name=False)))

        db.cachedb.execute("""ATTACH DATABASE "{}" AS masterdb""".format(
            get_masterdb_path()))
        query = """
            SELECT  cdc.id,
                    LOWER(cnc.card_short_name) as short,
                    oc.number as owned,
                    LOWER(cc.full_name) as chara,
                    LOWER(rt.text) as rarity,
                    LOWER(ct.text) as color,
                    CASE 
                        WHEN cdc.rarity % 2 == 0 THEN 1
                        ELSE 0
                    END idolized,
                    CASE 
                        WHEN pk.id IS NOT NULL THEN sd.condition || pk.short ELSE '' 
                    END time_prob_key, 
                    IFNULL(LOWER(sk.keywords), "") as skill,
                    IFNULL(LOWER(lk.keywords), "") as leader,
                    CASE
                        WHEN cdc.leader_skill_id IN (70,71,72,73,81,82,83,84,104,105,106,113,117,118)
                        AND cdc.rarity > 6 
                        THEN "fes" 
                        ELSE ""
                    END fes,
                    CASE
                        WHEN cdc.leader_skill_id IN (70,71,72,73,81,82,83,84,104,105,106,113,117)
                        AND cdc.rarity > 6 
                        THEN "blanc"
                        ELSE ""
                    END blanc,
                    CASE
                        WHEN cdc.leader_skill_id IN (118)
                        AND cdc.rarity > 6 
                        THEN "noir"
                        ELSE ""
                    END noir,
                    CASE
                        WHEN cdc.chara_id IN ({})
                        THEN "carnival"
                        ELSE ""
                    END carnival,
                    CASE
                        WHEN 1.0 * cdc.vocal_min / (cdc.vocal_min + cdc.visual_min + cdc.dance_min) > 0.39 
                        THEN "vocal" 
                        WHEN 1.0 * cdc.visual_min / (cdc.vocal_min + cdc.visual_min + cdc.dance_min) > 0.39 
                        THEN "visual"
                        WHEN 1.0 * cdc.dance_min / (cdc.vocal_min + cdc.visual_min + cdc.dance_min) > 0.39 
                        THEN "dance"
                        ELSE "balance"
                    END main_attribute
            FROM card_data_cache as cdc
            INNER JOIN card_name_cache cnc on cdc.id = cnc.card_id
            INNER JOIN owned_card oc on oc.card_id = cnc.card_id
            INNER JOIN chara_cache cc on cdc.chara_id = cc.chara_id
            INNER JOIN rarity_text rt on cdc.rarity = rt.id
            INNER JOIN color_text ct on cdc.attribute = ct.id
            LEFT JOIN masterdb.skill_data sd on cdc.skill_id = sd.id
            LEFT JOIN probability_keywords pk on pk.id = sd.probability_type
            LEFT JOIN skill_keywords sk on sd.skill_type = sk.id
            LEFT JOIN leader_keywords lk on cdc.leader_skill_id = lk.id
        """.format(carnival_idols)
        if card_list is not None:
            query += "WHERE cdc.id IN ({})".format(','.join(['?'] *
                                                            len(card_list)))
            data = db.cachedb.execute_and_fetchall(query,
                                                   card_list,
                                                   out_dict=True)
        else:
            data = db.cachedb.execute_and_fetchall(query, out_dict=True)
            db.cachedb.execute("DROP TABLE IF EXISTS card_index_keywords")
            db.cachedb.execute("""
                CREATE TABLE IF NOT EXISTS card_index_keywords (
                    "card_id" INTEGER UNIQUE PRIMARY KEY,
                    "fields" BLOB
                )
            """)
        logger.debug("Initializing quicksearch db for {} cards".format(
            len(data)))
        for card in data:
            card_id = card['id']
            fields = {_: card[_] for _ in KEYWORD_KEYS}
            db.cachedb.execute(
                """
                    INSERT OR REPLACE INTO card_index_keywords ("card_id", "fields")
                    VALUES (?,?)
                """, [card_id, str(fields)])
        db.cachedb.commit()
        logger.debug(
            "Quicksearch db transaction for {} cards completed".format(
                len(data)))
        db.cachedb.execute("DETACH DATABASE masterdb")
Esempio n. 28
0
def main_cleanup():
    logger.info("Virtual Chihiro going back to sleep...")
Esempio n. 29
0
def cleanup():
    logger.info("Waiting for all threads to finish...")
    kill_tip_refresher_service()