def testGetScenarioList(self):
        """
        Test retrieving scenario list
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertEqual(reg.scenario_list(), [1, 2, 3])
    def testGetScenarioName(self):
        """
        Test retrieving scenario name
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertEqual(reg.get_scenario_name(1), "Scenario 1")
        self.assertEqual(reg.get_scenario_name(2), "scenario B")
        self.assertEqual(reg.get_scenario_name(3), "scenario 3")
    def testScenarioNameExists(self):
        """
        Test scenario name exists
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertFalse(reg.scenario_name_exists('bbbb'))
        self.assertTrue(reg.scenario_name_exists('Scenario 1'))
        self.assertTrue(reg.scenario_name_exists('scenario 3'))
    def testGetScenarioTitles(self):
        """
        Test retrieving scenario titles
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertEqual(
            reg.scenario_titles(),
            OrderedDict([('Scenario 1', 1), ('scenario 3', 3),
                         ('scenario B', 2)]))
    def testScenarioExists(self):
        """
        Test scenario exists
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertFalse(reg.scenario_exists(-1))
        self.assertTrue(reg.scenario_exists(1))
        self.assertTrue(reg.scenario_exists(3))
        self.assertFalse(reg.scenario_exists(5))
Exemplo n.º 6
0
 def testFilter(self):
     """
     Test filtering inside the dialog
     """
     layer = make_scenario_layer()
     mb_electorate_layer = make_meshblock_electorate_layer()
     registry = ScenarioRegistry(
         source_layer=layer,
         id_field='id',
         name_field='name',
         meshblock_electorate_layer=mb_electorate_layer)
     dlg = ScenarioSelectionDialog(scenario_registry=registry)
     self.assertEqual(
         [dlg.list.item(r).text() for r in range(dlg.list.count())],
         ['Scenario 1', 'scenario 3', 'scenario B'])
     dlg.search.setText('eee')  # connection not fired on first change?
     dlg.search.setText('3')
     self.assertEqual([
         dlg.list.item(r).text() for r in range(dlg.list.count())
         if not dlg.list.item(r).isHidden()
     ], ['scenario 3'])
     dlg.search.setText('B')
     self.assertEqual([
         dlg.list.item(r).text() for r in range(dlg.list.count())
         if not dlg.list.item(r).isHidden()
     ], ['scenario B'])
     # case insensitive!
     dlg.search.setText('b')
     self.assertEqual([
         dlg.list.item(r).text() for r in range(dlg.list.count())
         if not dlg.list.item(r).isHidden()
     ], ['scenario B'])
    def testGetScenario(self):
        """
        Test retrieving scenario feature
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        f = reg.get_scenario(1)
        self.assertEqual(
            f.attributes(),
            [1, 'Scenario 1',
             QDateTime(2018, 6, 4, 12, 13, 14), 'user 1'])
        f = reg.get_scenario(2)
        self.assertEqual(
            f.attributes(),
            [2, 'scenario B',
             QDateTime(2018, 7, 5, 12, 13, 14), 'user 2'])
 def testConstruct(self):
     """
     Test constructing dock
     """
     scenario_layer = make_scenario_layer()
     scenario_registry = ScenarioRegistry(source_layer=scenario_layer,
                                          id_field='id',
                                          name_field='name',
                                          meshblock_electorate_layer=None)
     context = LinzRedistrictingContext(scenario_registry=scenario_registry)
     widget = LinzRedistrictingDockWidget(context=context, iface=IFACE)
     self.assertIsNotNone(widget)
Exemplo n.º 9
0
 def testConstruct(self):
     """
     Test creating dialog
     """
     layer = make_scenario_layer()
     mb_electorate_layer = make_meshblock_electorate_layer()
     registry = ScenarioRegistry(
         source_layer=layer,
         id_field='id',
         name_field='name',
         meshblock_electorate_layer=mb_electorate_layer)
     self.assertIsNotNone(
         ScenarioSelectionDialog(scenario_registry=registry))
Exemplo n.º 10
0
 def testAccept(self):
     """
     Test that accepting dialog
     """
     layer = make_scenario_layer()
     mb_electorate_layer = make_meshblock_electorate_layer()
     registry = ScenarioRegistry(
         source_layer=layer,
         id_field='id',
         name_field='name',
         meshblock_electorate_layer=mb_electorate_layer)
     dlg = ScenarioSelectionDialog(scenario_registry=registry)
     dlg.set_selected_scenario('d4')
     dlg.accept()
    def testScenarioRegistry(self):
        """
        Test a LinzDistrictRegistry
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        self.assertEqual(reg.source_layer, layer)
        self.assertEqual(reg.id_field, 'id')
        self.assertEqual(reg.id_field_index, 0)
        self.assertEqual(reg.name_field, 'name')
        self.assertEqual(reg.name_field_index, 1)
    def testBranch(self):
        """
        Test branching scenario
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)

        # dupe name
        res, error = reg.branch_scenario(1, 'Scenario 1')
        self.assertFalse(res)
        self.assertIn('already exists', error)

        # missing source scenario
        res, error = reg.branch_scenario(5, 'Scenario 5')
        self.assertFalse(res)
        self.assertIn('does not exist', error)

        # good
        res, error = reg.branch_scenario(1, 'Scenario 5')
        self.assertFalse(error)
        self.assertEqual(res, 4)

        f = [f for f in layer.getFeatures()][-1]
        self.assertEqual(f[0], res)
        self.assertEqual(f[1], 'Scenario 5')
        self.assertEqual(f[2].date(), QDateTime.currentDateTime().date())
        self.assertEqual(f[3], QgsApplication.userFullName())

        f = [f.attributes() for f in mb_electorate_layer.getFeatures()]
        self.assertEqual(
            f,
            [[3, 4, 0, 'c', 'z'], [4, 4, 1, 'd', 'zz'], [1, 2, 0, 'a', 'x'],
             [2, 2, 1, 'b', 'y'], [3, 1, 0, 'c', 'z'], [4, 1, 1, 'd', 'zz']])

        res, error = reg.branch_scenario(2, 'Scenario 6')
        self.assertFalse(error)
        self.assertEqual(res, 5)

        f = [f for f in layer.getFeatures()][-1]
        self.assertEqual(f[0], res)
        self.assertEqual(f[1], 'Scenario 6')
        self.assertEqual(f[2].date(), QDateTime.currentDateTime().date())
        self.assertEqual(f[3], QgsApplication.userFullName())

        f = [f.attributes() for f in mb_electorate_layer.getFeatures()]
        self.assertEqual(
            f, [[3, 4, 0, 'c', 'z'], [4, 4, 1, 'd', 'zz'], [1, 5, 0, 'a', 'x'],
                [2, 5, 1, 'b', 'y'], [1, 2, 0, 'a', 'x'], [2, 2, 1, 'b', 'y'],
                [3, 1, 0, 'c', 'z'], [4, 1, 1, 'd', 'zz']])
Exemplo n.º 13
0
    def testPopulation(self):
        """
        Test that dialog is correctly populated from registry
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()
        registry = ScenarioRegistry(
            source_layer=layer,
            id_field='id',
            name_field='name',
            meshblock_electorate_layer=mb_electorate_layer)
        dlg = ScenarioSelectionDialog(scenario_registry=registry)
        self.assertEqual(
            [dlg.list.item(r).text() for r in range(dlg.list.count())],
            ['Scenario 1', 'scenario 3', 'scenario B'])

        # initial selection must be final scenario
        self.assertEqual(dlg.selected_scenario(), 2)
 def testNameForCurrentTask(self):
     """
     Test retrieving friendly name for currenttask
     """
     scenario_layer = make_scenario_layer()
     scenario_registry = ScenarioRegistry(source_layer=scenario_layer,
                                          id_field='id',
                                          name_field='name',
                                          meshblock_electorate_layer=None)
     context = LinzRedistrictingContext(scenario_registry=scenario_registry)
     context.task = LinzRedistrictingContext.TASK_GN
     self.assertEqual(context.get_name_for_current_task(),
                      'General (North Island)')
     context.task = LinzRedistrictingContext.TASK_GS
     self.assertEqual(context.get_name_for_current_task(),
                      'General (South Island)')
     context.task = LinzRedistrictingContext.TASK_M
     self.assertEqual(context.get_name_for_current_task(), 'Māori')
    def __init__(self, scenario_registry: ScenarioRegistry, parent=None):
        """
        Constructor for ScenarioSelectionDialog
        :param scenario_registry: linked scenario registry
        :param parent: parent widget
        """
        super().__init__(parent)

        self.scenario_registry = scenario_registry

        self.setWindowTitle(self.tr('Select Current Scenario'))

        layout = QVBoxLayout()

        self.search = QgsFilterLineEdit()
        self.search.setShowSearchIcon(True)
        self.search.setPlaceholderText(self.tr('Search for scenario'))
        self.search.textChanged.connect(self.filter_changed)
        layout.addWidget(self.search)

        self.list = QListWidget()
        for title, scenario_id in scenario_registry.scenario_titles().items():
            item = QListWidgetItem(title)
            item.setData(Qt.UserRole, scenario_id)
            self.list.addItem(item)

        layout.addWidget(self.list, 10)

        button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        layout.addWidget(button_box)
        button_box.rejected.connect(self.reject)
        button_box.accepted.connect(self.accept)

        self.setLayout(layout)

        self.list.itemDoubleClicked.connect(
            self.accept)

        # select last scenario by default
        if self.list.count() > 0:
            self.list.item(self.list.count() - 1).setSelected(True)
 def testBasic(self):
     """
     Test getters/settings
     """
     scenario_layer = make_scenario_layer()
     scenario_registry = ScenarioRegistry(source_layer=scenario_layer,
                                          id_field='id',
                                          name_field='name',
                                          meshblock_electorate_layer=None)
     context = LinzRedistrictingContext(scenario_registry=scenario_registry)
     self.assertIn(context.task, (LinzRedistrictingContext.TASK_GN,
                                  LinzRedistrictingContext.TASK_GS,
                                  LinzRedistrictingContext.TASK_M))
     context.task = LinzRedistrictingContext.TASK_GS
     self.assertEqual(context.task, LinzRedistrictingContext.TASK_GS)
     self.assertIsNotNone(context.scenario)
     context.scenario = 10
     self.assertEqual(context.scenario, 10)
     context.set_scenario(3)
     self.assertEqual(context.scenario, 3)
 def testTitle(self):
     """
     Test title updates
     """
     scenario_layer = make_scenario_layer()
     scenario_registry = ScenarioRegistry(source_layer=scenario_layer,
                                          id_field='id',
                                          name_field='name',
                                          meshblock_electorate_layer=None)
     context = LinzRedistrictingContext(scenario_registry=scenario_registry)
     context.task = LinzRedistrictingContext.TASK_GS
     context.scenario = 1
     widget = LinzRedistrictingDockWidget(context=context, iface=IFACE)
     self.assertEqual(
         widget.windowTitle(),
         'Redistricting - General (South Island) - Scenario 1')
     context.task = LinzRedistrictingContext.TASK_GN
     context.scenario = 3
     widget.update_dock_title(context=context)
     self.assertEqual(
         widget.windowTitle(),
         'Redistricting - General (North Island) - scenario 3')
Exemplo n.º 18
0
    def testSelection(self):
        """
        Test setting/getting selected scenario
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()
        registry = ScenarioRegistry(
            source_layer=layer,
            id_field='id',
            name_field='name',
            meshblock_electorate_layer=mb_electorate_layer)
        dlg = ScenarioSelectionDialog(scenario_registry=registry)

        dlg.set_selected_scenario(1)
        self.assertEqual(dlg.selected_scenario(), 1)
        dlg.set_selected_scenario(2)
        self.assertEqual(dlg.selected_scenario(), 2)
        dlg.set_selected_scenario(3)
        self.assertEqual(dlg.selected_scenario(), 3)

        # nothing at all selected
        dlg.list.clearSelection()
        self.assertIsNone(dlg.selected_scenario())
Exemplo n.º 19
0
    def testDialog(self):
        """
        Test dialog functionality
        """
        scenario_layer = make_scenario_layer()
        scenario_registry = ScenarioRegistry(source_layer=scenario_layer,
                                             id_field='id',
                                             name_field='name',
                                             meshblock_electorate_layer=None)

        layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=fld1:string&field=code:string&field=type:string&field=estimated_pop:int&field=deprecated:int&field=stats_nz_pop:int&field=stats_nz_var_20:int&field=stats_nz_var_23:int&field=scenario_id:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes(["test4", "xtest1", 'GN'])
        f2 = QgsFeature()
        f2.setAttributes(["test2", "xtest3", 'GS'])
        f3 = QgsFeature()
        f3.setAttributes(["test3", "xtest3", 'M'])
        layer.dataProvider().addFeatures([f, f2, f3])
        quota_layer = make_quota_layer()

        reg = LinzElectoralDistrictRegistry(source_layer=layer,
                                            quota_layer=quota_layer,
                                            electorate_type='',
                                            source_field='fld1',
                                            title_field='fld1')

        context = LinzRedistrictingContext(scenario_registry=scenario_registry)
        dlg = CreateElectorateDialog(registry=reg, context=context)
        self.assertIsNotNone(dlg)

        self.assertFalse(
            dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())

        dlg.name_line_edit.setText('new district')
        dlg.code_line_edit.setText('new code')
        self.assertEqual(dlg.name(), 'new district')
        self.assertEqual(dlg.code(), 'new code')

        # dupe name
        dlg.name_line_edit.setText('test4')
        self.assertFalse(
            dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertIn('already exists', dlg.feedback_label.text())
        dlg.name_line_edit.setText('test99')
        self.assertTrue(dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertFalse(dlg.feedback_label.text())
        dlg.name_line_edit.setText('')
        self.assertFalse(
            dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertIn('must be entered', dlg.feedback_label.text())
        dlg.name_line_edit.setText('test99')
        self.assertTrue(dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertFalse(dlg.feedback_label.text())

        # dupe code
        dlg.code_line_edit.setText('xtest1')
        self.assertFalse(
            dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertIn('already exists', dlg.feedback_label.text())
        dlg.code_line_edit.setText('test99')
        self.assertTrue(dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        self.assertFalse(dlg.feedback_label.text())
        dlg.code_line_edit.setText('')
        self.assertIn('must be entered', dlg.feedback_label.text())
        self.assertFalse(
            dlg.button_box.button(QDialogButtonBox.Ok).isEnabled())
        dlg.code_line_edit.setText('test99')
        self.assertFalse(dlg.feedback_label.text())
    def testSwitchTask(self):  # pylint: disable=too-many-locals, too-many-statements
        """
        Test scenario switch task
        """
        layer = make_scenario_layer()
        mb_electorate_layer = QgsVectorLayer(
            "NoGeometry?field=id:int&field=scenario_id:int&field=meshblock_number:int&field=gn_id:int&field=gs_id:int&field=m_id:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes([1, 1, 11, 1, 0, 7])
        f2 = QgsFeature()
        f2.setAttributes([2, 1, 12, 2, 0, 7])
        f3 = QgsFeature()
        f3.setAttributes([3, 1, 13, 2, 0, 7])
        f4 = QgsFeature()
        f4.setAttributes([4, 1, 14, 0, 4, 8])
        f5 = QgsFeature()
        f5.setAttributes([5, 1, 15, 0, 5, 8])
        f6 = QgsFeature()
        f6.setAttributes([6, 1, 16, 0, 5, 8])
        f7 = QgsFeature()
        f7.setAttributes([7, 2, 11, 2, 0, 7])
        f8 = QgsFeature()
        f8.setAttributes([8, 2, 12, 2, 0, 8])
        f9 = QgsFeature()
        f9.setAttributes([9, 2, 13, 3, 0, 7])
        f10 = QgsFeature()
        f10.setAttributes([10, 2, 14, 0, 5, 8])
        f11 = QgsFeature()
        f11.setAttributes([11, 2, 15, 0, 4, 7])
        f12 = QgsFeature()
        f12.setAttributes([12, 2, 16, 0, 4, 8])
        mb_electorate_layer.dataProvider().addFeatures(
            [f, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12])

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        electorate_layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=electorate_id:int&field=code:string&field=type:string&field=estimated_pop:int&field=scenario_id:int&field=invalid:int&field=invalid_reason:string&field=name:string&field=stats_nz_pop:int&field=stats_nz_var_20:int&field=stats_nz_var_23:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes(
            [1, "test1", 'GN', -1, 0, 1, 'old invalid', NULL, 1111, 11, -11])
        f2 = QgsFeature()
        f2.setAttributes(
            [2, "test2", 'GN', -1, 0, 1, 'old invalid 2', NULL, 1112, 12, -12])
        f3 = QgsFeature()
        f3.setAttributes(
            [3, "test3", 'GN', -1, 0, 1, 'old invalid 3', NULL, 1113, 13, -13])
        f4 = QgsFeature()
        f4.setAttributes(
            [4, "test4", 'GS', -1, 0, 1, 'old invalid 4', NULL, 1114, 14, -14])
        f5 = QgsFeature()
        f5.setAttributes(
            [5, "test5", 'GS', -1, 0, 1, 'old invalid 5', NULL, 1115, 15, -15])
        f6 = QgsFeature()
        f6.setAttributes(
            [6, "test6", 'GS', -1, 0, 1, 'old invalid 6', NULL, 1116, 16, -16])
        f7 = QgsFeature()
        f7.setAttributes(
            [7, "test7", 'M', -1, 0, 1, 'old invalid 7', NULL, 1117, 17, -17])
        f8 = QgsFeature()
        f8.setAttributes(
            [8, "test8", 'M', -1, 0, 1, 'old invalid 8', NULL, 1118, 18, -18])
        electorate_layer.dataProvider().addFeatures(
            [f, f2, f3, f4, f5, f6, f7, f8])

        meshblock_layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=MeshblockNumber:string&field=offline_pop_m:int&field=offline_pop_gn:int&field=offline_pop_gs:int&field=staged_electorate:int&field=offshore:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes(["11", 5, 11, 0])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
        f2 = QgsFeature()
        f2.setAttributes(["12", 6, 12, 0])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 3)))
        f3 = QgsFeature()
        f3.setAttributes(["13", 7, 13, 0])
        f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 5)))
        f4 = QgsFeature()
        f4.setAttributes(["14", 8, 0, 20])
        f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6, 7)))
        f5 = QgsFeature()
        f5.setAttributes(["15", 9, 0, 30])
        f5.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(8, 9)))
        f6 = QgsFeature()
        f6.setAttributes(["16", 10, 0, 40])
        f6.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 11)))
        meshblock_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6])

        task = ScenarioSwitchTask(
            task_name='',
            electorate_layer=electorate_layer,
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=1)
        self.assertTrue(task.run())
        self.assertEqual(
            [f.attributes() for f in electorate_layer.getFeatures()],
            [[1, 'test1', 'GN', 11, 1, NULL, None, NULL, NULL, NULL, NULL],
             [2, 'test2', 'GN', 25, 1, NULL, None, NULL, NULL, NULL, NULL],
             [3, 'test3', 'GN', 0, 1, NULL, None, NULL, NULL, NULL, NULL],
             [4, 'test4', 'GS', 20, 1, NULL, None, NULL, NULL, NULL, NULL],
             [5, 'test5', 'GS', 70, 1, NULL, None, NULL, NULL, NULL, NULL],
             [6, 'test6', 'GS', 0, 1, NULL, None, NULL, NULL, NULL, NULL],
             [7, 'test7', 'M', 18, 1, NULL, None, NULL, NULL, NULL, NULL],
             [8, 'test8', 'M', 27, 1, NULL, None, NULL, NULL, NULL, NULL]])
        self.assertEqual(
            [f.geometry().asWkt() for f in electorate_layer.getFeatures()], [
                'Point (1 2)', 'MultiPoint ((2 3),(4 5))',
                'GeometryCollection ()', 'Point (6 7)',
                'MultiPoint ((8 9),(10 11))', 'GeometryCollection ()',
                'MultiPoint ((1 2),(2 3),(4 5))',
                'MultiPoint ((6 7),(8 9),(10 11))'
            ])
        task = UpdateStagedElectoratesTask(
            task_name='',
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=1,
            task='GN')
        self.assertTrue(task.run())
        self.assertEqual(
            [f['staged_electorate'] for f in meshblock_layer.getFeatures()],
            [1, 2, 2, 0, 0, 0])
        task = UpdateStagedElectoratesTask(
            task_name='',
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=1,
            task='M')
        self.assertTrue(task.run())
        self.assertEqual(
            [f['staged_electorate'] for f in meshblock_layer.getFeatures()],
            [7, 7, 7, 8, 8, 8])

        task = ScenarioSwitchTask(
            task_name='',
            electorate_layer=electorate_layer,
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=2)
        self.assertTrue(task.run())
        self.assertEqual(
            [f.attributes() for f in electorate_layer.getFeatures()],
            [[1, 'test1', 'GN', 0, 2, NULL, None, NULL, NULL, NULL, NULL],
             [2, 'test2', 'GN', 23, 2, NULL, None, NULL, NULL, NULL, NULL],
             [3, 'test3', 'GN', 13, 2, NULL, None, NULL, NULL, NULL, NULL],
             [4, 'test4', 'GS', 70, 2, NULL, None, NULL, NULL, NULL, NULL],
             [5, 'test5', 'GS', 20, 2, NULL, None, NULL, NULL, NULL, NULL],
             [6, 'test6', 'GS', 0, 2, NULL, None, NULL, NULL, NULL, NULL],
             [7, 'test7', 'M', 21, 2, NULL, None, NULL, NULL, NULL, NULL],
             [8, 'test8', 'M', 24, 2, NULL, None, NULL, NULL, NULL, NULL]])
        self.assertEqual(
            [f.geometry().asWkt() for f in electorate_layer.getFeatures()], [
                'GeometryCollection ()', 'MultiPoint ((1 2),(2 3))',
                'Point (4 5)', 'MultiPoint ((8 9),(10 11))', 'Point (6 7)',
                'GeometryCollection ()', 'MultiPoint ((1 2),(4 5),(8 9))',
                'MultiPoint ((2 3),(6 7),(10 11))'
            ])
        task = UpdateStagedElectoratesTask(
            task_name='',
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=2,
            task='GN')
        self.assertTrue(task.run())
        self.assertEqual(
            [f['staged_electorate'] for f in meshblock_layer.getFeatures()],
            [2, 2, 3, 0, 0, 0])
        task = UpdateStagedElectoratesTask(
            task_name='',
            meshblock_layer=meshblock_layer,
            meshblock_number_field_name='MeshblockNumber',
            scenario_registry=reg,
            scenario=2,
            task='M')
        self.assertTrue(task.run())
        self.assertEqual(
            [f['staged_electorate'] for f in meshblock_layer.getFeatures()],
            [7, 8, 7, 8, 7, 8])
    def testElectorateHasMeshblocks(self):
        """
        Test checking whether an electorate has meshblocks assigned
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)

        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='c',
                                          electorate_type='GN',
                                          scenario_id=1))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='d',
                                          electorate_type='GN',
                                          scenario_id=1))
        self.assertFalse(
            reg.electorate_has_meshblocks(electorate_id='a',
                                          electorate_type='GN',
                                          scenario_id=1))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='z',
                                          electorate_type='GS',
                                          scenario_id=1))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='zz',
                                          electorate_type='GS',
                                          scenario_id=1))
        self.assertFalse(
            reg.electorate_has_meshblocks(electorate_id='x',
                                          electorate_type='GS',
                                          scenario_id=1))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='a',
                                          electorate_type='GN',
                                          scenario_id=2))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='b',
                                          electorate_type='GN',
                                          scenario_id=2))
        self.assertFalse(
            reg.electorate_has_meshblocks(electorate_id='c',
                                          electorate_type='GN',
                                          scenario_id=2))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='x',
                                          electorate_type='GS',
                                          scenario_id=2))
        self.assertTrue(
            reg.electorate_has_meshblocks(electorate_id='y',
                                          electorate_type='GS',
                                          scenario_id=2))
        self.assertFalse(
            reg.electorate_has_meshblocks(electorate_id='z',
                                          electorate_type='GS',
                                          scenario_id=2))
    def testValidationTask(self):  # pylint: disable=too-many-locals, too-many-statements
        """
        Test validation task
        """
        layer = make_scenario_layer()
        mb_electorate_layer = QgsVectorLayer(
            "NoGeometry?field=id:int&field=scenario_id:int&field=meshblock_number:int&field=gn_id:int&field=gs_id:int&field=m_id:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes([1, 1, 11, 1, 0, 7])
        f2 = QgsFeature()
        f2.setAttributes([2, 1, 12, 2, 0, 0])
        f3 = QgsFeature()
        f3.setAttributes([3, 1, 13, 2, 0, 0])
        f4 = QgsFeature()
        f4.setAttributes([4, 1, 14, 3, 4, 0])
        f5 = QgsFeature()
        f5.setAttributes([5, 1, 15, 3, 5, 0])
        f6 = QgsFeature()
        f6.setAttributes([6, 1, 16, 2, 5, 0])
        mb_electorate_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6])

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)
        electorate_layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=electorate_id:int&field=code:string&field=type:string&field=estimated_pop:int&field=scenario_id:int&field=deprecated:int&field=invalid:int&field=invalid_reason:string&field=name:string&field=stats_nz_pop:int&field=stats_nz_var_20:int&field=stats_nz_var_23:int&field=electorate_id_stats:string&field=expected_regions:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes([
            1, "test1", 'GN', 1, 0, 0, 1, 'old invalid', NULL, NULL, NULL,
            NULL, NULL, 1
        ])
        f2 = QgsFeature()
        f2.setAttributes([
            2, "test2", 'GN', 1, 0, 0, 1, 'old invalid 2', NULL, NULL, NULL,
            NULL, NULL, 2
        ])
        f3 = QgsFeature()
        f3.setAttributes([
            3, "test3", 'GN', 1, 0, 0, 1, 'old invalid 3', NULL, NULL, NULL,
            NULL, NULL, 2
        ])
        f4 = QgsFeature()
        f4.setAttributes([
            4, "test4", 'GS', 1, 0, 0, 1, 'old invalid 4', NULL, NULL, NULL,
            NULL, NULL, 2
        ])
        f5 = QgsFeature()
        f5.setAttributes([
            5, "test5", 'GS', 1, 0, 0, 1, 'old invalid 5', NULL, NULL, NULL,
            NULL, NULL, 1
        ])
        f6 = QgsFeature()
        f6.setAttributes([
            6, "test6", 'GS', 1, 0, 0, 1, 'old invalid 6', NULL, NULL, NULL,
            NULL, NULL, 1
        ])
        f7 = QgsFeature()
        f7.setAttributes([
            7, "test7", 'M', 1, 0, 1, 1, 'old invalid 7', NULL, NULL, NULL,
            NULL, NULL, 1
        ])
        f8 = QgsFeature()
        # deprecated
        f8.setAttributes([
            8, "test8", 'M', 1, 0, 1, 1, 'old invalid 8', NULL, NULL, NULL,
            NULL, NULL, 1
        ])
        electorate_layer.dataProvider().addFeatures(
            [f, f2, f3, f4, f5, f6, f7, f8])

        meshblock_layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=MeshblockNumber:string&field=offline_pop_m:int&field=offline_pop_gn:int&field=offline_pop_gs:int&field=staged_electorate:int&field=offshore:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes(["11", 5, 58900, 0, NULL, 0])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
        f2 = QgsFeature()
        f2.setAttributes(["12", 6, 57000, 0, NULL, 0])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 3)))
        f3 = QgsFeature()
        f3.setAttributes(["13", 7, 2000, 0, NULL, 0])
        f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 5)))
        f4 = QgsFeature()
        f4.setAttributes(["14", 8, 0, 20, NULL, 0])
        f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(6, 7)))
        f5 = QgsFeature()
        f5.setAttributes(["15", 9, 0, 30, NULL, 0])
        f5.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(8, 9)))
        f6 = QgsFeature()
        f6.setAttributes(["16", 10, 0, 40, NULL, 1])
        f6.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 11)))
        meshblock_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6])

        quota_layer = make_quota_layer()

        electorate_registry = LinzElectoralDistrictRegistry(
            source_layer=electorate_layer,
            source_field='electorate_id',
            title_field='code',
            electorate_type='GN',
            quota_layer=quota_layer)

        task = ValidationTask(task_name='',
                              electorate_registry=electorate_registry,
                              meshblock_layer=meshblock_layer,
                              meshblock_number_field_name='MeshblockNumber',
                              scenario_registry=reg,
                              scenario=1,
                              task='GN')
        self.assertEqual(
            [f.attributes()[:9] for f in electorate_layer.getFeatures()],
            [[1, 'test1', 'GN', 1, 0, 0, NULL, NULL, NULL],
             [2, 'test2', 'GN', 1, 0, 0, NULL, NULL, NULL],
             [3, 'test3', 'GN', 1, 0, 0, NULL, NULL, NULL],
             [4, 'test4', 'GS', 1, 0, 0, 1, 'old invalid 4', NULL],
             [5, 'test5', 'GS', 1, 0, 0, 1, 'old invalid 5', NULL],
             [6, 'test6', 'GS', 1, 0, 0, 1, 'old invalid 6', NULL],
             [7, 'test7', 'M', 1, 0, 1, 1, 'old invalid 7', NULL],
             [8, 'test8', 'M', 1, 0, 1, 1, 'old invalid 8', NULL]])

        self.assertTrue(task.run())
        self.assertEqual(len(task.results), 5)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_ID], 2)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_NAME],
                         'test2')
        self.assertEqual(task.results[0][ValidationTask.ERROR],
                         'Electorate is non-contiguous')
        self.assertEqual(
            task.results[0][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'MultiPoint ((2 3),(4 5),(10 11))')
        self.assertEqual(task.results[1][ValidationTask.ELECTORATE_ID], 2)
        self.assertEqual(task.results[1][ValidationTask.ELECTORATE_NAME],
                         'test2')
        self.assertEqual(task.results[1][ValidationTask.ERROR],
                         'Contiguous part 1')
        self.assertEqual(
            task.results[1][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'Point (2 3)')
        self.assertEqual(task.results[2][ValidationTask.ELECTORATE_ID], 2)
        self.assertEqual(task.results[2][ValidationTask.ELECTORATE_NAME],
                         'test2')
        self.assertEqual(task.results[2][ValidationTask.ERROR],
                         'Contiguous part 2')
        self.assertEqual(
            task.results[2][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'Point (4 5)')
        self.assertEqual(task.results[3][ValidationTask.ELECTORATE_ID], 2)
        self.assertEqual(task.results[3][ValidationTask.ELECTORATE_NAME],
                         'test2')
        self.assertEqual(task.results[3][ValidationTask.ERROR],
                         'Contiguous part 3')
        self.assertEqual(
            task.results[3][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'Point (10 11)')
        self.assertEqual(task.results[4][ValidationTask.ELECTORATE_ID], 3)
        self.assertEqual(task.results[4][ValidationTask.ELECTORATE_NAME],
                         'test3')
        self.assertEqual(task.results[4][ValidationTask.ERROR],
                         'Outside quota tolerance')
        self.assertEqual(
            [f.attributes()[:9] for f in electorate_layer.getFeatures()],
            [[1, 'test1', 'GN', 58900, 1, 0, 0, NULL, NULL],
             [
                 2, 'test2', 'GN', 1, 0, 0, 1, 'Electorate is non-contiguous',
                 NULL
             ], [
                 3, 'test3', 'GN', 1, 0, 0, 1, 'Outside quota tolerance', NULL
             ], [4, 'test4', 'GS', 1, 0, 0, 1, 'old invalid 4', NULL],
             [5, 'test5', 'GS', 1, 0, 0, 1, 'old invalid 5', NULL],
             [6, 'test6', 'GS', 1, 0, 0, 1, 'old invalid 6', NULL],
             [7, 'test7', 'M', 1, 0, 1, 1, 'old invalid 7', NULL],
             [8, 'test8', 'M', 1, 0, 1, 1, 'old invalid 8', NULL]])

        electorate_registry = LinzElectoralDistrictRegistry(
            source_layer=electorate_layer,
            source_field='electorate_id',
            title_field='code',
            electorate_type='GN',
            quota_layer=quota_layer)

        task = ValidationTask(task_name='',
                              electorate_registry=electorate_registry,
                              meshblock_layer=meshblock_layer,
                              meshblock_number_field_name='MeshblockNumber',
                              scenario_registry=reg,
                              scenario=1,
                              task='GS')

        self.assertTrue(task.run())
        self.assertEqual(len(task.results), 7)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_ID], 4)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_NAME],
                         'test4')
        self.assertEqual(task.results[0][ValidationTask.ERROR],
                         'Outside quota tolerance')
        self.assertEqual(task.results[1][ValidationTask.ELECTORATE_ID], 4)
        self.assertEqual(task.results[1][ValidationTask.ELECTORATE_NAME],
                         'test4')
        self.assertEqual(task.results[1][ValidationTask.ERROR],
                         'Electorate has less parts than expected')
        self.assertEqual(task.results[2][ValidationTask.ELECTORATE_ID], 5)
        self.assertEqual(task.results[2][ValidationTask.ELECTORATE_NAME],
                         'test5')
        self.assertEqual(task.results[2][ValidationTask.ERROR],
                         'Outside quota tolerance')
        self.assertEqual(task.results[3][ValidationTask.ELECTORATE_ID], 5)
        self.assertEqual(task.results[3][ValidationTask.ELECTORATE_NAME],
                         'test5')
        self.assertEqual(task.results[3][ValidationTask.ERROR],
                         'Electorate is non-contiguous')
        self.assertEqual(
            task.results[3][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'MultiPoint ((8 9),(10 11))')
        self.assertEqual(task.results[4][ValidationTask.ELECTORATE_ID], 5)
        self.assertEqual(task.results[4][ValidationTask.ELECTORATE_NAME],
                         'test5')
        self.assertEqual(task.results[4][ValidationTask.ERROR],
                         'Contiguous part 1')
        self.assertEqual(
            task.results[4][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'Point (8 9)')
        self.assertEqual(task.results[5][ValidationTask.ELECTORATE_ID], 5)
        self.assertEqual(task.results[5][ValidationTask.ELECTORATE_NAME],
                         'test5')
        self.assertEqual(task.results[5][ValidationTask.ERROR],
                         'Contiguous part 2')
        self.assertEqual(
            task.results[5][ValidationTask.ELECTORATE_GEOMETRY].asWkt(0),
            'Point (10 11)')
        self.assertEqual(task.results[6][ValidationTask.ELECTORATE_ID], 6)
        self.assertEqual(task.results[6][ValidationTask.ELECTORATE_NAME],
                         'test6')
        self.assertEqual(task.results[6][ValidationTask.ERROR],
                         'Outside quota tolerance')
        self.assertEqual([
            f.attributes()[:9] for f in electorate_layer.getFeatures()
        ], [[1, 'test1', 'GN', 58900, 1, 0, 0, NULL, NULL],
            [
                2, 'test2', 'GN', 1, 0, 0, 1, 'Electorate is non-contiguous',
                NULL
            ], [3, 'test3', 'GN', 1, 0, 0, 1, 'Outside quota tolerance', NULL],
            [
                4, 'test4', 'GS', 1, 0, 0, 1,
                'Electorate has less parts than expected', NULL
            ],
            [
                5, 'test5', 'GS', 1, 0, 0, 1, 'Electorate is non-contiguous',
                NULL
            ], [6, 'test6', 'GS', 1, 0, 0, 1, 'Outside quota tolerance', NULL],
            [7, 'test7', 'M', 1, 0, 1, 1, 'old invalid 7', NULL],
            [8, 'test8', 'M', 1, 0, 1, 1, 'old invalid 8', NULL]])

        electorate_registry = LinzElectoralDistrictRegistry(
            source_layer=electorate_layer,
            source_field='electorate_id',
            title_field='code',
            electorate_type='M',
            quota_layer=quota_layer)

        task = ValidationTask(task_name='',
                              electorate_registry=electorate_registry,
                              meshblock_layer=meshblock_layer,
                              meshblock_number_field_name='MeshblockNumber',
                              scenario_registry=reg,
                              scenario=1,
                              task='M')

        self.assertTrue(task.run())
        self.assertEqual(len(task.results), 1)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_ID], 7)
        self.assertEqual(task.results[0][ValidationTask.ELECTORATE_NAME],
                         'test7')
        self.assertEqual(task.results[0][ValidationTask.ERROR],
                         'Deprecated electorate has meshblocks assigned')
        self.assertEqual([
            f.attributes()[:9] for f in electorate_layer.getFeatures()
        ], [[1, 'test1', 'GN', 58900, 1, 0, 0, NULL, NULL],
            [
                2, 'test2', 'GN', 1, 0, 0, 1, 'Electorate is non-contiguous',
                NULL
            ], [3, 'test3', 'GN', 1, 0, 0, 1, 'Outside quota tolerance', NULL],
            [
                4, 'test4', 'GS', 1, 0, 0, 1,
                'Electorate has less parts than expected', NULL
            ],
            [
                5, 'test5', 'GS', 1, 0, 0, 1, 'Electorate is non-contiguous',
                NULL
            ], [6, 'test6', 'GS', 1, 0, 0, 1, 'Outside quota tolerance', NULL],
            [
                7, 'test7', 'M', 1, 0, 1, 1,
                'Deprecated electorate has meshblocks assigned', NULL
            ], [8, 'test8', 'M', 0, 1, 1, 0, NULL, NULL]])
    def testExportTask(self):  # pylint: disable=too-many-locals, too-many-statements
        """
        Test export task
        """
        layer = make_scenario_layer()
        mb_electorate_layer = QgsVectorLayer(
            "NoGeometry?field=id:int&field=scenario_id:int&field=meshblock_number:int&field=gn_id:int&field=gs_id:int&field=m_id:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes([1, 1, 11, 1, 0, 7])
        f2 = QgsFeature()
        f2.setAttributes([2, 1, 12, 2, 0, 7])
        f3 = QgsFeature()
        f3.setAttributes([3, 1, 13, 2, 0, 7])
        f4 = QgsFeature()
        f4.setAttributes([4, 1, 14, 3, 4, 8])
        f5 = QgsFeature()
        f5.setAttributes([5, 1, 15, 0, 5, 8])
        f6 = QgsFeature()
        f6.setAttributes([6, 1, 16, 0, 5, 8])
        mb_electorate_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6])

        reg = ScenarioRegistry(
            source_layer=layer,
            id_field='id',
            name_field='name',
            meshblock_electorate_layer=mb_electorate_layer
        )
        electorate_layer = QgsVectorLayer(
            "Point?crs=EPSG:4326&field=electorate_id:int&field=code:string&field=type:string&field=estimated_pop:int&field=scenario_id:int&field=deprecated:int&field=invalid:int&field=invalid_reason:string&field=name:string&field=stats_nz_pop:int&field=stats_nz_var_20:int&field=stats_nz_var_23:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes([1, "test1", 'GN', 1, 0, 0, 1, 'old invalid'])
        f2 = QgsFeature()
        f2.setAttributes([2, "test2", 'GN', 1, 0, 0, 1, 'old invalid 2'])
        f3 = QgsFeature()
        f3.setAttributes([3, "test3", 'GN', 1, 0, 0, 1, 'old invalid 3'])
        f4 = QgsFeature()
        f4.setAttributes([4, "test4", 'GS', 1, 0, 0, 1, 'old invalid 4'])
        f5 = QgsFeature()
        f5.setAttributes([5, "test5", 'GS', 1, 0, 0, 1, 'old invalid 5'])
        f6 = QgsFeature()
        f6.setAttributes([6, "test6", 'GS', 1, 0, 0, 1, 'old invalid 6'])
        f7 = QgsFeature()
        f7.setAttributes([7, "test7", 'M', 1, 0, 0, 1, 'old invalid 7'])
        f8 = QgsFeature()
        f8.setAttributes([8, "test8", 'M', 1, 0, 0, 1, 'old invalid 8'])
        electorate_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6, f7, f8])

        meshblock_layer = QgsVectorLayer(
            "Polygon?crs=EPSG:4326&field=MeshblockNumber:string&field=offline_pop_m:int&field=offline_pop_gn:int&field=offline_pop_gs:int&field=staged_electorate:int&field=offshore:int",
            "source", "memory")
        f = QgsFeature()
        f.setAttributes(["11", 5, 58900, 0])
        f.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        f2 = QgsFeature()
        f2.setAttributes(["12", 6, 57000, 0])
        f2.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        f3 = QgsFeature()
        f3.setAttributes(["13", 7, 2000, 0])
        f3.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        f4 = QgsFeature()
        f4.setAttributes(["14", 8, 0, 20])
        f4.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        f5 = QgsFeature()
        f5.setAttributes(["15", 9, 0, 30])
        f5.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        f6 = QgsFeature()
        f6.setAttributes(["16", 10, 0, 40])
        f6.setGeometry(QgsGeometry.fromWkt('Polygon((1 1, 2 1, 2 2, 1 2, 1 1))'))
        self.assertTrue(meshblock_layer.dataProvider().addFeatures([f, f2, f3, f4, f5, f6]))

        quota_layer = make_quota_layer()
        user_log_layer = make_user_log_layer()
        f = QgsFeature()
        f.setAttributes([1, NULL, 'user', 'v1', 1, '11', 'GN', 1, 2])
        user_log_layer.dataProvider().addFeature(f)

        electorate_registry = LinzElectoralDistrictRegistry(source_layer=electorate_layer, source_field='electorate_id',
                                                            title_field='code', electorate_type='GN',
                                                            quota_layer=quota_layer)

        out_file = '/tmp/test.gpkg'
        task = ExportTask(task_name='', dest_file=out_file, electorate_registry=electorate_registry,
                          meshblock_layer=meshblock_layer,
                          meshblock_number_field_name='MeshblockNumber', scenario_registry=reg, scenario=1,
                          user_log_layer=user_log_layer)

        self.assertTrue(task.run(), task.message)

        out_electorate_layer = QgsVectorLayer('{}|layername=electorates'.format(out_file), 'electorates', 'ogr')
        self.assertTrue(out_electorate_layer.isValid())
        self.assertEqual([f.attributes() for f in out_electorate_layer.getFeatures()], [[1, 'GN', 'test1', NULL],
                                                                                        [2, 'GN', 'test2', NULL],
                                                                                        [3, 'GN', 'test3', NULL],
                                                                                        [4, 'GS', 'test4', NULL],
                                                                                        [5, 'GS', 'test5', NULL],
                                                                                        [6, 'M', 'test7', NULL],
                                                                                        [7, 'M', 'test8', NULL]])
        self.assertEqual([f.geometry().asWkt() for f in out_electorate_layer.getFeatures()],
                         ['Polygon ((1 1, 2 1, 2 2, 1 2, 1 1))',
                          'Polygon ((2 1, 1 1, 1 2, 2 2, 2 1))',
                          'Polygon ((1 1, 2 1, 2 2, 1 2, 1 1))',
                          'Polygon ((1 1, 2 1, 2 2, 1 2, 1 1))',
                          'Polygon ((2 1, 1 1, 1 2, 2 2, 2 1))',
                          'Polygon ((2 1, 1 1, 1 2, 2 2, 2 1))',
                          'Polygon ((2 1, 1 1, 1 2, 2 2, 2 1))'])
        out_mb_layer = QgsVectorLayer('{}|layername=meshblocks'.format(out_file), 'electorates', 'ogr')
        self.assertTrue(out_mb_layer.isValid())
        self.assertEqual([f.attributes() for f in out_mb_layer.getFeatures()], [[1, 11, 'test1', NULL, 'test7'],
                                                                                [2, 12, 'test2', NULL, 'test7'],
                                                                                [3, 13, 'test2', NULL, 'test7'],
                                                                                [4, 14, 'test3', 'test4', 'test8'],
                                                                                [5, 15, NULL, 'test5', 'test8'],
                                                                                [6, 16, NULL, 'test5', 'test8']])
        out_log_layer = QgsVectorLayer('{}|layername=user_log'.format(out_file), 'electorates', 'ogr')
        self.assertTrue(out_log_layer.isValid())
        self.assertEqual([f.attributes() for f in out_log_layer.getFeatures()],
                         [[1, 1, NULL, 'user', 'v1', 1, '11', 'GN', 1, 2]])
    def testCopyScenarios(self):
        """
        Test copying scenarios between registries
        """
        layer1 = make_scenario_layer()
        mb_electorate_layer1 = make_meshblock_electorate_layer()

        reg1 = ScenarioRegistry(
            source_layer=layer1,
            id_field='id',
            name_field='name',
            meshblock_electorate_layer=mb_electorate_layer1)

        layer2 = make_scenario_layer()
        layer2.dataProvider().truncate()
        mb_electorate_layer2 = make_meshblock_electorate_layer()
        mb_electorate_layer2.dataProvider().truncate()

        reg2 = ScenarioRegistry(
            source_layer=layer2,
            id_field='id',
            name_field='name',
            meshblock_electorate_layer=mb_electorate_layer2)
        self.assertEqual(layer2.featureCount(), 0)
        self.assertEqual(mb_electorate_layer2.featureCount(), 0)

        res, error = reg2.import_scenario_from_other_registry(
            source_registry=reg1,
            source_scenario_id=-1,
            new_scenario_name='copied scenario')
        self.assertFalse(res)
        self.assertIn('does not exist ', error)

        # good params
        res, error = reg2.import_scenario_from_other_registry(
            source_registry=reg1,
            source_scenario_id=1,
            new_scenario_name='copied scenario')
        self.assertTrue(res)
        self.assertFalse(error)
        self.assertEqual(layer2.featureCount(), 1)
        self.assertEqual(mb_electorate_layer2.featureCount(), 2)
        f = [f for f in layer2.getFeatures()][-1]
        self.assertEqual(f[0], res)
        self.assertEqual(f[1], 'copied scenario')
        self.assertEqual(f[2].date(), QDate(2018, 6, 4))
        self.assertEqual(f[3], 'user 1')

        f = [f.attributes() for f in mb_electorate_layer2.getFeatures()]
        self.assertEqual(f, [[3, res, 0, 'c', 'z'], [4, res, 1, 'd', 'zz']])

        res2, error = reg2.import_scenario_from_other_registry(
            source_registry=reg1,
            source_scenario_id=2,
            new_scenario_name='copied scenario 2')
        self.assertTrue(res2)
        self.assertFalse(error)
        self.assertEqual(layer2.featureCount(), 2)
        self.assertEqual(mb_electorate_layer2.featureCount(), 4)
        f = [f for f in layer2.getFeatures()][-1]
        self.assertEqual(f[0], res2)
        self.assertEqual(f[1], 'copied scenario 2')
        self.assertEqual(f[2].date(), QDate(2018, 7, 5))
        self.assertEqual(f[3], 'user 2')

        f = [f.attributes() for f in mb_electorate_layer2.getFeatures()]
        self.assertEqual(f, [[3, res, 0, 'c', 'z'], [4, res, 1, 'd', 'zz'],
                             [1, res2, 0, 'a', 'x'], [2, res2, 1, 'b', 'y']])

        # dupe name
        res, error = reg2.import_scenario_from_other_registry(
            source_registry=reg1,
            source_scenario_id=-1,
            new_scenario_name='copied scenario')
        self.assertFalse(res)
        self.assertIn('already exists', error)
Exemplo n.º 25
0
    def __init__(
            self,
            task_name: str,
            electorate_layer: QgsVectorLayer,
            meshblock_layer: QgsVectorLayer,  # pylint: disable=too-many-locals, too-many-statements
            meshblock_number_field_name: str,
            scenario_registry: ScenarioRegistry,
            scenario,
            task: Optional[str] = None):
        """
        Constructor for ScenarioSwitchTask
        :param task_name: user-visible, translated name for task
        :param electorate_layer: electorate layer
        :param meshblock_layer: meshblock layer
        :param meshblock_number_field_name: name of meshblock number field
        :param scenario_registry: scenario registry
        :param scenario: target scenario id to switch to
        :param task: current redistricting task
        """
        super().__init__(task_name)

        self.scenario = scenario
        self.electorate_layer = electorate_layer
        self.task = task

        self.type_idx = electorate_layer.fields().lookupField('type')
        assert self.type_idx >= 0
        self.scenario_id_idx = electorate_layer.fields().lookupField(
            'scenario_id')
        assert self.scenario_id_idx >= 0
        self.estimated_pop_idx = electorate_layer.fields().lookupField(
            'estimated_pop')
        assert self.estimated_pop_idx >= 0
        self.mb_number_idx = scenario_registry.meshblock_electorate_layer.fields(
        ).lookupField('meshblock_number')
        assert self.mb_number_idx >= 0
        self.mb_off_pop_m_idx = meshblock_layer.fields().lookupField(
            'offline_pop_m')
        assert self.mb_off_pop_m_idx >= 0
        self.mb_off_pop_ni_idx = meshblock_layer.fields().lookupField(
            'offline_pop_gn')
        assert self.mb_off_pop_ni_idx >= 0
        self.mb_off_pop_si_idx = meshblock_layer.fields().lookupField(
            'offline_pop_gs')
        assert self.mb_off_pop_si_idx >= 0
        self.mb_offshore_idx = meshblock_layer.fields().lookupField('offshore')
        assert self.mb_offshore_idx >= 0

        self.invalid_reason_idx = self.electorate_layer.fields().lookupField(
            'invalid_reason')
        assert self.invalid_reason_idx >= 0
        self.invalid_idx = self.electorate_layer.fields().lookupField(
            'invalid')
        assert self.invalid_idx >= 0

        electorate_id_idx = electorate_layer.fields().lookupField(
            'electorate_id')
        assert electorate_id_idx >= 0
        self.code_idx = electorate_layer.fields().lookupField('code')
        assert self.code_idx >= 0
        self.name_idx = electorate_layer.fields().lookupField('name')
        assert self.name_idx >= 0
        self.meshblock_number_idx = meshblock_layer.fields().lookupField(
            meshblock_number_field_name)
        assert self.meshblock_number_idx >= 0

        # do a bit of preparatory processing on the main thread for safety

        # dict of meshblock number to feature
        meshblocks = {}
        for m in meshblock_layer.getFeatures():
            meshblocks[int(m[self.meshblock_number_idx])] = m

        # dict of electorates to process (by id)
        self.electorates_to_process = {}
        request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
        request.setSubsetOfAttributes(
            [electorate_id_idx, self.type_idx, self.code_idx, self.name_idx])
        for electorate in electorate_layer.getFeatures(request):
            # get meshblocks for this electorate in the target scenario
            electorate_id = electorate[electorate_id_idx]
            electorate_type = electorate[self.type_idx]
            electorate_code = electorate[self.code_idx]
            electorate_name = electorate[self.name_idx]
            if self.task and electorate_type != self.task:
                continue

            electorate_meshblocks = scenario_registry.electorate_meshblocks(
                electorate_id=electorate_id,
                electorate_type=electorate_type,
                scenario_id=scenario)
            assigned_meshblock_numbers = [
                m[self.mb_number_idx] for m in electorate_meshblocks
            ]
            matching_meshblocks = [
                meshblocks[m] for m in assigned_meshblock_numbers
            ]
            offshore_meshblocks = [
                m for m in matching_meshblocks if m[self.mb_offshore_idx]
            ]
            non_offshore_meshblocks = [
                m for m in matching_meshblocks if not m[self.mb_offshore_idx]
            ]

            self.electorates_to_process[electorate_id] = {
                self.ELECTORATE_FEATURE_ID: electorate.id(),
                self.ELECTORATE_TYPE: electorate_type,
                self.ELECTORATE_CODE: electorate_code,
                self.ELECTORATE_NAME: electorate_name,
                self.MESHBLOCKS: matching_meshblocks,
                self.OFFSHORE_MESHBLOCKS: offshore_meshblocks,
                self.NON_OFFSHORE_MESHBLOCKS: non_offshore_meshblocks
            }

        self.setDependentLayers([electorate_layer])
    def testElectorateMeshblocks(self):
        """
        Test retrieving meshblocks belong to an electorate for a scenario
        """
        layer = make_scenario_layer()
        mb_electorate_layer = make_meshblock_electorate_layer()

        reg = ScenarioRegistry(source_layer=layer,
                               id_field='id',
                               name_field='name',
                               meshblock_electorate_layer=mb_electorate_layer)

        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='c', electorate_type='GN', scenario_id=1)
        ]
        self.assertEqual(res, [0])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='d', electorate_type='GN', scenario_id=1)
        ]
        self.assertEqual(res, [1])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='a', electorate_type='GN', scenario_id=1)
        ]
        self.assertEqual(res, [])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='z', electorate_type='GS', scenario_id=1)
        ]
        self.assertEqual(res, [0])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='zz', electorate_type='GS', scenario_id=1)
        ]
        self.assertEqual(res, [1])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='x', electorate_type='GS', scenario_id=1)
        ]
        self.assertEqual(res, [])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='a', electorate_type='GN', scenario_id=2)
        ]
        self.assertEqual(res, [0])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='b', electorate_type='GN', scenario_id=2)
        ]
        self.assertEqual(res, [1])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='c', electorate_type='GN', scenario_id=2)
        ]
        self.assertEqual(res, [])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='x', electorate_type='GS', scenario_id=2)
        ]
        self.assertEqual(res, [0])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='y', electorate_type='GS', scenario_id=2)
        ]
        self.assertEqual(res, [1])
        res = [
            f['meshblock_number'] for f in reg.electorate_meshblocks(
                electorate_id='z', electorate_type='GS', scenario_id=2)
        ]
        self.assertEqual(res, [])