Example #1
0
def context():
    """A context instance."""
    return Context(
        artists=[
            Artist("artist1"),
            Artist("artist2"),
        ],
        tasks=[
            Task("0010", 1),
            Task("0020", 2),
            Task("0030", 3),
        ],
    )
Example #2
0
def test_import_assignments_to_csv(tmpdir):
    """Ensure we can import a list of assignments to a .csv file."""
    path = os.path.join(tmpdir, "artists.csv")
    with open(path, "w") as stream:
        stream.write("0010,Artist1\n0020,Artist2\n")

    artist1 = Artist("Artist1")
    artist2 = Artist("Artist2")
    task1 = Task("0010", 1)
    task2 = Task("0020", 2)
    context = Context(
        artists=[artist1, artist2],
        tasks=[task1, task2],
    )

    actual = _io.import_assignments_from_csv(context, path)
    assert actual == [Assignment(artist1, task1), Assignment(artist2, task2)]
Example #3
0
    def __init__(self, context: Context, auto_solve=False):
        super().__init__()
        self.context = context  # type: Context
        self.assignments = ()  # type: Tuple[Assignment, ...]
        self.statistics = ()  # type: Tuple[Score, ...]
        self.solution_count = 0
        self.current_score = 0
        self.auto_solve = auto_solve
        self.dirty = False
        self.path = ""
        self._path_autosave = os.path.join(tempfile.gettempdir(), "tmp.yml")

        self._thread = WorkerThread()
        self._thread.started.connect(self.onSolvingStarted.emit, Qt.DirectConnection)  # type: ignore
        self._thread.finished.connect(self.onSolvingEnded.emit, Qt.DirectConnection)  # type: ignore
        self._thread.foundSolution.connect(self._on_solution_found, Qt.DirectConnection)  # type: ignore
        self.set_context(context or Context())

        if self.auto_solve and self.can_play():
            self.play()
Example #4
0
def test_export_assignments_to_csv(tmpdir):
    """Ensure we can export a list of assignments to a .csv file."""
    path = os.path.join(tmpdir, "artists.csv")
    artist1 = Artist("Artist1")
    artist2 = Artist("Artist2")
    task1 = Task("0010", 1)
    task2 = Task("0020", 2)
    context = Context(
        artists=[artist1, artist2],
        tasks=[task1, task2],
        assignments=[Assignment(artist1, task1),
                     Assignment(artist2, task2)],
    )

    _io.export_assignments_to_csv(context.assignments, path)

    with open(path) as stream:
        actual = stream.read()

    assert actual == "0010,Artist1\n0020,Artist2\n"
Example #5
0
    def __init__(self, context=None, parent=None):
        super().__init__(parent)
        context = context or Context()

        self._manager = Manager(context)

        # Build top menu
        self.action_new = QAction("New", self)
        self.action_save = QAction("Save", self)
        self.action_open = QAction("Open", self)
        self.action_save_as = QAction("Save As", self)
        self.action_quit = QAction("Quit", self)
        self.action_show_artists = QAction("Artists", self)
        self.action_show_artists.setCheckable(True)
        self.action_show_artists.setChecked(True)
        self.action_show_tasks = QAction("Tasks", self)
        self.action_show_tasks.setCheckable(True)
        self.action_show_tasks.setChecked(True)
        self.action_show_taskgroups = QAction("Task Groups", self)
        self.action_show_taskgroups.setCheckable(True)
        self.action_show_settings = QAction("Settings", self)
        self.action_show_settings.setCheckable(True)
        self.action_show_scores = QAction("Score", self)
        self.action_show_scores.setCheckable(True)

        self.menubar = QMenuBar(self)
        self.menu_file = QMenu("File", self.menubar)
        self.menu_view = QMenu("View", self.menubar)
        self.menubar.addAction(self.menu_file.menuAction())
        self.menubar.addAction(self.menu_view.menuAction())
        self.menu_file.addAction(self.action_new)
        self.menu_file.addAction(self.action_open)
        self.menu_file.addAction(self.action_save)
        self.menu_file.addAction(self.action_save_as)
        self.menu_file.addSeparator()
        self.menu_view.addAction(self.action_show_artists)
        self.menu_view.addAction(self.action_show_tasks)
        self.menu_view.addAction(self.action_show_taskgroups)
        self.menu_view.addAction(self.action_show_settings)
        self.menu_view.addAction(self.action_show_scores)
        self.setMenuBar(self.menubar)

        # Build dock widgets
        self.widget_artists = ArtistsWidget(self, self._manager)
        self.widget_tasks = TasksWidget(self, self._manager)
        self.widget_settings = SettingsWidget(self, self._manager)
        self.widget_scores = ScoresWidget(self)
        self.widget_tasksgroups = TasksGroupsWidget(self, self._manager,
                                                    self.widget_tasks)
        self.widget_gantt = GanttWidget(
            self,
            self._manager,
            self.widget_artists.model,
            self.widget_tasks.model,
            self.widget_artists.table.selectionModel(),
            self.widget_tasks.table.selectionModel(),
        )
        self.widget_footer = FooterBarWidget(self, self._manager)

        self.addDockWidget(Qt.RightDockWidgetArea, self.widget_artists)
        self.addDockWidget(Qt.RightDockWidgetArea, self.widget_tasks)
        self.addDockWidget(Qt.RightDockWidgetArea, self.widget_tasksgroups)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.widget_gantt)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.widget_scores)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.widget_settings)
        self.addToolBar(Qt.BottomToolBarArea, self.widget_footer)

        # Connect events
        self.widget_footer.actionPlay.connect(self._manager.play)
        self.widget_footer.actionStop.connect(self._manager.stop)
        self.widget_footer.actionLiveModeToggle.connect(
            self.on_autosolve_changed)
        self._manager.onSolutionFound.connect(self.on_solution_found)
        self._manager.onContextChanged.connect(self.on_context_changed)
        self._manager.onDirty.connect(self.on_dirty)
        self.action_new.triggered.connect(self.file_new)
        self.action_open.triggered.connect(self.file_open)
        self.action_save.triggered.connect(self.file_save)
        self.action_save_as.triggered.connect(self.file_save_as)
        self.widget_artists.artistDeleted.connect(self._on_artist_deleted)
        self.widget_tasks.taskDeleted.connect(self._on_task_deleted)

        for action, widget in (
            (self.action_show_artists, self.widget_artists),
            (self.action_show_tasks, self.widget_tasks),
            (self.action_show_taskgroups, self.widget_tasksgroups),
            (self.action_show_settings, self.widget_settings),
            (self.action_show_scores, self.widget_scores),
        ):
            widget.setVisible(action.isChecked())
            action.toggled.connect(widget.setVisible)

        self.shortcut = QShortcut(QKeySequence("Space"), self)
        self.shortcut.activated.connect(self._manager.toogle)

        self._manager.restore_autosave()
        self._update_window_title()
Example #6
0
 def file_new(self):
     """Clear the current session."""
     self._manager.set_context(Context())
     self._update_window_title()
Example #7
0
def manager():
    return Manager(Context())
Example #8
0
def test_serialization(tmp_path):
    """Validate we can serialize/deserialize a context. """
    path = tmp_path / "context.yml"
    artist1 = Artist("Artist1", tags={"0010": 1})
    artist2 = Artist("Artist1", tags={"0010": 1})
    task1 = Task("0010", 1, tags=["acting"])
    task2 = Task("0020", 1)
    context = Context(
        artists=[artist1],
        tasks=[task1, task2],
        assignments=[Assignment(artist1, task1),
                     Assignment(artist2, task2)],
        combinations=[TaskGroup([task1], 1)],
    )

    # Test serialization
    _io.export_context_to_yml(context, path)
    actual = yaml.load(path.read_text())
    expected = {
        "artists": [{
            "name": "Artist1",
            "availability": 100,
            "tags": [{
                "name": "0010",
                "weight": 1
            }],
        }],
        "tasks": [
            {
                "name": "0010",
                "duration": 1.0,
                "tags": ["acting"]
            },
            {
                "name": "0020",
                "duration": 1.0
            },
        ],
        "settings": {
            "TAGS": 100,
            "EQUAL_TASKS_BY_USER": 10,
            "EQUAL_TASKS_COUNT_BY_USER": 10,
        },
        "assignments": [
            {
                "artist": "Artist1",
                "task": "0010"
            },
            {
                "artist": "Artist1",
                "task": "0020"
            },
        ],
        "combinations": [{
            "tasks": ["0010"],
            "weight": 1
        }],
    }
    assert actual == expected

    # Test deserialization round-trip
    deserialized = _io.import_context_from_yml(path)
    assert context == deserialized