<commit_before>from devilry.apps.core.testhelper import TestHelper

from .base import SubjectAdminSeleniumTestCase

class RelatedUsersUITestMixin(object):
    def find_element(self, cssselector):
        return self.selenium.find_element_by_css_selector('.devilry_subjectadmin_relatedusers {0}'.format(cssselector))
    def find_elements(self, cssselector):
        return self.selenium.find_elements_by_css_selector('.devilry_subjectadmin_relatedusers {0}'.format(cssselector))

    def waitForGridRowCount(self, count):
        self.waitFor(self.selenium, lambda s: len(self.find_gridrows()) == count)

    def find_gridrows(self):
        return self.find_elements('.devilry_subjectadmin_relatedusergrid .x-grid-row')

    def get_row_by_username(self, username):
        cssselector = '.relateduser_username_{username}'.format(username=username)
        self.waitForCssSelector('.x-grid-row {0}'.format(cssselector))
        for row in self.find_gridrows():
            matches = row.find_elements_by_css_selector(cssselector)
            if len(matches) > 0:
                return row
        raise ValueError('Could not find any rows matching the following username: {0}.'.format(username))

    def click_row_by_username(self, username, add_to_selection=True):
        self.get_row_by_username(username).click()

    def get_row_data(self, row):
        result = {}
        result['full_name'] = row.find_element_by_css_selector('.meta_cell .full_name').text.strip()
        result['username'] = row.find_element_by_css_selector('.meta_cell .username').text.strip()
        result['tags'] = row.find_element_by_css_selector('.tags_cell').text.strip()
        return result

    def click_add_related_user_button(self):
        self.waitForCssSelector('.add_related_user_button')
        addbutton = self.find_element('.add_related_user_button')
        addbutton.click()

    def ui_add_related_user(self, username):
        usersearchfield = self.find_element('.devilry_subjectadmin_selectrelateduserpanel input[type=text]')
        self.click_add_related_user_button()
        self.waitForDisplayed(usersearchfield)
        usersearchfield.send_keys(username)
        match = self.waitForAndFindElementByCssSelector('.autocompleteuserwidget_matchlist .matchlistitem_{0}'.format(username))
        match.click()
        self.waitForNotDisplayed(usersearchfield)
        self.waitForCssSelector('.alert-success')
        user = getattr(self.testhelper, username)
        displayname = user.devilryuserprofile.full_name or user.username
        self.waitForText('{0} added'.format(displayname))

    def click_remove_button(self):
        removebutton = self.waitForAndFindElementByCssSelector('.remove_related_user_button button')
        removebutton.click()

    def ui_remove_related_users(self, *usernames):
        displaynames = []
        for username in usernames:
            self.click_row_by_username(username)
            user = getattr(self.testhelper, username)
            displayname = user.devilryuserprofile.full_name or user.username
            displaynames = []
        self.click_remove_button()
        removeconfirmbutton = self.find_element('.removeconfirmpanel .okbutton button')
        self.waitForDisplayed(removeconfirmbutton)
        removeconfirmbutton.click()
        self.waitForText('Removed: {0}'.format(', '.join(displaynames)))

    def click_tagbutton(self, action):
        tagsbutton = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_relatedusers .related_users_tags_button')
        tagsbutton.click()
        cssselector = '.{0}_tags_button'.format(action)
        button = self.waitForAndFindElementByCssSelector(cssselector)
        self.waitForDisplayed(button)
        button.click()
        cssselector = '.devilry_subjectadmin_relatedusers .{0}_tags_panel'.format(action)
        panel = self.waitForAndFindElementByCssSelector(cssselector)
        self.waitForDisplayed(panel)
        return panel

    def ui_set_or_add_tags(self, action, tags):
        panel = self.click_tagbutton(action)
        textarea = panel.find_element_by_css_selector('textarea')
        textarea.send_keys(','.join(tags))
        savebutton = panel.find_element_by_css_selector('.choosetags_savebutton button')
        self.waitForEnabled(savebutton)
        savebutton.click()
        self.waitForCssSelector('.alert-success')
        self.waitForText('with: {0}'.format(', '.join(tags)))

    def ui_set_or_add_tags_cancel(self, action):
        panel = self.click_tagbutton(action)
        cancelbutton = panel.find_element_by_css_selector('.choosetags_cancelbutton button')
        self.waitForEnabled(cancelbutton)
        cancelbutton.click()
        helpbox = self.getHelpBox()
        self.waitForDisplayed(helpbox)

    def ui_clear_tags(self):
        panel = self.click_tagbutton('clear')
        okbutton = panel.find_element_by_css_selector('.okbutton')
        self.waitForDisplayed(okbutton)
        okbutton.click()
        self.waitForCssSelector('.alert-success')
        self.waitForText('Cleared tags on')

    def getHelpBox(self):
        return self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_relatedusers .related_user_helpbox')

class TestRelatedStudentsUI(SubjectAdminSeleniumTestCase, RelatedUsersUITestMixin):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:admin(p1admin)'])
        self.period = self.testhelper.sub_p1

    def _browseToManageStudentsAs(self, username, period_id):
        path = '/period/{0}/@@relatedstudents'.format(period_id)
        self.loginTo(username, path)
        self.waitForCssSelector('.devilry_subjectadmin_relatedstudents')

    def _add_relatedstudent(self, username, full_name=None, tags='', candidate_id=None):
        user = self.testhelper.create_user(username, fullname=full_name)
        self.period.relatedstudent_set.create(user=user,
                                              tags=tags,
                                              candidate_id=candidate_id)

    def test_render(self):
        self._add_relatedstudent('student1', full_name='Student One',
                                 tags='a,b',
                                 candidate_id='SEC-RET')
        self._add_relatedstudent('student2')
        self._add_relatedstudent('student3', full_name='Student Three')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(3)
        self.assertEquals(self.get_row_data(self.get_row_by_username('student1')),
                          {'full_name': 'Student One',
                           'username': 'student1',
                           'tags': 'a,b'})
        self.assertEquals(self.get_row_data(self.get_row_by_username('student2')),
                          {'full_name': 'Full name missing',
                           'username': 'student2',
                           'tags': ''})
        self.assertEquals(self.get_row_data(self.get_row_by_username('student3')),
                          {'full_name': 'Student Three',
                           'username': 'student3',
                           'tags': ''})

    def test_invalid_period_id(self):
        self._browseToManageStudentsAs('p1admin', 1000000)
        self.waitFor(self.selenium, lambda s: len(s.find_elements_by_css_selector('.devilry_extjsextras_alertmessage')) == 1)
        for message in self.find_elements('.devilry_extjsextras_alertmessage'):
            self.assertIn('Permission denied', message.text.strip())

    def test_add_student(self):
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_selectrelateduserpanel')
        self.testhelper.create_user('student1')
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())

        self.ui_add_related_user('student1')
        self.waitForGridRowCount(1)
        self.assertTrue(self.period.relatedstudent_set.filter(user__username='student1').exists())

    def test_add_student_cancel(self):
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_selectrelateduserpanel')
        self.testhelper.create_user('student1')
        self.ui_add_related_user('student1')
        self.click_add_related_user_button()
        cancelbutton = self.find_element('.devilry_subjectadmin_selectrelateduserpanel .cancelbutton button')
        self.waitForDisplayed(cancelbutton)
        cancelbutton.click()
        self.waitForNotDisplayed(cancelbutton)

    def test_remove_single(self):
        self._add_relatedstudent('student1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(1)
        self.ui_remove_related_users('student1')
        self.waitForGridRowCount(0)
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())

    def test_remove_many(self):
        self._add_relatedstudent('student1')
        self._add_relatedstudent('student2', full_name='Student Two')
        self._add_relatedstudent('student3', full_name='Student Three')
        self._add_relatedstudent('ignored', full_name='Ignored student')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(4)
        self.ui_remove_related_users('student1', 'student2', 'student3')
        self.waitForGridRowCount(1)
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student2').exists())
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student3').exists())
        self.assertTrue(self.period.relatedstudent_set.filter(user__username='ignored').exists())

    def test_remove_enable_disable(self):
        self._add_relatedstudent('student1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        removebutton = self.waitForAndFindElementByCssSelector('.remove_related_user_button button')
        self.assertFalse(removebutton.is_enabled())
        self.click_row_by_username('student1')
        self.waitForEnabled(removebutton)
        self.click_row_by_username('student1')
        self.waitForDisabled(removebutton)

    def test_add_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='a,b')
        self._add_relatedstudent('ignored', tags='unchanged')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags('add', ['bad', 'supergood', 'awesome'])

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'a,b,bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='ignored').tags,
                          'unchanged')

    def test_add_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags_cancel('add')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')

    def test_set_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='a,b')
        self._add_relatedstudent('ignored', tags='unchanged')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags('set', ['bad', 'supergood', 'awesome'])

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='ignored').tags,
                          'unchanged')

    def test_set_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags_cancel('set')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')

    def test_clear_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_clear_tags()
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          '')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          '')

    def test_clear_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')

        panel = self.click_tagbutton('clear')
        cancelbutton = panel.find_element_by_css_selector('.cancelbutton')
        self.waitForDisplayed(cancelbutton)
        cancelbutton.click()

        helpbox = self.getHelpBox()
        self.waitForDisplayed(helpbox)

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')
<commit_msg>devilry_subjectadmin.tests.relatedusersui: Fixed minor issue.<commit_after>from devilry.apps.core.testhelper import TestHelper

from .base import SubjectAdminSeleniumTestCase

class RelatedUsersUITestMixin(object):
    def find_element(self, cssselector):
        return self.selenium.find_element_by_css_selector('.devilry_subjectadmin_relatedusers {0}'.format(cssselector))
    def find_elements(self, cssselector):
        return self.selenium.find_elements_by_css_selector('.devilry_subjectadmin_relatedusers {0}'.format(cssselector))

    def waitForGridRowCount(self, count):
        self.waitFor(self.selenium, lambda s: len(self.find_gridrows()) == count)

    def find_gridrows(self):
        return self.find_elements('.devilry_subjectadmin_relatedusergrid .x-grid-row')

    def get_row_by_username(self, username):
        cssselector = '.relateduser_username_{username}'.format(username=username)
        self.waitForCssSelector('.x-grid-row {0}'.format(cssselector))
        for row in self.find_gridrows():
            matches = row.find_elements_by_css_selector(cssselector)
            if len(matches) > 0:
                return row
        raise ValueError('Could not find any rows matching the following username: {0}.'.format(username))

    def click_row_by_username(self, username, add_to_selection=True):
        self.get_row_by_username(username).click()

    def get_row_data(self, row):
        result = {}
        result['full_name'] = row.find_element_by_css_selector('.meta_cell .full_name').text.strip()
        result['username'] = row.find_element_by_css_selector('.meta_cell .username').text.strip()
        result['tags'] = row.find_element_by_css_selector('.tags_cell').text.strip()
        return result

    def click_add_related_user_button(self):
        self.waitForCssSelector('.add_related_user_button')
        addbutton = self.find_element('.add_related_user_button')
        addbutton.click()

    def ui_add_related_user(self, username):
        usersearchfield = self.find_element('.devilry_subjectadmin_selectrelateduserpanel input[type=text]')
        self.click_add_related_user_button()
        self.waitForDisplayed(usersearchfield)
        usersearchfield.send_keys(username)
        match = self.waitForAndFindElementByCssSelector('.autocompleteuserwidget_matchlist .matchlistitem_{0}'.format(username))
        match.click()
        self.waitForNotDisplayed(usersearchfield)
        self.waitForCssSelector('.alert-success')
        user = getattr(self.testhelper, username)
        displayname = user.devilryuserprofile.full_name or user.username
        self.waitForText('{0} added'.format(displayname))

    def click_remove_button(self):
        removebutton = self.waitForAndFindElementByCssSelector('.remove_related_user_button button')
        removebutton.click()

    def ui_remove_related_users(self, *usernames):
        displaynames = []
        for username in usernames:
            self.click_row_by_username(username)
            user = getattr(self.testhelper, username)
            displayname = user.devilryuserprofile.full_name or user.username
            displaynames = []
        self.click_remove_button()
        removeconfirmbutton = self.find_element('.removeconfirmpanel .okbutton button')
        self.waitForDisplayed(removeconfirmbutton)
        removeconfirmbutton.click()
        self.waitForText('Removed: {0}'.format(', '.join(displaynames)))

    def click_tagbutton(self, action):
        tagsbutton = self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_relatedusers .related_users_tags_button')
        tagsbutton.click()
        cssselector = '.{0}_tags_button'.format(action)
        button = self.waitForAndFindElementByCssSelector(cssselector)
        self.waitForDisplayed(button)
        button.click()
        cssselector = '.devilry_subjectadmin_relatedusers .{0}_tags_panel'.format(action)
        panel = self.waitForAndFindElementByCssSelector(cssselector)
        self.waitForDisplayed(panel)
        return panel

    def ui_set_or_add_tags(self, action, tags):
        panel = self.click_tagbutton(action)
        textarea = panel.find_element_by_css_selector('textarea')
        textarea.send_keys(','.join(tags))
        savebutton = panel.find_element_by_css_selector('.choosetags_savebutton button')
        self.waitForEnabled(savebutton)
        savebutton.click()
        self.waitForCssSelector('.alert-success')
        self.waitForText('with: {0}'.format(', '.join(tags)))

    def ui_set_or_add_tags_cancel(self, action):
        panel = self.click_tagbutton(action)
        cancelbutton = panel.find_element_by_css_selector('.choosetags_cancelbutton button')
        self.waitForEnabled(cancelbutton)
        cancelbutton.click()
        helpbox = self.getHelpBox()
        self.waitForDisplayed(helpbox)

    def ui_clear_tags(self):
        panel = self.click_tagbutton('clear')
        okbutton = panel.find_element_by_css_selector('.okbutton')
        self.waitForDisplayed(okbutton)
        okbutton.click()
        self.waitForCssSelector('.alert-success')
        self.waitForText('Cleared tags on')

    def getHelpBox(self):
        return self.waitForAndFindElementByCssSelector('.devilry_subjectadmin_relatedusers .related_user_helpbox')

class TestRelatedStudentsUI(SubjectAdminSeleniumTestCase, RelatedUsersUITestMixin):
    def setUp(self):
        self.testhelper = TestHelper()
        self.testhelper.add(nodes='uni',
                            subjects=['sub'],
                            periods=['p1:admin(p1admin)'])
        self.period = self.testhelper.sub_p1

    def _browseToManageStudentsAs(self, username, period_id):
        path = '/period/{0}/@@relatedstudents'.format(period_id)
        self.loginTo(username, path)
        self.waitForCssSelector('.devilry_subjectadmin_relatedstudents')

    def _add_relatedstudent(self, username, full_name=None, tags='', candidate_id=None):
        user = self.testhelper.create_user(username, fullname=full_name)
        self.period.relatedstudent_set.create(user=user,
                                              tags=tags,
                                              candidate_id=candidate_id)

    def test_render(self):
        self._add_relatedstudent('student1', full_name='Student One',
                                 tags='a,b',
                                 candidate_id='SEC-RET')
        self._add_relatedstudent('student2')
        self._add_relatedstudent('student3', full_name='Student Three')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(3)
        self.assertEquals(self.get_row_data(self.get_row_by_username('student1')),
                          {'full_name': 'Student One',
                           'username': 'student1',
                           'tags': 'a,b'})
        self.assertEquals(self.get_row_data(self.get_row_by_username('student2')),
                          {'full_name': 'Full name missing',
                           'username': 'student2',
                           'tags': ''})
        self.assertEquals(self.get_row_data(self.get_row_by_username('student3')),
                          {'full_name': 'Student Three',
                           'username': 'student3',
                           'tags': ''})

    def test_invalid_period_id(self):
        self._browseToManageStudentsAs('p1admin', 1000000)
        def find_permissiondeniedmessage(s):
            for message in self.selenium.find_elements_by_css_selector('.devilry_extjsextras_alertmessage'):
                if 'Permission denied' in message.text.strip():
                    return True
            return False
        self.waitFor(self.selenium, find_permissiondeniedmessage)

    def test_add_student(self):
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_selectrelateduserpanel')
        self.testhelper.create_user('student1')
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())

        self.ui_add_related_user('student1')
        self.waitForGridRowCount(1)
        self.assertTrue(self.period.relatedstudent_set.filter(user__username='student1').exists())

    def test_add_student_cancel(self):
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_selectrelateduserpanel')
        self.testhelper.create_user('student1')
        self.ui_add_related_user('student1')
        self.click_add_related_user_button()
        cancelbutton = self.find_element('.devilry_subjectadmin_selectrelateduserpanel .cancelbutton button')
        self.waitForDisplayed(cancelbutton)
        cancelbutton.click()
        self.waitForNotDisplayed(cancelbutton)

    def test_remove_single(self):
        self._add_relatedstudent('student1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(1)
        self.ui_remove_related_users('student1')
        self.waitForGridRowCount(0)
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())

    def test_remove_many(self):
        self._add_relatedstudent('student1')
        self._add_relatedstudent('student2', full_name='Student Two')
        self._add_relatedstudent('student3', full_name='Student Three')
        self._add_relatedstudent('ignored', full_name='Ignored student')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.waitForCssSelector('.devilry_subjectadmin_relatedusers')
        self.waitForGridRowCount(4)
        self.ui_remove_related_users('student1', 'student2', 'student3')
        self.waitForGridRowCount(1)
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student1').exists())
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student2').exists())
        self.assertFalse(self.period.relatedstudent_set.filter(user__username='student3').exists())
        self.assertTrue(self.period.relatedstudent_set.filter(user__username='ignored').exists())

    def test_remove_enable_disable(self):
        self._add_relatedstudent('student1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        removebutton = self.waitForAndFindElementByCssSelector('.remove_related_user_button button')
        self.assertFalse(removebutton.is_enabled())
        self.click_row_by_username('student1')
        self.waitForEnabled(removebutton)
        self.click_row_by_username('student1')
        self.waitForDisabled(removebutton)

    def test_add_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='a,b')
        self._add_relatedstudent('ignored', tags='unchanged')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags('add', ['bad', 'supergood', 'awesome'])

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'a,b,bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='ignored').tags,
                          'unchanged')

    def test_add_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags_cancel('add')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')

    def test_set_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='a,b')
        self._add_relatedstudent('ignored', tags='unchanged')
        self._browseToManageStudentsAs('p1admin', self.period.id)

        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags('set', ['bad', 'supergood', 'awesome'])

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'bad,supergood,awesome')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='ignored').tags,
                          'unchanged')

    def test_set_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_set_or_add_tags_cancel('set')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')

    def test_clear_tags(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')
        self.ui_clear_tags()
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          '')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          '')

    def test_clear_tags_cancel(self):
        self._add_relatedstudent('student1', tags='good,bad')
        self._add_relatedstudent('student2', tags='group1')
        self._browseToManageStudentsAs('p1admin', self.period.id)
        self.click_row_by_username('student1')
        self.click_row_by_username('student2')

        panel = self.click_tagbutton('clear')
        cancelbutton = panel.find_element_by_css_selector('.cancelbutton')
        self.waitForDisplayed(cancelbutton)
        cancelbutton.click()

        helpbox = self.getHelpBox()
        self.waitForDisplayed(helpbox)

        self.assertEquals(self.period.relatedstudent_set.get(user__username='student1').tags,
                          'good,bad')
        self.assertEquals(self.period.relatedstudent_set.get(user__username='student2').tags,
                          'group1')
<|endoftext|>


<commit_before>#!/usr/bin/python3

import os
import webbrowser
import urllib.parse
import pathlib
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit', '3.0')
from gi.repository import Gtk, WebKit
from get_kmp import get_download_folder, download_kmp_file
from install_kmp import install_kmp
from list_installed_kmp import get_kmp_version

def process_kmp(view, url, downloadfile, verbose=False):
    if verbose:
        print("Downloading file to", downloadfile)
    if download_kmp_file(url, downloadfile, True):
        keyboardid = os.path.basename(os.path.splitext(downloadfile)[0])
        installed_kmp_ver = get_kmp_version(keyboardid)
        if verbose:
            print("File downloaded")
        if installed_kmp_ver:
            pass
        w = InstallKmpWindow(downloadfile)
        w.show_all()
        #install_kmp(downloadfile, True)
        #keyboardid = os.path.basename(os.path.splitext(downloadfile)[0])
        #welcome_file = os.path.join("/usr/local/share/doc/keyman", keyboardid, "welcome.htm")
        #if os.path.isfile(welcome_file):
        #    uri_path = pathlib.Path(welcome_file).as_uri()
        #    view.load_uri(uri_path)
        return True
    return False

def check(view, frame, req, nav, policy):
    uri = req.get_uri()
    parsed = urllib.parse.urlparse(uri)
    if parsed.scheme == "keyman":
        if parsed.path == "download":
            qs = urllib.parse.parse_qs(parsed.query)
            downloadfile = os.path.join(get_download_folder(), qs['filename'][0])
            if process_kmp(view, qs['url'][0], downloadfile, True):
                policy.ignore()
                return True
        elif parsed.path == "link":
            qs = urllib.parse.parse_qs(parsed.query)
            webbrowser.open(qs['url'][0])
            return True
    return False

class InstallKmpWindow(Gtk.Window):

    def __init__(self, kmpfile):
        print("kmpfile:", kmpfile)
        keyboardid = os.path.basename(os.path.splitext(kmpfile)[0])
        windowtitle = "Installing" + keyboardid
        Gtk.Window.__init__(self, title=windowtitle)

        self.set_border_width(3)

        self.notebook = Gtk.Notebook()
        self.add(self.notebook)

        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)
        self.page1.add(Gtk.Label('Details'))
        self.notebook.append_page(self.page1, Gtk.Label('Details'))

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        self.page2.add(Gtk.Label('README'))
        self.notebook.append_page(
            self.page2,
            Gtk.Label('README')
        )

class DownloadKmpWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Keyman keyboard")

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        s = Gtk.ScrolledWindow()
        user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
        #user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
        webview = WebKit.WebView()
        settings = WebKit.WebSettings()
        settings.set_property('user-agent', user_agent)
        webview.set_settings(settings)
        webview.connect("navigation-policy-decision-requested", check)
        webview.load_uri("https://keyman.com/keyboards?embed=macos&version=10")
        #webview.load_uri("https://keyman.com/keyboards?embed=windows&version=10.0")
        #webview.load_uri("https://keyman.com/keyboards?embed=linux&version=11")
        s.add(webview)
        vbox.pack_start(s, True, True, 0)

        hbox = Gtk.Box(spacing=6)
        #hbox.set_halign(Gtk.Align.FILL)
        vbox.pack_start(hbox, False, False, 0)

        #button = Gtk.Button.new_with_label("Click Me")
        #button.connect("clicked", self.on_click_me_clicked)
        #hbox.pack_start(button, False, False, 0)

        #button = Gtk.Button.new_with_mnemonic("_Open")
        #button.connect("clicked", self.on_open_clicked)
        #hbox.pack_start(button, False, False, 0)

        button = Gtk.Button.new_with_mnemonic("_Close")
        button.connect("clicked", self.on_close_clicked)
        hbox.pack_end(button, False, False, 0)

        self.add(vbox)

    #def on_click_me_clicked(self, button):
    #    print("\"Click me\" button was clicked")

    #def on_open_clicked(self, button):
    #    print("\"Open\" button was clicked")

    def on_close_clicked(self, button):
        print("Closing application")
        Gtk.main_quit()

if __name__ == '__main__':
    w = DownloadKmpWindow()
    #w.set_title("Keyman keyboard")
    w.connect("destroy", Gtk.main_quit)
    w.resize(800, 800)
    w.show_all()
Gtk.main()<commit_msg>display readme in confirmation window if avail<commit_after>#!/usr/bin/python3

import os
import webbrowser
import urllib.parse
import pathlib
import tempfile
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('WebKit', '3.0')
from gi.repository import Gtk, WebKit
from get_kmp import get_download_folder, download_kmp_file
from install_kmp import install_kmp, extract_kmp
from list_installed_kmp import get_kmp_version

def process_kmp(view, url, downloadfile, verbose=False):
    if verbose:
        print("Downloading file to", downloadfile)
    if download_kmp_file(url, downloadfile, True):
        if verbose:
            print("File downloaded")

        w = InstallKmpWindow(downloadfile)
        w.show_all()
        #install_kmp(downloadfile, True)
        #keyboardid = os.path.basename(os.path.splitext(downloadfile)[0])
        #welcome_file = os.path.join("/usr/local/share/doc/keyman", keyboardid, "welcome.htm")
        #if os.path.isfile(welcome_file):
        #    uri_path = pathlib.Path(welcome_file).as_uri()
        #    view.load_uri(uri_path)
        return True
    return False

def check(view, frame, req, nav, policy):
    uri = req.get_uri()
    parsed = urllib.parse.urlparse(uri)
    if parsed.scheme == "keyman":
        if parsed.path == "download":
            qs = urllib.parse.parse_qs(parsed.query)
            downloadfile = os.path.join(get_download_folder(), qs['filename'][0])
            if process_kmp(view, qs['url'][0], downloadfile, True):
                policy.ignore()
                return True
        elif parsed.path == "link":
            qs = urllib.parse.parse_qs(parsed.query)
            webbrowser.open(qs['url'][0])
            return True
    return False

class InstallKmpWindow(Gtk.Window):

    def __init__(self, kmpfile):
        print("kmpfile:", kmpfile)
        keyboardid = os.path.basename(os.path.splitext(kmpfile)[0])
        installed_kmp_ver = get_kmp_version(keyboardid)
        windowtitle = "Installing keyboard/package " + keyboardid
        Gtk.Window.__init__(self, title=windowtitle)

        self.set_border_width(3)

        self.page1 = Gtk.Box()
        self.page1.set_border_width(10)

        hbox = Gtk.Box(spacing=10)
        vbox_left = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vbox_left.set_homogeneous(False)
        vbox_right = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        vbox_right.set_homogeneous(False)
        hbox.pack_start(vbox_left, True, True, 0)
        hbox.pack_start(vbox_right, True, True, 0)

        label = Gtk.Label()
        label.set_text("Keyboard layouts:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()
        # Fonts is optional
        label.set_text("Fonts:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()
        label.set_text("Package version:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()
        label.set_text("Author:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()
        # Website is optional
        label.set_text("Website:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()
        label.set_text("Copyright:")
        label.set_justify(Gtk.Justification.RIGHT)
        vbox_left.pack_start(label, True, True, 0)
        label = Gtk.Label()

        self.page1.add(hbox)

        #self.page1.add(Gtk.Label('Details'))

        self.page2 = Gtk.Box()
        self.page2.set_border_width(10)
        s = Gtk.ScrolledWindow()
        webview = WebKit.WebView()
        with tempfile.TemporaryDirectory() as tmpdirname:
            extract_kmp(kmpfile, tmpdirname)
            readme_file = os.path.join(tmpdirname, "readme.htm")
            if os.path.isfile(readme_file):
                readme_uri = pathlib.Path(readme_file).as_uri()
                webview.load_uri(readme_uri)
                s.add(webview)
                self.page2.pack_start(s, True, True, 10)

                self.notebook = Gtk.Notebook()
                self.notebook.set_tab_pos(Gtk.PositionType.BOTTOM)
                self.add(self.notebook)
                self.notebook.append_page(
                    self.page1,
                    Gtk.Label('Details'))
                self.notebook.append_page(
                    self.page2,
                    Gtk.Label('README')
        )
            else:
                self.add(self.page1)
        self.resize(640, 480)

class DownloadKmpWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Keyman keyboard")

        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)

        s = Gtk.ScrolledWindow()
        user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"
        #user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
        webview = WebKit.WebView()
        settings = WebKit.WebSettings()
        settings.set_property('user-agent', user_agent)
        webview.set_settings(settings)
        webview.connect("navigation-policy-decision-requested", check)
        webview.load_uri("https://keyman.com/keyboards?embed=macos&version=10")
        #webview.load_uri("https://keyman.com/keyboards?embed=windows&version=10.0")
        #webview.load_uri("https://keyman.com/keyboards?embed=linux&version=11")
        s.add(webview)
        vbox.pack_start(s, True, True, 0)

        hbox = Gtk.Box(spacing=6)
        #hbox.set_halign(Gtk.Align.FILL)
        vbox.pack_start(hbox, False, False, 0)

        #button = Gtk.Button.new_with_label("Click Me")
        #button.connect("clicked", self.on_click_me_clicked)
        #hbox.pack_start(button, False, False, 0)

        #button = Gtk.Button.new_with_mnemonic("_Open")
        #button.connect("clicked", self.on_open_clicked)
        #hbox.pack_start(button, False, False, 0)

        button = Gtk.Button.new_with_mnemonic("_Close")
        button.connect("clicked", self.on_close_clicked)
        hbox.pack_end(button, False, False, 0)

        self.add(vbox)

    #def on_click_me_clicked(self, button):
    #    print("\"Click me\" button was clicked")

    #def on_open_clicked(self, button):
    #    print("\"Open\" button was clicked")

    def on_close_clicked(self, button):
        print("Closing application")
        Gtk.main_quit()

if __name__ == '__main__':
    w = DownloadKmpWindow()
    #w.set_title("Keyman keyboard")
    w.connect("destroy", Gtk.main_quit)
    w.resize(800, 800)
    w.show_all()
Gtk.main()<|endoftext|>


<commit_before>from subprocess import Popen, PIPE, STDOUT
from signal import signal, SIGPIPE, SIG_DFL
from pysv import utils
signal(SIGPIPE,SIG_DFL)

SAT = 'sat'
UNSAT = 'unsat'
UNKNOWN = 'unknown'
TIMEOUT = 'timeout'

class Solver(object):
    """This solver assumes that z3 command is visible in the path. This is true for standard installation of the z3 solver on Linux machines. SolverCommandZ3 runs z3 command in the shell with appropriate parameters and returns the raw output of this command.
        """

    Z3 = 'z3'
    MathSAT = 'mathsat'
    YICES = 'yices'
    OTHER = 'other'
    supported_solvers = [Z3, MathSAT, YICES, OTHER]

    def __init__(self, env):
        self.env = env
        self.solver_type = env.solver
        self.solver_interactive_mode = env.solver_interactive_mode

    def apply(self, script, other_params=None):
        """Runs a solver and passes the script on the standard input.

        :param script: A script in SMT-LIB 2.0 language.
        :param other_params: Optional parameters for the z3 command.
        :return: SolverResult containing merged output from stdout and stderr.
        """
        if other_params is None:
            other_params = []
        try:
            if self.solver_interactive_mode:
                out_data, err_data = self.run_solver_interactive(script, other_params)
            else:
                out_data, err_data = self.run_solver_once(script, other_params)
        except FileNotFoundError:
            raise FileNotFoundError('Solver binaries not found! Check your solvers_bin folder or --solver_path argument.')
        except Exception:
            raise Exception('Solver could not be executed or critical error occurred!')
        else: # no exception.
            text = self.prepare_apply_output(out_data, err_data)
            return SolverResult(text, self.env, script, text_errors=err_data)

    def run_solver_interactive(self, script, other_params):
        script += '\n'  # To avoid situation that lack of \n at the end makes solver run indefinitely.
        cmd_strings = self.get_cmd_strings(other_params)
        p = Popen(cmd_strings, stdout=PIPE, stdin=PIPE, stderr=STDOUT, universal_newlines=True, bufsize=-1)

        # Asserting all constraints and reading output.
        p.stdin.write(script)
        p.stdin.flush()

        auxiliary_output = ''

        # Reading auxiliary outputs and satisfiability decision.
        line = p.stdout.readline()
        decisions = ['sat', 'unsat', 'unknown']
        solver_abort = False
        i = 0
        while line.rstrip() not in decisions:
            if line == '':
                if p.poll() is not None:
                    solver_abort = True # This will be reached if solver process is killed or it exceeds time limit.
                    break
                i += 1
            else:
                i = 0
            if i >= 100:
                r = p.poll()
                raise Exception("Only empty strings read from the solver's output! Check, if solver process ended without any errors. Solver reply to poll function: " + str(r))
            auxiliary_output += line
            line = p.stdout.readline()
            if line[0:6] == '(error':
                raise Exception("Solver returned error! '" + line.rstrip() +"'")

        if solver_abort:
            return 'timeout\n', ''
        else:
            decision = line
            out = ''
            err = ''
            if decision.rstrip() == 'sat':
                # o2, e2 = self.p.communicate(input='(get-model)')
                code = '(get-model)\n'
                if self.env.produce_assignments:
                    code += '(get-assignment)\n'
                code += '\n(exit)\n'
                p.stdin.write(code)
                p.stdin.flush()
                out = p.stdout.read()

            elif decision.rstrip() == 'unsat':
                if self.env.produce_unsat_core:
                    # o2, e2 = self.p.communicate(input='(get-unsat-core)')
                    p.stdin.write('(get-unsat-core)\n(exit)\n')
                    p.stdin.flush()
                    out = p.stdout.read()

            p.terminate()
            return decision + out, auxiliary_output + err

    def run_solver_once(self, script, other_params):
        cmd_strings = self.get_cmd_strings(other_params)
        p = Popen(cmd_strings, stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True, bufsize=-1)
        return p.communicate(input=script)  # a tuple (stdout, stderr) is returned

    def get_cmd_strings(self, other_params):
        raise Exception('Function get_cmd_strings is not implemented!')

    def prepare_apply_output(self, out_data, err_data):
        res = out_data
        if err_data != '':
            res += '\n' + err_data
        return res

    @staticmethod
    def get_solver_specific_args(solver_type, env, other_args = None):
        if other_args is None:
            other_args = []
        if solver_type == Solver.Z3:
            res = ['-smt2', '-in']
        elif solver_type == Solver.MathSAT:
            res = ['-input=smt2', '-model_generation=TRUE'] #'-model'
        elif solver_type == Solver.YICES:
            res = []
        else:
            res = []
        res.extend(other_args)
        return res

    @staticmethod
    def get_solver_specific_bin_name(solver_type):
        if solver_type == Solver.Z3:
            return 'z3'
        elif solver_type == Solver.MathSAT:
            return 'mathsat'
        elif solver_type == Solver.YICES:
            return 'yices-smt2'
        else:
            return None

class SolverBinaries(Solver):

    def __init__(self, env, solver_name= None, args = None):
        if args is None:
            args = []
        if solver_name is None:
            solver_name = Solver.get_solver_specific_bin_name(env.solver)
        self.args = args
        # self.solver_name = solver_name
        if env.solver_path is not None:
            self.solver_name = env.solver_path
        else:
            import os
            BASE_DIR = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'solvers_bin'))
            self.solver_name = BASE_DIR + os.sep + solver_name
            # print('Solver path: ' + self.solver_name)
        Solver.__init__(self, env)

    def get_cmd_strings(self, other_params):
        cmd = [self.solver_name]
        cmd.extend(Solver.get_solver_specific_args(self.solver_type, self.env, self.args))
        cmd.extend(other_params)
        return cmd

def run_solver(script, env):
    """Runs the SMT-LIB 2.0 script using specified solver."""
    # if env.solver == Solver.Z3:
    #     return SolverCommandZ3(interactive_mode=env.solver_interactive_mode).apply(script)
    if env.solver in Solver.supported_solvers:
        return SolverBinaries(env).apply(script)
    else:
        raise Exception('Chosen solver is not supported!')

class SolverResult(object):
    """Processed synthesis result of the solver.

    Attributes:
    -----------
    text : string
        Raw output of the solver.
    decision : string
        Solver decision: sat, unsat, unsupported or unknown.
    model : dict[string,string]
        Dictionary containing values of all variables present in the model.
    """

    def __init__(self, result, env, script=None, text_errors=""):
        self.env = env
        if isinstance(result, SolverResult):
            self.text = result.text
            self.text_errors = result.text_errors
            self.decision = result.decision
            self.model = result.model.copy()
            self.unsat_core = result.unsat_core[:]
            self.assignments = result.assignments.copy()
            self.script = result.script
            self.was_any_error = result.was_any_error
        else:
            self.text = result
            self.text_errors = text_errors
            self.was_any_error = True if text_errors is not None and text_errors != "" else False
            utils.logger.debug('SolverResult.text = ' + self.text)
            self.decision = SolverResult.get_decision(result)
            self.model = {}
            self.assignments = {}
            self.unsat_core = []
            self.script = script
            if self.decision == 'sat':
                self.model = SolverResult.get_model_values(result)
                if env.produce_assignments:
                    self.assignments = SolverResult.get_assignments(result, env.solver_interactive_mode)
            if self.decision == 'unsat' and env.produce_unsat_core:
                self.unsat_core = SolverResult.get_unsat_core(result, env.solver_interactive_mode, env.produce_assignments)

    def __getitem__(self, var_name):
        return self.model[var_name]

    def __str__(self):
        return self.text

    def str_formatted(self):
        """Returns string in the format declared by the output_data option."""
        if not self.env.silent:
            res  = '----------------------------------------------\n'
            res += 'SOLVER RESULT\n'
            res += '----------------------------------------------\n'
        else:
            res = ''
        for s in self.env.output_data:
            if s == 'raw':
                res += str(self.text) + '\n'
            elif s == 'decision':
                res += str(self.decision) + '\n'
            elif s == 'model':
                res += str(self.model) + '\n'
            elif s == 'unsat_core':
                res += str(self.unsat_core) + '\n'
            elif s == 'assignments':
                res += str(self.assignments) + '\n'
            elif s == 'final_code':
                if not self.env.silent:
                    res += '--------------------------\n'
                    res += 'SYNTHESIZED PYTHON CODE:'
                res += str(self.final_code) + '\n'  # final_code will work only for SynthesisResult subclass.
            elif s == "holes_content":
                res += str(self.holes_content)  # final_code will work only for SynthesisResult subclass.
        return res

    @staticmethod
    def get_decision(text):
        """Returns solver decision: sat, unsat, unsupported or unknown."""
        if text == '':
            return ''
        else:
            return text.split()[0]

    @staticmethod
    def get_model_values(text):
        """Returns dictionary with values assigned to variables."""
        words = utils.str_to_wlist(text)
        if len(words) <= 1:
            raise Exception('Trying to get model while presumably only check-sat was invoked!')

        start = 1
        prefix = words[start] + words[start + 1] # On the i=0 always is a decision.
        if prefix == '(objectives':
            start = utils.index_of_closing_parenthesis(words, start) + 1
            prefix = words[start] + words[start + 1]

        if prefix == '(error' or prefix not in ('(model', '(('):
            return {}
        elif prefix == '(model':
            return SolverResult.get_model_explicit(words[start:])
        elif prefix == '((':
            return SolverResult.get_model_simplified(words[start:])

    @staticmethod
    def get_model_explicit(words):
        model_values = {}
        i = 2
        while i < len(words):
            if words[i] == 'define-fun':
                name = words[i + 1]
                # Usually i+2 and i+3 contains parenthesis, but in some scenarios there may be some values
                # in between. They are ignored here.
                i = utils.index_of_closing_parenthesis(words, i + 2)
                # i+1 is a type of the function
                if words[i + 2] == '(':
                    j = utils.index_of_closing_parenthesis(words, i + 2)
                    value = ' '.join(words[i + 2:j + 1])
                    i = j + 1  # j+1 is closing parenthesis of define-fun
                else:
                    value = words[i + 2]
                    i += 3  # i+3 is closing parenthesis of define-fun
                model_values[name] = value
                assert words[i] == ')'  # i should point to the last parenthesis of define-fun
            i += 1
        return model_values

    @staticmethod
    def get_model_simplified(words):
        # raise Exception('Loading model in the simplified form is not supported yet!')
        model_values = {}
        i = 1
        while i < len(words):
            if words[i] == '(':
                name = words[i + 1]
                # i+1 is a type of the function
                if words[i + 2] == '(':
                    j = utils.index_of_closing_parenthesis(words, i + 2)
                    value = ' '.join(words[i + 2:j + 1])
                    i = j + 1  # j+1 is closing parenthesis
                else:
                    value = words[i + 2]
                    i += 3  # i+3 is closing parenthesis
                model_values[name] = value
                assert words[i] == ')'  # i should point to the last parenthesis of value definition
            i += 1
        return model_values

    @staticmethod
    def get_unsat_core(text, interactive_mode, produce_assignments):
        """Returns unsat-core or empty list if it was not obtainable (e.g. decision was sat)."""
        unsat_core = []
        words = utils.str_to_wlist(text)

        # skip model - NOTE: in the interactive mode there is no need to skip the model
        if not interactive_mode:
            j = utils.index_of_closing_parenthesis(words, 1) + 1 # omit model
            if produce_assignments:
                x = words[j:]
                j = utils.index_of_closing_parenthesis(words, j) + 1 # omit assignments
                x = words[j:]
            if j+1 >= len(words):
                return []
        else:
            j = 1

        prefix = words[j] + words[j+1]
        if prefix == '(error':
            return []
        else:
            while j < len(words):
                if words[j] == '(':
                    pass
                elif words[j] == ')':
                    break
                else:
                    unsat_core.append(words[j])
                j += 1
        return unsat_core

    @staticmethod
    def get_assignments(text, interactive_mode):
        """Returns dictionary of assignments if decision was sat."""
        words = utils.str_to_wlist(text)

        j = 1 # On the j=0 is a decision.
        prefix = words[j] + words[j + 1]
        if prefix == '(objectives':
            j = utils.index_of_closing_parenthesis(words, j) + 1
            prefix = words[j] + words[j + 1]
        if prefix == '(model' or prefix == '((': # skip model - assignments are printed after it.
            j = utils.index_of_closing_parenthesis(words, j) + 1
            prefix = words[j] + words[j + 1]

        if j + 1 >= len(words):
            return []
        elif prefix == '(error':
            return {}
        else:
            return utils.wlist_to_dict_parenthesis(words[j:])<commit_msg>Better exception behavior when solver fails or cannot be found.<commit_after>from __future__ import print_function
import sys
from subprocess import Popen, PIPE, STDOUT
from signal import signal, SIGPIPE, SIG_DFL
from pysv import utils
signal(SIGPIPE,SIG_DFL)

SAT = 'sat'
UNSAT = 'unsat'
UNKNOWN = 'unknown'
TIMEOUT = 'timeout'

class Solver(object):
    """This solver assumes that z3 command is visible in the path. This is true for standard installation of the z3 solver on Linux machines. SolverCommandZ3 runs z3 command in the shell with appropriate parameters and returns the raw output of this command.
        """

    Z3 = 'z3'
    MathSAT = 'mathsat'
    YICES = 'yices'
    OTHER = 'other'
    supported_solvers = [Z3, MathSAT, YICES, OTHER]

    def __init__(self, env):
        self.env = env
        self.solver_type = env.solver
        self.solver_interactive_mode = env.solver_interactive_mode

    def apply(self, script, other_params=None):
        """Runs a solver and passes the script on the standard input.

        :param script: A script in SMT-LIB 2.0 language.
        :param other_params: Optional parameters for the z3 command.
        :return: SolverResult containing merged output from stdout and stderr.
        """
        if other_params is None:
            other_params = []
        try:
            if self.solver_interactive_mode:
                out_data, err_data = self.run_solver_interactive(script, other_params)
            else:
                out_data, err_data = self.run_solver_once(script, other_params)
        except OSError as e:
            print("Solver binaries not found! Check your solvers_bin folder or --solver_path argument.", file=sys.stderr)
            raise e
        except Exception as e:
            print("Solver could not be executed or critical error occurred!", file=sys.stderr)
            raise e
        else: # no exception.
            text = self.prepare_apply_output(out_data, err_data)
            return SolverResult(text, self.env, script, text_errors=err_data)

    def run_solver_interactive(self, script, other_params):
        script += '\n'  # To avoid situation that lack of \n at the end makes solver run indefinitely.
        cmd_strings = self.get_cmd_strings(other_params)
        p = Popen(cmd_strings, stdout=PIPE, stdin=PIPE, stderr=STDOUT, universal_newlines=True, bufsize=-1)

        # Asserting all constraints and reading output.
        p.stdin.write(script)
        p.stdin.flush()

        auxiliary_output = ''

        # Reading auxiliary outputs and satisfiability decision.
        line = p.stdout.readline()
        decisions = ['sat', 'unsat', 'unknown']
        solver_abort = False
        i = 0
        while line.rstrip() not in decisions:
            if line == '':
                if p.poll() is not None:
                    solver_abort = True # This will be reached if solver process is killed or it exceeds time limit.
                    break
                i += 1
            else:
                i = 0
            if i >= 100:
                r = p.poll()
                raise Exception("Only empty strings read from the solver's output! Check, if solver process ended without any errors. Solver reply to poll function: " + str(r))
            auxiliary_output += line
            line = p.stdout.readline()
            if line[0:6] == '(error':
                raise Exception("Solver returned error! '" + line.rstrip() +"'")

        if solver_abort:
            return 'timeout\n', ''
        else:
            decision = line
            out = ''
            err = ''
            if decision.rstrip() == 'sat':
                # o2, e2 = self.p.communicate(input='(get-model)')
                code = '(get-model)\n'
                if self.env.produce_assignments:
                    code += '(get-assignment)\n'
                code += '\n(exit)\n'
                p.stdin.write(code)
                p.stdin.flush()
                out = p.stdout.read()

            elif decision.rstrip() == 'unsat':
                if self.env.produce_unsat_core:
                    # o2, e2 = self.p.communicate(input='(get-unsat-core)')
                    p.stdin.write('(get-unsat-core)\n(exit)\n')
                    p.stdin.flush()
                    out = p.stdout.read()

            p.terminate()
            return decision + out, auxiliary_output + err

    def run_solver_once(self, script, other_params):
        cmd_strings = self.get_cmd_strings(other_params)
        p = Popen(cmd_strings, stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True, bufsize=-1)
        return p.communicate(input=script)  # a tuple (stdout, stderr) is returned

    def get_cmd_strings(self, other_params):
        raise Exception('Function get_cmd_strings is not implemented!')

    def prepare_apply_output(self, out_data, err_data):
        res = out_data
        if err_data != '':
            res += '\n' + err_data
        return res

    @staticmethod
    def get_solver_specific_args(solver_type, env, other_args=None):
        if other_args is None:
            other_args = []
        if solver_type == Solver.Z3:
            res = ['-smt2', '-in']
        elif solver_type == Solver.MathSAT:
            res = ['-input=smt2', '-model_generation=TRUE'] #'-model'
        elif solver_type == Solver.YICES:
            res = []
        else:
            res = []
        res.extend(other_args)
        return res

    @staticmethod
    def get_solver_specific_bin_name(solver_type):
        if solver_type == Solver.Z3:
            return 'z3'
        elif solver_type == Solver.MathSAT:
            return 'mathsat'
        elif solver_type == Solver.YICES:
            return 'yices-smt2'
        else:
            return None

class SolverBinaries(Solver):

    def __init__(self, env, solver_name=None, args=None):
        if args is None:
            args = []
        if solver_name is None:
            solver_name = Solver.get_solver_specific_bin_name(env.solver)
        self.args = args
        # self.solver_name = solver_name
        if env.solver_path is not None:
            self.solver_name = env.solver_path
        else:
            import os
            BASE_DIR = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'solvers_bin'))
            self.solver_name = BASE_DIR + os.sep + solver_name
            # print('Solver path: ' + self.solver_name)
        Solver.__init__(self, env)

    def get_cmd_strings(self, other_params):
        cmd = [self.solver_name]
        cmd.extend(Solver.get_solver_specific_args(self.solver_type, self.env, self.args))
        cmd.extend(other_params)
        return cmd

def run_solver(script, env):
    """Runs the SMT-LIB 2.0 script using specified solver."""
    # if env.solver == Solver.Z3:
    #     return SolverCommandZ3(interactive_mode=env.solver_interactive_mode).apply(script)
    if env.solver in Solver.supported_solvers:
        return SolverBinaries(env).apply(script)
    else:
        raise Exception('Chosen solver is not supported!')

class SolverResult(object):
    """Processed synthesis result of the solver.

    Attributes:
    -----------
    text : string
        Raw output of the solver.
    decision : string
        Solver decision: sat, unsat, unsupported or unknown.
    model : dict[string,string]
        Dictionary containing values of all variables present in the model.
    """

    def __init__(self, result, env, script=None, text_errors=""):
        self.env = env
        if isinstance(result, SolverResult):
            self.text = result.text
            self.text_errors = result.text_errors
            self.decision = result.decision
            self.model = result.model.copy()
            self.unsat_core = result.unsat_core[:]
            self.assignments = result.assignments.copy()
            self.script = result.script
            self.was_any_error = result.was_any_error
        else:
            self.text = result
            self.text_errors = text_errors
            self.was_any_error = True if text_errors is not None and text_errors != "" else False
            utils.logger.debug('SolverResult.text = ' + self.text)
            self.decision = SolverResult.get_decision(result)
            self.model = {}
            self.assignments = {}
            self.unsat_core = []
            self.script = script
            if self.decision == 'sat':
                self.model = SolverResult.get_model_values(result)
                if env.produce_assignments:
                    self.assignments = SolverResult.get_assignments(result, env.solver_interactive_mode)
            if self.decision == 'unsat' and env.produce_unsat_core:
                self.unsat_core = SolverResult.get_unsat_core(result, env.solver_interactive_mode, env.produce_assignments)

    def __getitem__(self, var_name):
        return self.model[var_name]

    def __str__(self):
        return self.text

    def str_formatted(self):
        """Returns string in the format declared by the output_data option."""
        if not self.env.silent:
            res  = '----------------------------------------------\n'
            res += 'SOLVER RESULT\n'
            res += '----------------------------------------------\n'
        else:
            res = ''
        for s in self.env.output_data:
            if s == 'raw':
                res += str(self.text) + '\n'
            elif s == 'decision':
                res += str(self.decision) + '\n'
            elif s == 'model':
                res += str(self.model) + '\n'
            elif s == 'unsat_core':
                res += str(self.unsat_core) + '\n'
            elif s == 'assignments':
                res += str(self.assignments) + '\n'
            elif s == 'final_code':
                if not self.env.silent:
                    res += '--------------------------\n'
                    res += 'SYNTHESIZED PYTHON CODE:'
                res += str(self.final_code) + '\n'  # final_code will work only for SynthesisResult subclass.
            elif s == "holes_content":
                res += str(self.holes_content)  # final_code will work only for SynthesisResult subclass.
        return res

    @staticmethod
    def get_decision(text):
        """Returns solver decision: sat, unsat, unsupported or unknown."""
        if text == '':
            return ''
        else:
            return text.split()[0]

    @staticmethod
    def get_model_values(text):
        """Returns dictionary with values assigned to variables."""
        words = utils.str_to_wlist(text)
        if len(words) <= 1:
            raise Exception('Trying to get model while presumably only check-sat was invoked!')

        start = 1
        prefix = words[start] + words[start + 1] # On the i=0 always is a decision.
        if prefix == '(objectives':
            start = utils.index_of_closing_parenthesis(words, start) + 1
            prefix = words[start] + words[start + 1]

        if prefix == '(error' or prefix not in ('(model', '(('):
            return {}
        elif prefix == '(model':
            return SolverResult.get_model_explicit(words[start:])
        elif prefix == '((':
            return SolverResult.get_model_simplified(words[start:])

    @staticmethod
    def get_model_explicit(words):
        model_values = {}
        i = 2
        while i < len(words):
            if words[i] == 'define-fun':
                name = words[i + 1]
                # Usually i+2 and i+3 contains parenthesis, but in some scenarios there may be some values
                # in between. They are ignored here.
                i = utils.index_of_closing_parenthesis(words, i + 2)
                # i+1 is a type of the function
                if words[i + 2] == '(':
                    j = utils.index_of_closing_parenthesis(words, i + 2)
                    value = ' '.join(words[i + 2:j + 1])
                    i = j + 1  # j+1 is closing parenthesis of define-fun
                else:
                    value = words[i + 2]
                    i += 3  # i+3 is closing parenthesis of define-fun
                model_values[name] = value
                assert words[i] == ')'  # i should point to the last parenthesis of define-fun
            i += 1
        return model_values

    @staticmethod
    def get_model_simplified(words):
        # raise Exception('Loading model in the simplified form is not supported yet!')
        model_values = {}
        i = 1
        while i < len(words):
            if words[i] == '(':
                name = words[i + 1]
                # i+1 is a type of the function
                if words[i + 2] == '(':
                    j = utils.index_of_closing_parenthesis(words, i + 2)
                    value = ' '.join(words[i + 2:j + 1])
                    i = j + 1  # j+1 is closing parenthesis
                else:
                    value = words[i + 2]
                    i += 3  # i+3 is closing parenthesis
                model_values[name] = value
                assert words[i] == ')'  # i should point to the last parenthesis of value definition
            i += 1
        return model_values

    @staticmethod
    def get_unsat_core(text, interactive_mode, produce_assignments):
        """Returns unsat-core or empty list if it was not obtainable (e.g. decision was sat)."""
        unsat_core = []
        words = utils.str_to_wlist(text)

        # skip model - NOTE: in the interactive mode there is no need to skip the model
        if not interactive_mode:
            j = utils.index_of_closing_parenthesis(words, 1) + 1 # omit model
            if produce_assignments:
                x = words[j:]
                j = utils.index_of_closing_parenthesis(words, j) + 1 # omit assignments
                x = words[j:]
            if j+1 >= len(words):
                return []
        else:
            j = 1

        prefix = words[j] + words[j+1]
        if prefix == '(error':
            return []
        else:
            while j < len(words):
                if words[j] == '(':
                    pass
                elif words[j] == ')':
                    break
                else:
                    unsat_core.append(words[j])
                j += 1
        return unsat_core

    @staticmethod
    def get_assignments(text, interactive_mode):
        """Returns dictionary of assignments if decision was sat."""
        words = utils.str_to_wlist(text)

        j = 1 # On the j=0 is a decision.
        prefix = words[j] + words[j + 1]
        if prefix == '(objectives':
            j = utils.index_of_closing_parenthesis(words, j) + 1
            prefix = words[j] + words[j + 1]
        if prefix == '(model' or prefix == '((': # skip model - assignments are printed after it.
            j = utils.index_of_closing_parenthesis(words, j) + 1
            prefix = words[j] + words[j + 1]

        if j + 1 >= len(words):
            return []
        elif prefix == '(error':
            return {}
        else:
            return utils.wlist_to_dict_parenthesis(words[j:])<|endoftext|>


<commit_before>
import wpilib

class PreciseDelay:
    '''
        Used to synchronize a timing loop.

        Usage::

            delay = PreciseDelay(time_to_delay)

            while something:
                # do things here
                delay.wait()
    '''

    def __init__(self, delay_period):
        '''
            :param delay_period: The amount of time to do a delay
            :type delay_period: float
        '''

        self.delay = wpilib.Timer.delay
        self.timer = wpilib.Timer()
        self.delay_period = delay_period

        self.timer.start()

    def wait(self):
        '''Waits until the delay period has passed'''

        # we must *always* yield here, so other things can run
        self.delay(0.001)

        while not self.timer.hasPeriodPassed(self.delay_period):
            self.delay(0.001)<commit_msg>Fix PreciseDelay to work properly<commit_after>
import hal
import time
import wpilib

class PreciseDelay:
    '''
        Used to synchronize a timing loop. Will delay precisely so that
        the next invocation of your loop happens at the same period, as long
        as your code does not run longer than the length of the delay.

        Our experience has shown that 25ms is a good loop period.

        Usage::

            delay = PreciseDelay(time_to_delay)

            while something:
                # do things here
                delay.wait()
    '''

    def __init__(self, delay_period):
        '''
            :param delay_period: The amount of time (in seconds) to do a delay
            :type delay_period: float
        '''

        # The WPILib sleep/etc functions are slightly less stable as
        # they have more overhead, so only use them in simulation mode
        if hal.HALIsSimulation:
            self.delay = wpilib.Timer.delay
            self.get_now = wpilib.Timer.getFPGATimestamp
        else:
            self.delay = time.sleep
            self.get_now = time.time

        self.delay_period = float(delay_period)
        if self.delay_period < 0.001:
            raise ValueError("You probably don't want to delay less than 1ms!")

        self.next_delay = self.get_now() + self.delay_period

    def wait(self):
        '''Waits until the delay period has passed'''

        # optimization -- avoid local lookups
        delay = self.delay
        get_now = self.get_now
        next_delay = self.next_delay

        while True:
            # we must *always* yield here, so other things can run
            delay(0.0002)

            if next_delay < get_now():
                break

        self.next_delay += self.delay_period
<|endoftext|>


<commit_before>#!/usr/bin/env python3

#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2014-2019 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
# SPDX-License-Identifier: BSD-2-Clause

import os
import argparse
import importlib

from migen import *

from litex.build.io import CRG

from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *

from liteeth.phy import LiteEthPHY

# BaseSoC ------------------------------------------------------------------------------------------

class BaseSoC(SoCCore):
    def __init__(self, platform, with_ethernet=False, **kwargs):
        sys_clk_freq = int(1e9/platform.default_clk_period)

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self, platform, sys_clk_freq,
            ident          = "LiteX Simple SoC",
            ident_version  = True,
            **kwargs)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = CRG(platform.request(platform.default_clk_name))

        # Ethernet ---------------------------------------------------------------------------------
        if with_ethernet:
            self.submodules.ethphy = LiteEthPHY(
                clock_pads = self.platform.request("eth_clocks"),
                pads       = self.platform.request("eth"),
                clk_freq   = self.clk_freq)
            self.add_csr("ethphy")
            self.add_ethernet(phy=self.ethphy)

# Build --------------------------------------------------------------------------------------------

def main():
    parser = argparse.ArgumentParser(description="Generic LiteX SoC")
    parser.add_argument("platform",                             help="Module name of the platform to build for")
    parser.add_argument("--build",         action="store_true", help="Build bitstream")
    parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support")
    parser.add_argument("--toolchain",     default=None,        help="FPGA toolchain (None default)")
    builder_args(parser)
    soc_core_args(parser)
    args = parser.parse_args()

    platform_module = importlib.import_module(args.platform)
    if args.toolchain is not None:
        platform = platform_module.Platform(toolchain=args.toolchain)
    else:
        platform = platform_module.Platform()
    soc = BaseSoC(platform, with_ethernet=args.with_ethernet, **soc_core_argdict(args))
    builder = Builder(soc, **builder_argdict(args))
    builder.build(run=args.build)

if __name__ == "__main__":
    main()
<commit_msg>targets/simple: simplify (only keep minimal SoC + Leds) and add load argument.<commit_after>#!/usr/bin/env python3

#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2014-2020 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
# SPDX-License-Identifier: BSD-2-Clause

import os
import argparse
import importlib

from migen import *

from litex.build.io import CRG

from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *

from litex.soc.cores.led import LedChaser

# BaseSoC ------------------------------------------------------------------------------------------

class BaseSoC(SoCCore):
    def __init__(self, platform, with_ethernet=False, **kwargs):
        sys_clk_freq = int(1e9/platform.default_clk_period)

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self, platform, sys_clk_freq,
            ident          = "LiteX Simple SoC",
            ident_version  = True,
            **kwargs)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = CRG(platform.request(platform.default_clk_name))

        # Leds -------------------------------------------------------------------------------------
        self.submodules.leds = LedChaser(
            pads         = platform.request_all("user_led"),
            sys_clk_freq = sys_clk_freq)
        self.add_csr("leds")

# Build --------------------------------------------------------------------------------------------

def main():
    parser = argparse.ArgumentParser(description="Generic LiteX SoC")
    parser.add_argument("platform",                             help="Module name of the platform to build for")
    parser.add_argument("--build",         action="store_true", help="Build bitstream")
    parser.add_argument("--load",          action="store_true", help="Load bitstream")
    parser.add_argument("--toolchain",     default=None,        help="FPGA toolchain (None default)")
    builder_args(parser)
    soc_core_args(parser)
    args = parser.parse_args()

    platform_module = importlib.import_module(args.platform)
    platform_kwargs = {}
    if args.toolchain is not None:
        platform_kwargs["toolchain"] = args.toolchain
    platform = platform_module.Platform(**platform_kwargs)
    soc = BaseSoC(platform,**soc_core_argdict(args))
    builder = Builder(soc, **builder_argdict(args))
    builder.build(run=args.build)

    if args.load:
        prog = soc.platform.create_programmer()
        prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + platform.bitstream_ext))

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before>
import cv2 as cv
import numpy as np
import time
import sys
import os

lcdEnable = True
gpioEnable = True

if lcdEnable == True or gpioEnable == True:
	import RPi.GPIO as GPIO

# Define GPIO to LCD mapping
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

SWITCH_CAPTURE 	= 11
SWITCH_STOP		= 9

LED_GREEN = 10
LED_RED = 22

redThresholdArea = 10000
greenThresholdArea = 10000

#SERVO_PIN = 4
#FREQ = 50

def gpioInit():
	GPIO.setmode(GPIO.BCM)
	GPIO.setup(LED_GREEN, GPIO.OUT)
	GPIO.setup(LED_RED, GPIO.OUT)
	GPIO.setup(SWITCH_CAPTURE, GPIO.IN, pull_up_down = GPIO.PUD_UP)
	GPIO.setup(SWITCH_STOP, GPIO.IN, pull_up_down = GPIO.PUD_UP)
	GPIO.output(LED_RED, True)
	GPIO.output(LED_GREEN, True)
	#GPIO.setup(SERVO_PIN, GPIO.OUT)

# Class for LCD
class LCD:

	def __init__(self, lcd_rs,lcd_en,lcd_d4,lcd_d5,lcd_d6,lcd_d7):

		self.LCD_RS = lcd_rs
		self.LCD_EN = lcd_en
		self.LCD_D4 = lcd_d4
		self.LCD_D5 = lcd_d5
		self.LCD_D6 = lcd_d6
		self.LCD_D7 = lcd_d7

		self.LCD_WIDTH = 20
		self.LCD_CHR = True
		self.LCD_CMD = False

		self.LCD_LINE_1 = 0x80
		self.LCD_LINE_2 = 0xC0

		self.E_PULSE = 0.0001
		self.E_DELAY = 0.0001

		GPIO.setmode(GPIO.BCM)
		GPIO.setup(self.LCD_EN, GPIO.OUT)  # E
		GPIO.setup(self.LCD_RS, GPIO.OUT) # RS
		GPIO.setup(self.LCD_D4, GPIO.OUT) # DB4
		GPIO.setup(self.LCD_D5, GPIO.OUT) # DB5
		GPIO.setup(self.LCD_D6, GPIO.OUT) # DB6
		GPIO.setup(self.LCD_D7, GPIO.OUT) # DB7

		self.lcd_init()

		# Initialise display
		self.lcd_init()

		# Send some test
		#self.lcd_byte(0x80, False)
		#self.lcd_string("Rasbperry Pi")
		#self.lcd_byte(0xC0, False)
		#self.lcd_string("Model B")
		#time.sleep(5)

	def lcd_init(self):
		# Initialise display
		self.lcd_byte(0x33,False)
		self.lcd_byte(0x32,False)
		self.lcd_byte(0x28,False)
		self.lcd_byte(0x0C,False)
		self.lcd_byte(0x06,False)
		self.lcd_byte(0x01,False)

	def lcd_string(self, message):
		# Send string to display

		message = message.ljust(self.LCD_WIDTH," ")

		for i in range(self.LCD_WIDTH):
			self.lcd_byte(ord(message[i]),True)

	def lcd_byte(self,bits, mode):
		# Send byte to data pins
		# bits = data
		# mode = True  for character
		#        False for command

		GPIO.output(self.LCD_RS, mode) # RS

		# High bits
		GPIO.output(self.LCD_D4, False)
		GPIO.output(self.LCD_D5, False)
		GPIO.output(self.LCD_D6, False)
		GPIO.output(self.LCD_D7, False)
		if bits&0x10==0x10:
			GPIO.output(self.LCD_D4, True)
		if bits&0x20==0x20:
			GPIO.output(self.LCD_D5, True)
		if bits&0x40==0x40:
			GPIO.output(self.LCD_D6, True)
		if bits&0x80==0x80:
			GPIO.output(self.LCD_D7, True)

		# Toggle 'Enable' pin
		time.sleep(self.E_DELAY)
		GPIO.output(self.LCD_EN, True)
		time.sleep(self.E_PULSE)
		GPIO.output(self.LCD_EN, False)
		time.sleep(self.E_DELAY)

		# Low bits
		GPIO.output(self.LCD_D4, False)
		GPIO.output(self.LCD_D5, False)
		GPIO.output(self.LCD_D6, False)
		GPIO.output(self.LCD_D7, False)
		if bits&0x01==0x01:
			GPIO.output(self.LCD_D4, True)
		if bits&0x02==0x02:
			GPIO.output(self.LCD_D5, True)
		if bits&0x04==0x04:
			GPIO.output(self.LCD_D6, True)
		if bits&0x08==0x08:
			GPIO.output(self.LCD_D7, True)

		# Toggle 'Enable' pin
		time.sleep(self.E_DELAY)
		GPIO.output(self.LCD_EN, True)
		time.sleep(self.E_PULSE)
		GPIO.output(self.LCD_EN, False)
		time.sleep(self.E_DELAY)

# Class for Image Processing
class Image:

	def __init__(self, _camera, _interval, filt, rlowHSV, rhighHSV, glowHSV, ghighHSV):

		# store
		self.cameraIndex = _camera
		self.frameInterval = _interval
		self.filt = filt
		self.capture = cv.VideoCapture(self.cameraIndex)

		#self.fwindow = cv.namedWindow("Result")
		self.redlowHSV = rlowHSV
		self.redhighHSV = rhighHSV

		self.greenlowHSV = glowHSV
		self.greenhighHSV = ghighHSV

		self.greenlastX = 0
		self.greenlastY = 0
		self.redlastX 	= 0
		self.redlastY 	= 0

		self.red_count = 0
		self.green_count = 0

		self.green_flag = False
		self.red_flag = False

	def clearFlags(self):
		self.red_flag = False
		self.green_flag = False

	def clearCounts(self):
		self.red_count = 0
		self.green_count = 0

	def getFlags(self):
		if self.red_flag == True and self.green_flag == True:
			return -1 # Both found
		elif self.red_flag == False and self.green_flag == False:
			return -2 # Not found
		elif self.red_flag == True and self.green_flag == False:
			return 1 # Success
		elif self.red_flag == False and self.green_flag == True:
			return 2

	def doCaptureAndProcess(self):
		#_frame = ''
		for i in range(10):
			_, _frame = self.capture.read()

		frame = cv.resize(_frame, (640, 480))

		if self.filt == 0:
			filteredImage = frame
		elif self.filt == 1:
			filteredImage = cv.blur(frame, (5,5))
		elif self.filt == 2:
			filteredImage = cv.GaussianBlur(frame, (5,5),0)
		elif self.filt == 3:
			filteredImage = cv.medianBlur(frame, 5)
		elif self.filt == 4:
			filteredImage = cv.bilateralFilter(frame,9,75,75)

		kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))

		hsvImage = cv.cvtColor(filteredImage, cv.COLOR_BGR2HSV)

		RedimgThresholded = cv.inRange(hsvImage, self.redlowHSV, self.redhighHSV)
		GreenimgThresholded = cv.inRange(hsvImage, self.greenlowHSV, self.greenhighHSV)
		erosion = cv.erode(RedimgThresholded,kernel,iterations = 1)
		dilation = cv.dilate(RedimgThresholded,kernel,iterations = 1)

		dilation = cv.dilate(RedimgThresholded,kernel,iterations = 1)
		erosion = cv.erode(RedimgThresholded,kernel,iterations = 1)

		erosion = cv.erode(GreenimgThresholded,kernel,iterations = 1)
		dilation = cv.dilate(GreenimgThresholded,kernel,iterations = 1)

		dilation = cv.dilate(GreenimgThresholded,kernel,iterations = 1)
		erosion = cv.erode(GreenimgThresholded,kernel,iterations = 1)

		Redmoments = cv.moments(RedimgThresholded)
		Greenmoments = cv.moments(GreenimgThresholded)

		Redm01  = Redmoments['m01']
		Redm10  = Redmoments['m10']
		Redarea = Redmoments['m00']

		Greenm01  = Greenmoments['m01']
		Greenm10  = Greenmoments['m10']
		Greenarea = Greenmoments['m00']

		if Redarea > redThresholdArea:
			#print "Red"
			posX = Redm10 / Redarea
			posY = Redm01 / Redarea

			if self.redlastX >= 0 and self.redlastY >= 0 and posX >= 0  and posY >= 0:
				cv.line(filteredImage, (int(posX), int(posY)), (int(self.redlastX),int(self.redlastY)), (0,0,255), 5)

			redlastX = posX
			redlastY = posY
			if Redarea > Greenarea:
				if gpioEnable == True:
					GPIO.output(LED_GREEN, False)
					GPIO.output(LED_RED, True)
				self.red_count += 1
				self.red_flag = True

		if Greenarea > greenThresholdArea:
			posX = Greenm10 / Greenarea
			posY = Greenm01 / Greenarea

			if self.greenlastX >= 0 and self.greenlastY >= 0 and posX >= 0  and posY >= 0:
				cv.line(filteredImage, (int(posX), int(posY)), (int(self.greenlastX),int(self.greenlastY)), (0,0,255), 5)

			greenlastX = posX
			greenlastY = posY

			if Greenarea > Redarea:
				if gpioEnable == True:
					GPIO.output(LED_GREEN, True)
					GPIO.output(LED_RED, False)
				self.green_count += 1
				self.green_flag = True

		# Calculate percentage area
		red_per = (Redarea * 100) / (640 * 480)
		green_per = (Greenarea * 100) / (640 * 480)

		print "red: " + str("%.2f" % red_per) + "%"
		print "green: " + str("%.2f" % green_per) + "%"

		if lcdEnable == True:
			lcd.lcd_byte(0xC0, False)
			lcd.lcd_string(str(self.green_count))
			lcd.lcd_string(", ")
			lcd.lcd_string(str(self.red_count))
			lcd.lcd_string("        ")
			lcd.lcd_byte(0x94, False)
			lcd.lcd_string("red: " + str("%.2f" % red_per) + "%")
			lcd.lcd_byte(0xD4, False)
			lcd.lcd_string("green: " + str("%.2f" % green_per) + "%")

		cv.imshow("Red Thresholded Image", RedimgThresholded)
		cv.imshow("Green Thresholded Image", GreenimgThresholded)
		cv.imshow("Original Image", filteredImage)

redlowHSV = np.array([160,150,60], dtype=np.uint8)
redhighHSV = np.array([170,255,255], dtype=np.uint8)

greenlowHSV = np.array([50,150,60], dtype=np.uint8)
greenhighHSV = np.array([75,255,255], dtype=np.uint8)

#os.system("servod")
time.sleep(1)

obj = Image(0, 1, 1, redlowHSV, redhighHSV, greenlowHSV, greenhighHSV)
if gpioEnable == True:
	gpioInit()

# If LCD is enabled enable lcd for display
if lcdEnable == True:
	lcd = LCD(LCD_RS, LCD_E, LCD_D4, LCD_D5,LCD_D6,LCD_D7)
	time.sleep(2)
	lcd.lcd_byte(0x80, False)
	lcd.lcd_string("  Color Detection  ")

def process():
	count = 0
	while count < 10:
		obj.doCaptureAndProcess()
		count += 1
		res = obj.getFlags()
		if res == -1:
			print "Both Found"
		elif res == -2:
			print "Not Found"
		elif res == 1:
			os.system("echo 0=100% > /dev/servoblaster")
			print "Red"
			count = 11
			time.sleep(5)
			os.system("echo 0=50% > /dev/servoblaster")
		elif res == 2:
			print "Green"
			os.system("echo 0=0% > /dev/servoblaster")
			count = 11
			time.sleep(5)
			os.system("echo 0=50% > /dev/servoblaster")
	obj.clearFlags()

os.system("servod --p1pins=7,0,0,0,0,0,0,0")
#time.sleep(1)
os.system("echo 0=50% > /dev/servoblaster")
print "System started"
obj.doCaptureAndProcess()
#Servo = GPIO.PWM(SERVO_PIN, FREQ)
while True:

	#process()
	if gpioEnable == True:
		if GPIO.input(SWITCH_CAPTURE) == 0:
			print "Capture"
			time.sleep(0.3)
			process()
		if GPIO.input(SWITCH_STOP) == 0:
			print "Clear"
			time.sleep(0.3)
			obj.clearCounts()

	# Break Operation if key interrupt
	k = cv.waitKey(5) & 0xFF
	if k == 27:
		break
<commit_msg>delivery<commit_after>
import cv2 as cv
import numpy as np
import time
import sys
import os

lcdEnable = True
gpioEnable = True

if lcdEnable == True or gpioEnable == True:
	import RPi.GPIO as GPIO

# Define GPIO to LCD mapping
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

SWITCH_CAPTURE 	= 11
SWITCH_STOP		= 9

LED_GREEN = 10
LED_RED = 22

redThresholdArea = 10000
greenThresholdArea = 10000

#SERVO_PIN = 4
#FREQ = 50

def gpioInit():
	GPIO.setmode(GPIO.BCM)
	GPIO.setup(LED_GREEN, GPIO.OUT)
	GPIO.setup(LED_RED, GPIO.OUT)
	GPIO.setup(SWITCH_CAPTURE, GPIO.IN, pull_up_down = GPIO.PUD_UP)
	GPIO.setup(SWITCH_STOP, GPIO.IN, pull_up_down = GPIO.PUD_UP)
	GPIO.output(LED_RED, True)
	GPIO.output(LED_GREEN, True)
	#GPIO.setup(SERVO_PIN, GPIO.OUT)

# Class for LCD
class LCD:

	def __init__(self, lcd_rs,lcd_en,lcd_d4,lcd_d5,lcd_d6,lcd_d7):

		self.LCD_RS = lcd_rs
		self.LCD_EN = lcd_en
		self.LCD_D4 = lcd_d4
		self.LCD_D5 = lcd_d5
		self.LCD_D6 = lcd_d6
		self.LCD_D7 = lcd_d7

		self.LCD_WIDTH = 20
		self.LCD_CHR = True
		self.LCD_CMD = False

		self.LCD_LINE_1 = 0x80
		self.LCD_LINE_2 = 0xC0

		self.E_PULSE = 0.0001
		self.E_DELAY = 0.0001

		GPIO.setmode(GPIO.BCM)
		GPIO.setup(self.LCD_EN, GPIO.OUT)  # E
		GPIO.setup(self.LCD_RS, GPIO.OUT) # RS
		GPIO.setup(self.LCD_D4, GPIO.OUT) # DB4
		GPIO.setup(self.LCD_D5, GPIO.OUT) # DB5
		GPIO.setup(self.LCD_D6, GPIO.OUT) # DB6
		GPIO.setup(self.LCD_D7, GPIO.OUT) # DB7

		self.lcd_init()

		# Initialise display
		self.lcd_init()

		# Send some test
		#self.lcd_byte(0x80, False)
		#self.lcd_string("Rasbperry Pi")
		#self.lcd_byte(0xC0, False)
		#self.lcd_string("Model B")
		#time.sleep(5)

	def lcd_init(self):
		# Initialise display
		self.lcd_byte(0x33,False)
		self.lcd_byte(0x32,False)
		self.lcd_byte(0x28,False)
		self.lcd_byte(0x0C,False)
		self.lcd_byte(0x06,False)
		self.lcd_byte(0x01,False)

	def lcd_string(self, message):
		# Send string to display

		message = message.ljust(self.LCD_WIDTH," ")

		for i in range(self.LCD_WIDTH):
			self.lcd_byte(ord(message[i]),True)

	def lcd_byte(self,bits, mode):
		# Send byte to data pins
		# bits = data
		# mode = True  for character
		#        False for command

		GPIO.output(self.LCD_RS, mode) # RS

		# High bits
		GPIO.output(self.LCD_D4, False)
		GPIO.output(self.LCD_D5, False)
		GPIO.output(self.LCD_D6, False)
		GPIO.output(self.LCD_D7, False)
		if bits&0x10==0x10:
			GPIO.output(self.LCD_D4, True)
		if bits&0x20==0x20:
			GPIO.output(self.LCD_D5, True)
		if bits&0x40==0x40:
			GPIO.output(self.LCD_D6, True)
		if bits&0x80==0x80:
			GPIO.output(self.LCD_D7, True)

		# Toggle 'Enable' pin
		time.sleep(self.E_DELAY)
		GPIO.output(self.LCD_EN, True)
		time.sleep(self.E_PULSE)
		GPIO.output(self.LCD_EN, False)
		time.sleep(self.E_DELAY)

		# Low bits
		GPIO.output(self.LCD_D4, False)
		GPIO.output(self.LCD_D5, False)
		GPIO.output(self.LCD_D6, False)
		GPIO.output(self.LCD_D7, False)
		if bits&0x01==0x01:
			GPIO.output(self.LCD_D4, True)
		if bits&0x02==0x02:
			GPIO.output(self.LCD_D5, True)
		if bits&0x04==0x04:
			GPIO.output(self.LCD_D6, True)
		if bits&0x08==0x08:
			GPIO.output(self.LCD_D7, True)

		# Toggle 'Enable' pin
		time.sleep(self.E_DELAY)
		GPIO.output(self.LCD_EN, True)
		time.sleep(self.E_PULSE)
		GPIO.output(self.LCD_EN, False)
		time.sleep(self.E_DELAY)

# Class for Image Processing
class Image:

	def __init__(self, _camera, _interval, filt, rlowHSV, rhighHSV, glowHSV, ghighHSV):

		# store
		self.cameraIndex = _camera
		self.frameInterval = _interval
		self.filt = filt
		self.capture = cv.VideoCapture(self.cameraIndex)

		#self.fwindow = cv.namedWindow("Result")
		self.redlowHSV = rlowHSV
		self.redhighHSV = rhighHSV

		self.greenlowHSV = glowHSV
		self.greenhighHSV = ghighHSV

		self.greenlastX = 0
		self.greenlastY = 0
		self.redlastX 	= 0
		self.redlastY 	= 0

		self.red_count = 0
		self.green_count = 0

		self.green_flag = False
		self.red_flag = False

	def clearFlags(self):
		self.red_flag = False
		self.green_flag = False

	def clearCounts(self):
		self.red_count = 0
		self.green_count = 0

	def getFlags(self):
		if self.red_flag == True and self.green_flag == True:
			return -1 # Both found
		elif self.red_flag == False and self.green_flag == False:
			return -2 # Not found
		elif self.red_flag == True and self.green_flag == False:
			return 1 # Success
		elif self.red_flag == False and self.green_flag == True:
			return 2

	def doCaptureAndProcess(self):
		#_frame = ''
		for i in range(10):
			_, _frame = self.capture.read()

		frame = cv.resize(_frame, (640, 480))

		if self.filt == 0:
			filteredImage = frame
		elif self.filt == 1:
			filteredImage = cv.blur(frame, (5,5))
		elif self.filt == 2:
			filteredImage = cv.GaussianBlur(frame, (5,5),0)
		elif self.filt == 3:
			filteredImage = cv.medianBlur(frame, 5)
		elif self.filt == 4:
			filteredImage = cv.bilateralFilter(frame,9,75,75)

		kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))

		hsvImage = cv.cvtColor(filteredImage, cv.COLOR_BGR2HSV)

		RedimgThresholded = cv.inRange(hsvImage, self.redlowHSV, self.redhighHSV)
		GreenimgThresholded = cv.inRange(hsvImage, self.greenlowHSV, self.greenhighHSV)
		erosion = cv.erode(RedimgThresholded,kernel,iterations = 1)
		dilation = cv.dilate(RedimgThresholded,kernel,iterations = 1)

		dilation = cv.dilate(RedimgThresholded,kernel,iterations = 1)
		erosion = cv.erode(RedimgThresholded,kernel,iterations = 1)

		erosion = cv.erode(GreenimgThresholded,kernel,iterations = 1)
		dilation = cv.dilate(GreenimgThresholded,kernel,iterations = 1)

		dilation = cv.dilate(GreenimgThresholded,kernel,iterations = 1)
		erosion = cv.erode(GreenimgThresholded,kernel,iterations = 1)

		Redmoments = cv.moments(RedimgThresholded)
		Greenmoments = cv.moments(GreenimgThresholded)

		Redm01  = Redmoments['m01']
		Redm10  = Redmoments['m10']
		Redarea = Redmoments['m00']

		Greenm01  = Greenmoments['m01']
		Greenm10  = Greenmoments['m10']
		Greenarea = Greenmoments['m00']

		if Redarea > redThresholdArea:
			#print "Red"
			posX = Redm10 / Redarea
			posY = Redm01 / Redarea

			if self.redlastX >= 0 and self.redlastY >= 0 and posX >= 0  and posY >= 0:
				cv.line(filteredImage, (int(posX), int(posY)), (int(self.redlastX),int(self.redlastY)), (0,0,255), 5)

			redlastX = posX
			redlastY = posY
			if Redarea > Greenarea:
				if gpioEnable == True:
					GPIO.output(LED_GREEN, False)
					GPIO.output(LED_RED, True)
				self.red_count += 1
				self.red_flag = True

		if Greenarea > greenThresholdArea:
			posX = Greenm10 / Greenarea
			posY = Greenm01 / Greenarea

			if self.greenlastX >= 0 and self.greenlastY >= 0 and posX >= 0  and posY >= 0:
				cv.line(filteredImage, (int(posX), int(posY)), (int(self.greenlastX),int(self.greenlastY)), (0,0,255), 5)

			greenlastX = posX
			greenlastY = posY

			if Greenarea > Redarea:
				if gpioEnable == True:
					GPIO.output(LED_GREEN, True)
					GPIO.output(LED_RED, False)
				self.green_count += 1
				self.green_flag = True

		# Calculate percentage area
		red_per = (Redarea * 100) / (640 * 480)
		green_per = (Greenarea * 100) / (640 * 480)

		print "red: " + str("%.2f" % red_per) + "%"
		print "green: " + str("%.2f" % green_per) + "%"

		if lcdEnable == True:
			lcd.lcd_byte(0xC0, False)
			lcd.lcd_string(str(self.green_count))
			lcd.lcd_string(", ")
			lcd.lcd_string(str(self.red_count))
			lcd.lcd_string("        ")
			lcd.lcd_byte(0x94, False)
			lcd.lcd_string("red: " + str("%.2f" % red_per) + "%")
			lcd.lcd_byte(0xD4, False)
			lcd.lcd_string("green: " + str("%.2f" % green_per) + "%")

		cv.imshow("Red Thresholded Image", RedimgThresholded)
		cv.imshow("Green Thresholded Image", GreenimgThresholded)
		cv.imshow("Original Image", filteredImage)

redlowHSV = np.array([170,150,60], dtype=np.uint8)
redhighHSV = np.array([179,255,255], dtype=np.uint8)

greenlowHSV = np.array([60,150,60], dtype=np.uint8)
greenhighHSV = np.array([70,255,255], dtype=np.uint8)

#os.system("servod")
time.sleep(1)

obj = Image(0, 1, 1, redlowHSV, redhighHSV, greenlowHSV, greenhighHSV)
if gpioEnable == True:
	gpioInit()

# If LCD is enabled enable lcd for display
if lcdEnable == True:
	lcd = LCD(LCD_RS, LCD_E, LCD_D4, LCD_D5,LCD_D6,LCD_D7)
	time.sleep(2)
	lcd.lcd_byte(0x80, False)
	lcd.lcd_string("  Color Detection  ")

def process():
	count = 0
	while count < 10:
		obj.doCaptureAndProcess()
		count += 1
		res = obj.getFlags()
		if res == -1:
			print "Both Found"
		elif res == -2:
			print "Not Found"
		elif res == 1:
			os.system("echo 0=100% > /dev/servoblaster")
			print "Red"
			count = 11
			time.sleep(5)
			os.system("echo 0=50% > /dev/servoblaster")
		elif res == 2:
			print "Green"
			os.system("echo 0=0% > /dev/servoblaster")
			count = 11
			time.sleep(5)
			os.system("echo 0=50% > /dev/servoblaster")
	obj.clearFlags()

os.system("servod --p1pins=7,0,0,0,0,0,0,0")
#time.sleep(1)
os.system("echo 0=50% > /dev/servoblaster")
print "System started"
obj.doCaptureAndProcess()
#Servo = GPIO.PWM(SERVO_PIN, FREQ)
while True:

	#process()
	if gpioEnable == True:
		if GPIO.input(SWITCH_CAPTURE) == 0:
			print "Capture"
			time.sleep(0.3)
			process()
		if GPIO.input(SWITCH_STOP) == 0:
			print "Clear"
			time.sleep(0.3)
			obj.clearCounts()

	# Break Operation if key interrupt
	k = cv.waitKey(5) & 0xFF
	if k == 27:
		break
<|endoftext|>