from . import ClientConstants as CC
from . import ClientData
from . import ClientGUICommon
from . import ClientGUIControls
from . import ClientGUIFunctions
from . import ClientGUIOptionsPanels
from . import ClientGUIScrolledPanels
from . import ClientGUIShortcuts
from . import ClientGUITime
from . import ClientRatings
from . import ClientSearch
import datetime
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusGlobals as HG
from . import HydrusText
import os
import re
import string
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
from qtpy import QtGui as QG
from . import QtPorting as QP

class InputFileSystemPredicate( ClientGUIScrolledPanels.EditPanel ):

    def __init__( self, parent, predicate_type ):

        ClientGUIScrolledPanels.EditPanel.__init__( self, parent )

        self._predicates = []

        label = None
        editable_pred_panel_classes = []
        static_pred_buttons = []

        if predicate_type == HC.PREDICATE_TYPE_SYSTEM_AGE:

            editable_pred_panel_classes.append( PanelPredicateSystemAgeDelta )
            editable_pred_panel_classes.append( PanelPredicateSystemAgeDate )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME:

            editable_pred_panel_classes.append( PanelPredicateSystemModifiedDelta )
            editable_pred_panel_classes.append( PanelPredicateSystemModifiedDate )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS:

            editable_pred_panel_classes.append( PanelPredicateSystemHeight )
            editable_pred_panel_classes.append( PanelPredicateSystemWidth )
            editable_pred_panel_classes.append( PanelPredicateSystemRatio )
            editable_pred_panel_classes.append( PanelPredicateSystemNumPixels )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_DURATION:

            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_DURATION, ( '>', 0 ) ), ) ) )
            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_DURATION, ( '=', 0 ) ), ) ) )

            editable_pred_panel_classes.append( PanelPredicateSystemDuration )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE:

            editable_pred_panel_classes.append( PanelPredicateSystemFileService )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_KNOWN_URLS:

            editable_pred_panel_classes.append( PanelPredicateSystemKnownURLsExactURL )
            editable_pred_panel_classes.append( PanelPredicateSystemKnownURLsDomain )
            editable_pred_panel_classes.append( PanelPredicateSystemKnownURLsRegex )
            editable_pred_panel_classes.append( PanelPredicateSystemKnownURLsURLClass )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_HAS_AUDIO:

            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, True ), ) ) )
            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, False ), ) ) )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_HASH:

            editable_pred_panel_classes.append( PanelPredicateSystemHash )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_LIMIT:

            label = 'system:limit clips a large search result down to the given number of files. It is very useful for processing in smaller batches.'
            label += os.linesep * 2
            label += 'For all the simpler sorts (filesize, duration, etc...), it will select the n largest/smallest in the result set appropriate for that sort. For complicated sorts like tags, it will sample randomly.'

            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LIMIT, 64 ), ) ) )
            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LIMIT, 256 ), ) ) )
            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_LIMIT, 1024 ), ) ) )

            editable_pred_panel_classes.append( PanelPredicateSystemLimit )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_MIME:

            editable_pred_panel_classes.append( PanelPredicateSystemMime )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS:

            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '>', 0 ) ), ) ) )
            static_pred_buttons.append( StaticSystemPredicateButton( self, ( ClientSearch.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ), ) ) )

            editable_pred_panel_classes.append( PanelPredicateSystemNumTags )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS:

            editable_pred_panel_classes.append( PanelPredicateSystemNumWords )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_RATING:

            services_manager = HG.client_controller.services_manager

            ratings_services = services_manager.GetServices( ( HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL ) )

            if len( ratings_services ) > 0:

                editable_pred_panel_classes.append( PanelPredicateSystemRating )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO:

            editable_pred_panel_classes.append( PanelPredicateSystemSimilarTo )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_SIZE:

            editable_pred_panel_classes.append( PanelPredicateSystemSize )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER:

            editable_pred_panel_classes.append( PanelPredicateSystemTagAsNumber )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS:

            editable_pred_panel_classes.append( PanelPredicateSystemDuplicateRelationships )
            editable_pred_panel_classes.append( PanelPredicateSystemDuplicateKing )

        elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS:

            editable_pred_panel_classes.append( PanelPredicateSystemFileViewingStatsViews )
            editable_pred_panel_classes.append( PanelPredicateSystemFileViewingStatsViewtime )

        vbox = QP.VBoxLayout()

        if label is not None:

            st = ClientGUICommon.BetterStaticText( self, label = label )

            st.setWordWrap( True )

            QP.AddToLayout( vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR )

        for button in static_pred_buttons:

            QP.AddToLayout( vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR )

        for pred_class in editable_pred_panel_classes:

            panel = self._EditablePredPanel( self, pred_class )

            QP.AddToLayout( vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR )

        if len( static_pred_buttons ) > 0 and len( editable_pred_panel_classes ) == 0:

            QP.CallAfter( static_pred_buttons[0].setFocus, QC.Qt.OtherFocusReason )

        self.widget().setLayout( vbox )

    def GetValue( self ):

        return self._predicates

    def SubPanelOK( self, predicates ):

        self._predicates = predicates

        self.parentWidget().DoOK()

    class _EditablePredPanel( QW.QWidget ):

        def __init__( self, parent, predicate_class ):

            QW.QWidget.__init__( self, parent )

            self._predicate_panel = predicate_class( self )
            self._parent = parent

            self._ok = QW.QPushButton( 'ok', self )
            self._ok.clicked.connect( self._DoOK )
            self._ok.setObjectName( 'HydrusAccept' )

            hbox = QP.HBoxLayout()

            QP.AddToLayout( hbox, self._predicate_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
            QP.AddToLayout( hbox, self._ok, CC.FLAGS_VCENTER )

            self.setLayout( hbox )

            QP.CallAfter( self._ok.setFocus, QC.Qt.OtherFocusReason )

        def _DoOK( self ):

            try:

                self._predicate_panel.CheckCanOK()

            except Exception as e:

                message = 'Cannot OK: {}'.format( e )

                QW.QMessageBox.warning( self, 'Warning', message )

                return

            predicates = self._predicate_panel.GetPredicates()

            self._parent.SubPanelOK( predicates )

        def keyPressEvent( self, event ):

            ( modifier, key ) = ClientGUIShortcuts.ConvertKeyEventToSimpleTuple( event )

            if key in ( QC.Qt.Key_Enter, QC.Qt.Key_Return ):

                self._DoOK()

            else:

                event.ignore()

class StaticSystemPredicateButton( QW.QPushButton ):

    def __init__( self, parent, predicates ):

        QW.QPushButton.__init__( self, parent )

        self._parent = parent
        self._predicates = predicates

        label = ', '.join( ( predicate.ToString() for predicate in self._predicates ) )

        self.setText( label )

        self.clicked.connect( self.DoOK )

    def DoOK( self ):

        self._parent.SubPanelOK( self._predicates )

class PanelPredicateSystem( QW.QWidget ):

    PREDICATE_TYPE = None

    def CheckCanOK( self ):

        pass

    def GetInfo( self ):

        raise NotImplementedError()

    def GetPredicates( self ):

        info = self.GetInfo()

        predicates = ( ClientSearch.Predicate( self.PREDICATE_TYPE, info ), )

        return predicates

class PanelPredicateSystemAgeDate( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_AGE

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._date = QW.QCalendarWidget( self )

        qt_dt = QC.QDate.currentDate()

        qt_dt.addDays( -7 )

        self._date.setSelectedDate( qt_dt )

        self._sign.SetStringSelection( '>' )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:time imported'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._date, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        qt_dt = self._date.selectedDate()

        year = qt_dt.year()
        month = qt_dt.month()
        day = qt_dt.day()

        info = ( self._sign.GetStringSelection(), 'date', ( year, month, day ) )

        return info

class PanelPredicateSystemAgeDelta( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_AGE

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','>'] )

        self._years = QP.MakeQSpinBox( self, max=30, width = 60 )
        self._months = QP.MakeQSpinBox( self, max=60, width = 60 )
        self._days = QP.MakeQSpinBox( self, max=90, width = 60 )
        self._hours = QP.MakeQSpinBox( self, max=24, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        try:

            ( sign, age_type, ( years, months, days, hours ) ) = system_predicates[ 'age' ]

        except:

            # wew lad. replace this all with proper system pred saving on new_options in future
            sign = '<'

            years = 0
            months = 0
            days = 7
            hours = 0

        self._sign.SetStringSelection( sign )

        self._years.setValue( years )
        self._months.setValue( months )
        self._days.setValue( days )
        self._hours.setValue( hours )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:time imported'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._years, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'years'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._months, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'months'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._days, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'days'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._hours, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'hours'), CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), 'delta', (self._years.value(), self._months.value(), self._days.value(), self._hours.value()))

        return info

class PanelPredicateSystemModifiedDate( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._date = QW.QCalendarWidget( self )

        qt_dt = QC.QDate.currentDate()

        qt_dt.addDays( -7 )

        self._date.setSelectedDate( qt_dt )

        self._sign.SetStringSelection( '>' )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:modified date'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._date, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        qt_dt = self._date.selectedDate()

        year = qt_dt.year()
        month = qt_dt.month()
        day = qt_dt.day()

        info = ( self._sign.GetStringSelection(), 'date', ( year, month, day ) )

        return info

class PanelPredicateSystemModifiedDelta( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','>'] )

        self._years = QP.MakeQSpinBox( self, max=30 )
        self._months = QP.MakeQSpinBox( self, max=60 )
        self._days = QP.MakeQSpinBox( self, max=90 )
        self._hours = QP.MakeQSpinBox( self, max=24 )

        # wew lad. replace this all with proper system pred saving on new_options in future
        sign = '<'

        years = 0
        months = 0
        days = 7
        hours = 0

        self._sign.SetStringSelection( sign )

        self._years.setValue( years )
        self._months.setValue( months )
        self._days.setValue( days )
        self._hours.setValue( hours )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:modified date'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._years, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'years'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._months, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'months'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._days, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'days'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._hours, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'hours'), CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), 'delta', ( self._years.value(), self._months.value(), self._days.value(), self._hours.value() ) )

        return info

class PanelPredicateSystemDuplicateKing( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_KING

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        choices = [ 'is the best quality file of its group', 'is not the best quality file of its group' ]

        self._king = QP.RadioBox( self, choices = choices, vertical = True )

        #

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._king, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        king_str = self._king.GetStringSelection()

        king = 'is the' in king_str

        info = king

        return info

class PanelPredicateSystemDuplicateRelationships( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_COUNT

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        choices = [ '<', '\u2248', '=', '>' ]

        self._sign = QP.RadioBox( self, choices = choices )

        self._num = QP.MakeQSpinBox( self, min=0, max=65535 )

        choices = [ ( HC.duplicate_type_string_lookup[ status ], status ) for status in ( HC.DUPLICATE_MEMBER, HC.DUPLICATE_ALTERNATE, HC.DUPLICATE_FALSE_POSITIVE, HC.DUPLICATE_POTENTIAL ) ]

        self._dupe_type = ClientGUICommon.BetterRadioBox( self, choices = choices, vertical = True )

        #

        self._sign.SetStringSelection( '>' )
        self._num.setValue( 0 )

        #

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:num file relationships'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._num, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._dupe_type, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = (self._sign.GetStringSelection(), self._num.value(), self._dupe_type.GetValue())

        return info

class PanelPredicateSystemDuration( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_DURATION

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        choices = [ '<', '\u2248', '=', '>' ]

        self._sign = QP.RadioBox( self, choices = choices )

        self._duration_s = QP.MakeQSpinBox( self, max=3599, width = 60 )
        self._duration_ms = QP.MakeQSpinBox( self, max=999, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, ms ) = system_predicates[ 'duration' ]

        s = ms // 1000

        ms = ms % 1000

        self._sign.SetStringSelection( sign )

        self._duration_s.setValue( s )
        self._duration_ms.setValue( ms )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:duration'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._duration_s, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'s'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._duration_ms, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'ms'), CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = (self._sign.GetStringSelection(), self._duration_s.value() * 1000 + self._duration_ms.value())

        return info

class PanelPredicateSystemFileService( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = ClientGUICommon.BetterRadioBox( self, choices = [ ( 'is', True ), ( 'is not', False ) ], vertical = True )

        self._current_pending = ClientGUICommon.BetterRadioBox( self, choices = [ ( 'currently in', HC.CONTENT_STATUS_CURRENT ), ( 'pending to', HC.CONTENT_STATUS_PENDING ) ], vertical = True )

        services = HG.client_controller.services_manager.GetServices( HC.FILE_SERVICES )

        choices = [ ( service.GetName(), service.GetServiceKey() ) for service in services ]

        self._file_service_key = ClientGUICommon.BetterRadioBox( self, choices = choices, vertical = True )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:file service:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._current_pending, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._file_service_key, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetValue(), self._current_pending.GetValue(), self._file_service_key.GetValue() )

        return info

class PanelPredicateSystemFileViewingStatsViews( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._viewing_locations = QP.CheckListBox( self )

        self._viewing_locations.Append( 'media views', 'media' )
        self._viewing_locations.Append( 'preview views', 'preview' )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._value = QP.MakeQSpinBox( self, min=0, max=1000000 )

        #

        self._viewing_locations.Check( 0 )

        self._sign.Select( 3 )

        self._value.setValue( 10 )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._viewing_locations, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._value, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        viewing_locations = self._viewing_locations.GetChecked()

        if len( viewing_locations ) == 0:

            viewing_locations = [ 'media' ]

        sign = self._sign.GetStringSelection()

        value = self._value.value()

        info = ( 'views', tuple( viewing_locations ), sign, value )

        return info

class PanelPredicateSystemFileViewingStatsViewtime( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._viewing_locations = QP.CheckListBox( self )

        self._viewing_locations.Append( 'media viewtime', 'media' )
        self._viewing_locations.Append( 'preview viewtime', 'preview' )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._time_delta = ClientGUITime.TimeDeltaCtrl( self, min = 0, days = True, hours = True, minutes = True, seconds = True )

        #

        self._viewing_locations.Check( 0 )

        self._sign.Select( 3 )

        self._time_delta.SetValue( 600 )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._viewing_locations, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._time_delta, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        viewing_locations = self._viewing_locations.GetChecked()

        if len( viewing_locations ) == 0:

            viewing_locations = [ 'media' ]

        sign = self._sign.GetStringSelection()

        time_delta = self._time_delta.GetValue()

        info = ( 'viewtime', tuple( viewing_locations ), sign, time_delta )

        return info

class PanelPredicateSystemHash( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_HASH

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._hashes = QW.QPlainTextEdit( self )

        ( init_width, init_height ) = ClientGUIFunctions.ConvertTextToPixels( self._hashes, ( 66, 10 ) )

        self._hashes.setMinimumSize( QC.QSize( init_width, init_height ) )

        choices = [ 'sha256', 'md5', 'sha1', 'sha512' ]

        self._hash_type = QP.RadioBox( self, choices = choices, vertical = True )

        self._hashes.setPlaceholderText( 'enter hash (paste newline-separated for multiple hashes)' )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:hash='), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._hashes, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._hash_type, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        hex_hashes_raw = self._hashes.toPlainText()

        hex_hashes = HydrusText.DeserialiseNewlinedTexts( hex_hashes_raw )

        hex_hashes = [ HydrusText.HexFilter( hex_hash ) for hex_hash in hex_hashes ]

        hex_hashes = HydrusData.DedupeList( hex_hashes )

        hashes = tuple( [ bytes.fromhex( hex_hash ) for hex_hash in hex_hashes ] )

        hash_type = self._hash_type.GetStringSelection()

        return ( hashes, hash_type )

class PanelPredicateSystemHeight( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_HEIGHT

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._height = QP.MakeQSpinBox( self, max=200000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, height ) = system_predicates[ 'height' ]

        self._sign.SetStringSelection( sign )

        self._height.setValue( height )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:height'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._height, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), self._height.value())

        return info

class PanelPredicateSystemKnownURLsExactURL( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_KNOWN_URLS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._operator = ClientGUICommon.BetterChoice( self )

        self._operator.addItem( 'has', True )
        self._operator.addItem( 'does not have', False )

        self._exact_url = QW.QLineEdit( self )
        self._exact_url.setFixedWidth( 250 )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:known url'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._operator, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'exact url:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._exact_url, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        operator = self._operator.GetValue()

        if operator:

            operator_description = 'has url: '

        else:

            operator_description = 'does not have url: '

        rule_type = 'exact_match'

        exact_url = self._exact_url.text()

        rule = exact_url

        description = operator_description + exact_url

        return ( operator, rule_type, rule, description )

class PanelPredicateSystemKnownURLsDomain( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_KNOWN_URLS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._operator = ClientGUICommon.BetterChoice( self )

        self._operator.addItem( 'has', True )
        self._operator.addItem( 'does not have', False )

        self._domain = QW.QLineEdit( self )
        self._domain.setFixedWidth( 250 )

        self._domain.setPlaceholderText( 'example.com' )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:known url'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._operator, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'a url with domain:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._domain, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        operator = self._operator.GetValue()

        if operator:

            operator_description = 'has a url with domain: '

        else:

            operator_description = 'does not have a url with domain: '

        rule_type = 'domain'

        domain = self._domain.text()

        rule = domain

        description = operator_description + domain

        return ( operator, rule_type, rule, description )

class PanelPredicateSystemKnownURLsRegex( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_KNOWN_URLS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._operator = ClientGUICommon.BetterChoice( self )

        self._operator.addItem( 'has', True )
        self._operator.addItem( 'does not have', False )

        self._regex = QW.QLineEdit( self )
        self._regex.setFixedWidth( 250 )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:known url'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._operator, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'a url that matches this regex:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._regex, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def CheckCanOK( self ):

        regex = self._regex.text()

        try:

            re.compile( regex )

        except Exception as e:

            raise Exception( 'Cannot compile that regex: {}'.format( e ) )

    def GetInfo( self ):

        operator = self._operator.GetValue()

        if operator:

            operator_description = 'has a url matching regex: '

        else:

            operator_description = 'does not have a url matching regex: '

        rule_type = 'regex'

        regex = self._regex.text()

        rule = regex

        description = operator_description + regex

        return ( operator, rule_type, rule, description )

class PanelPredicateSystemKnownURLsURLClass( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_KNOWN_URLS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._operator = ClientGUICommon.BetterChoice( self )

        self._operator.addItem( 'has', True )
        self._operator.addItem( 'does not have', False )

        self._url_classes = ClientGUICommon.BetterChoice( self )

        for url_class in HG.client_controller.network_engine.domain_manager.GetURLClasses():

            if url_class.ShouldAssociateWithFiles():

                self._url_classes.addItem( url_class.GetName(), url_class )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:known url'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._operator, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'url matching this class:'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._url_classes, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        operator = self._operator.GetValue()

        if operator:

            operator_description = 'has '

        else:

            operator_description = 'does not have '

        rule_type = 'url_class'

        url_class = self._url_classes.GetValue()

        rule = url_class

        description = operator_description + url_class.GetName() + ' url'

        return ( operator, rule_type, rule, description )

class PanelPredicateSystemLimit( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_LIMIT

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._limit = QP.MakeQSpinBox( self, max=1000000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        limit = system_predicates[ 'limit' ]

        self._limit.setValue( limit )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:limit='), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._limit, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = self._limit.value()

        return info

class PanelPredicateSystemMime( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_MIME

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._mimes = ClientGUIOptionsPanels.OptionsPanelMimes( self, HC.SEARCHABLE_MIMES )

        system_predicates = HC.options[ 'file_system_predicates' ]

        mimes = system_predicates[ 'mime' ]

        if isinstance( mimes, int ):

            mimes = ( mimes, )

        self._mimes.SetValue( mimes )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText( self, 'system:filetype' ), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._mimes, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        mimes = self._mimes.GetValue()

        return mimes

class PanelPredicateSystemNumPixels( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_NUM_PIXELS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._num_pixels = QP.MakeQSpinBox( self, max=1048576, width = 60 )

        self._unit = QP.RadioBox( self, choices=['pixels','kilopixels','megapixels'] )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, num_pixels, unit ) = system_predicates[ 'num_pixels' ]

        self._sign.SetStringSelection( sign )

        self._num_pixels.setValue( num_pixels )

        self._unit.SetStringSelection( HydrusData.ConvertIntToPixels( unit ) )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:num_pixels'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._num_pixels, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._unit, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = (self._sign.GetStringSelection(), self._num_pixels.value(), HydrusData.ConvertPixelsToInt( self._unit.GetStringSelection() ))

        return info

class PanelPredicateSystemNumTags( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._num_tags = QP.MakeQSpinBox( self, max=2000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, num_tags ) = system_predicates[ 'num_tags' ]

        self._sign.SetStringSelection( sign )

        self._num_tags.setValue( num_tags )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:num_tags'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._num_tags, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), self._num_tags.value())

        return info

class PanelPredicateSystemNumWords( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._num_words = QP.MakeQSpinBox( self, max=1000000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, num_words ) = system_predicates[ 'num_words' ]

        self._sign.SetStringSelection( sign )

        self._num_words.setValue( num_words )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:num_words'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._num_words, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), self._num_words.value())

        return info

class PanelPredicateSystemRating( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_RATING

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        #

        local_like_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_LIKE, ), randomised = False )

        self._like_checkboxes_to_info = {}

        self._like_rating_ctrls = []

        gridbox = QP.GridLayout( cols = 5 )

        gridbox.setColumnStretch( 0, 1 )

        for service in local_like_services:

            name = service.GetName()
            service_key = service.GetServiceKey()

            rated_checkbox = QW.QCheckBox( 'rated', self )
            not_rated_checkbox = QW.QCheckBox( 'not rated', self )
            rating_ctrl = ClientGUICommon.RatingLikeDialog( self, service_key )

            self._like_checkboxes_to_info[ rated_checkbox ] = ( service_key, ClientRatings.SET )
            self._like_checkboxes_to_info[ not_rated_checkbox ] = ( service_key, ClientRatings.NULL )
            self._like_rating_ctrls.append( rating_ctrl )

            QP.AddToLayout( gridbox, ClientGUICommon.BetterStaticText(self,name), CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, rated_checkbox, CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, not_rated_checkbox, CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, (20,20), CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
            QP.AddToLayout( gridbox, rating_ctrl, CC.FLAGS_VCENTER )

        #

        local_numerical_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_RATING_NUMERICAL, ), randomised = False )

        self._numerical_checkboxes_to_info = {}

        self._numerical_rating_ctrls_to_info = {}

        for service in local_numerical_services:

            name = service.GetName()
            service_key = service.GetServiceKey()

            rated_checkbox = QW.QCheckBox( 'rated', self )
            not_rated_checkbox = QW.QCheckBox( 'not rated', self )
            choice = QP.RadioBox( self, choices=['>','<','=','\u2248'] )
            rating_ctrl = ClientGUICommon.RatingNumericalDialog( self, service_key )

            choice.Select( 2 )

            self._numerical_checkboxes_to_info[ rated_checkbox ] = ( service_key, ClientRatings.SET )
            self._numerical_checkboxes_to_info[ not_rated_checkbox ] = ( service_key, ClientRatings.NULL )
            self._numerical_rating_ctrls_to_info[ rating_ctrl ] = choice

            QP.AddToLayout( gridbox, ClientGUICommon.BetterStaticText(self,name), CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, rated_checkbox, CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, not_rated_checkbox, CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, choice, CC.FLAGS_VCENTER )
            QP.AddToLayout( gridbox, rating_ctrl, CC.FLAGS_VCENTER )

        #

        vbox = QP.VBoxLayout()

        QP.AddToLayout( vbox, gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )

        self.setLayout( vbox )

    def GetInfo( self ):

        infos = []

        #

        for ( checkbox, ( service_key, rating_state ) ) in list(self._like_checkboxes_to_info.items()):

            if checkbox.isChecked():

                if rating_state == ClientRatings.SET:

                    value = 'rated'

                elif rating_state == ClientRatings.NULL:

                    value = 'not rated'

                infos.append( ( '=', value, service_key ) )

        for ctrl in self._like_rating_ctrls:

            rating_state = ctrl.GetRatingState()

            if rating_state in ( ClientRatings.LIKE, ClientRatings.DISLIKE ):

                if rating_state == ClientRatings.LIKE:

                    value = 1

                elif rating_state == ClientRatings.DISLIKE:

                    value = 0

                service_key = ctrl.GetServiceKey()

                infos.append( ( '=', value, service_key ) )

        #

        for ( checkbox, ( service_key, rating_state ) ) in list(self._numerical_checkboxes_to_info.items()):

            if checkbox.isChecked():

                if rating_state == ClientRatings.SET:

                    value = 'rated'

                elif rating_state == ClientRatings.NULL:

                    value = 'not rated'

                infos.append( ( '=', value, service_key ) )

        for ( ctrl, choice ) in list(self._numerical_rating_ctrls_to_info.items()):

            rating_state = ctrl.GetRatingState()

            if rating_state == ClientRatings.SET:

                operator = choice.GetStringSelection()

                value = ctrl.GetRating()

                service_key = ctrl.GetServiceKey()

                infos.append( ( operator, value, service_key ) )

        #

        return infos

    def GetPredicates( self ):

        infos = self.GetInfo()

        predicates = [ ClientSearch.Predicate( self.PREDICATE_TYPE, info ) for info in infos ]

        return predicates

class PanelPredicateSystemRatio( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_RATIO

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['=','wider than','taller than','\u2248'] )

        self._width = QP.MakeQSpinBox( self, max=50000, width = 60 )

        self._height = QP.MakeQSpinBox( self, max=50000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, width, height ) = system_predicates[ 'ratio' ]

        self._sign.SetStringSelection( sign )

        self._width.setValue( width )

        self._height.setValue( height )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:ratio'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._width, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,':'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._height, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = (self._sign.GetStringSelection(), self._width.value(), self._height.value())

        return info

class PanelPredicateSystemSimilarTo( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._hashes = QW.QPlainTextEdit( self )

        ( init_width, init_height ) = ClientGUIFunctions.ConvertTextToPixels( self._hashes, ( 66, 10 ) )

        self._hashes.setMinimumSize( QC.QSize( init_width, init_height ) )

        self._max_hamming = QP.MakeQSpinBox( self, max=256, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        self._hashes.setPlaceholderText( 'enter hash (paste newline-separated for multiple hashes)' )

        hamming_distance = system_predicates[ 'hamming_distance' ]

        self._max_hamming.setValue( hamming_distance )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:similar_to'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._hashes, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, QW.QLabel( '\u2248', self ), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._max_hamming, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        hex_hashes_raw = self._hashes.toPlainText()

        hex_hashes = HydrusText.DeserialiseNewlinedTexts( hex_hashes_raw )

        hex_hashes = [ HydrusText.HexFilter( hex_hash ) for hex_hash in hex_hashes ]

        hex_hashes = HydrusData.DedupeList( hex_hashes )

        hashes = tuple( [ bytes.fromhex( hex_hash ) for hex_hash in hex_hashes ] )

        info = ( hashes, self._max_hamming.value())

        return info

class PanelPredicateSystemSize( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_SIZE

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._bytes = ClientGUIControls.BytesControl( self )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, size, unit ) = system_predicates[ 'size' ]

        self._sign.SetStringSelection( sign )

        self._bytes.SetSeparatedValue( size, unit )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:filesize'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._bytes, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        ( size, unit ) = self._bytes.GetSeparatedValue()

        info = ( self._sign.GetStringSelection(), size, unit )

        return info

class PanelPredicateSystemTagAsNumber( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._namespace = QW.QLineEdit( self )

        choices = [ '<', '\u2248', '>' ]

        self._sign = QP.RadioBox( self, choices = choices )

        self._num = QP.MakeQSpinBox( self, min=-99999999, max=99999999 )

        #

        self._namespace.setText( 'page' )
        self._sign.SetStringSelection( '>' )
        self._num.setValue( 0 )

        #

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:tag as number'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._namespace, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._num, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._namespace.text(), self._sign.GetStringSelection(), self._num.value())

        return info

class PanelPredicateSystemWidth( PanelPredicateSystem ):

    PREDICATE_TYPE = HC.PREDICATE_TYPE_SYSTEM_WIDTH

    def __init__( self, parent ):

        PanelPredicateSystem.__init__( self, parent )

        self._sign = QP.RadioBox( self, choices=['<','\u2248','=','>'] )

        self._width = QP.MakeQSpinBox( self, max=200000, width = 60 )

        system_predicates = HC.options[ 'file_system_predicates' ]

        ( sign, width ) = system_predicates[ 'width' ]

        self._sign.SetStringSelection( sign )

        self._width.setValue( width )

        hbox = QP.HBoxLayout()

        QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'system:width'), CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._sign, CC.FLAGS_VCENTER )
        QP.AddToLayout( hbox, self._width, CC.FLAGS_VCENTER )

        hbox.addStretch( 1 )

        self.setLayout( hbox )

    def GetInfo( self ):

        info = ( self._sign.GetStringSelection(), self._width.value())

        return info


import argparse
from pathlib import Path
import sys
from typing import List, Optional, Sequence

import mdformat
from mdformat._util import is_md_equal

def run(cli_args: Sequence[str]) -> int:  # noqa: C901
    parser = argparse.ArgumentParser(
        description="CommonMark compliant Markdown formatter"
    )
    parser.add_argument("paths", nargs="*", help="Files to format")
    parser.add_argument("--check", action="store_true")
    args = parser.parse_args(cli_args)

    if not args.paths:
        sys.stderr.write("No files have been passed in. Doing nothing.\n")
        return 0

    # Convert paths given as args to pathlib.Path objects.
    # Check that all paths are either files, directories or stdin.
    # Resolve directory paths to a list of file paths (ending with ".md").
    file_paths: List[Optional[Path]] = []  # Path to file or None for stdin/stdout
    for path_str in args.paths:
        if path_str == "-":
            file_paths.append(None)
            continue
        path_obj = Path(path_str)
        try:
            path_exists = path_obj.exists()
        except OSError:  # Catch "OSError: [WinError 123]" on Windows
            path_exists = False
        if not path_exists:
            sys.stderr.write(f'Error: File "{path_str}" does not exist.\n')
            return 1
        if path_obj.is_dir():
            for p in path_obj.glob("**/*.md"):
                file_paths.append(p)
        else:
            file_paths.append(path_obj)

    format_errors_found = False
    for path in file_paths:
        if path:
            path_str = str(path)
            original_str = path.read_text(encoding="utf-8")
        else:
            path_str = "-"
            original_str = sys.stdin.read()
        formatted_str = mdformat.text(original_str)

        if args.check:
            if formatted_str != original_str:
                format_errors_found = True
                sys.stderr.write(f'Error: File "{path_str}" is not formatted.\n')
        else:
            if not is_md_equal(original_str, formatted_str):
                sys.stderr.write(
                    f'Error: Could not format "{path_str}"\n'
                    "\n"
                    "The formatted Markdown renders to different HTML than the input Markdown.\n"  # noqa: E501
                    "This is likely a bug in mdformat. Please create an issue report here:\n"  # noqa: E501
                    "https://github.com/executablebooks/mdformat/issues\n"
                )
                return 1
            if path:
                path.write_text(formatted_str, encoding="utf-8")
            else:
                sys.stdout.write(formatted_str)
    if format_errors_found:
        return 1
    return 0


from typing import Dict, Callable
import pyaml
import time
from jsonable import Jsonable

class ScrapeResult(Jsonable):
  """information for the result of a web scrape of listings(owners)"""

  def __init__(self) -> None:
    # size of the raw http response
    self.bytes = 0

    # how long the scrape took
    self.took = ''

    # total number of listings attempted to be scraped
    self.total = 0

    # actual number of scraped listings
    self.scraped = 0

    # listings that were cached and therefore werent attempted to be scraped
    self.cached = 0

    # how many listing scrapes failed
    self.failures = 0

    # the sum of the number of items for every scraped listing
    self.items = 0

    # summary of the types of items scraped
    self.itemTypes: Dict[str, int] = {}

    # summary of the types of the listings scraped
    self.ownerTypes: Dict[str, int] = {}

  def start(self) -> Callable:
    """starts a scrape result. this is used to calculate how long it took"""
    t0 = time.time()

    def finished() -> None:
      """sets the attributes on this class"""
      t1 = time.time()
      self.took = f'{(t1 - t0):.2f} seconds'
      self.total = self.scraped + self.cached + self.failures
      self.items = sum(self.itemTypes.values())

    # let the caller indicate when the scrape is finished
    return finished

  def pretty(self) -> str:
    """returns a pretty string representing this scrape result"""
    return f'took: {self.took}\n' + pyaml.dump({
      'scraped': self.scraped,
      'failures': self.failures,
      'cached': self.cached,
      'total': self.total,
      'ownerTypes': self.ownerTypes,
      'items': self.items,
      'itemTypes': self.itemTypes,
      'bytes': self.bytes,
    }, sort_dicts=False).strip()


import gym
import gym_minigrid
import datetime
import numpy as np
import torch
import random
import cv2
import pygame
from memory import Memory
from embedder import Embedder
import os
import copy
import atexit
pygame.init()

## Reinforcement Learning Coach
###
### Handles OpenAI Gym environments
#
class Coach():
    def __init__(self, env, loss_fn, optim, gym=gym, preprocess_func=None, utility_func=None, embed=False, flatten=False, frameskip=1, batch_size=32, cuda=False, ale=False, init_skip=0, mid_skip=0, caution=0.0, render_skip=1):

        self.n_agents = 1

        if utility_func == None:
            raise Exception("Need utility function")
        if preprocess_func == None:
            raise Exception("Need preprocess function")
        if self.n_agents < 1:
            raise Exception("Need at least 1 agent.")
        if self.n_agents > 1:
            raise NotImplementedError

        super(Coach, self).__init__()
        print("Initializing Coach")

        self.ale = ale
        self.name = env
        self.gym = gym
        self.dones = [False for _ in range(self.n_agents)]
        self.length = 0
        self.memory = Memory(self.n_agents)
        self.episode = []
        self.embedder = Embedder()
        self.embedding = embed
        self.flatten = flatten
        self.best_episode = []
        self.p_obs = torch.zeros(1)
        self.values = []
        self.frameskip = frameskip
        self.loss_fn=loss_fn
        self.optim = optim
        self.preview = False
        self.single_step = False
        self.norm = True
        self.render = False
        self.debug_render = False
        self.caution = caution#0.95
        self.life = -1
        self.life = -1
        self.init_skip = init_skip#70
        self.render_frameskip = render_skip
        self.mid_skip = mid_skip#50
        self.steps = 0
        self.batch_size = batch_size
        self.preprocess_frame = preprocess_func
        self.update = utility_func
        self.cuda = cuda

        atexit.register(self.end)
        #create environments
        self.envs = [self.gym.make(self.name) for _ in range(self.n_agents)]
        self.env = 0

        self.actions = self.envs[0].action_space.n

        os.system("toilet {}".format(self.name))

    def weights_init(self, m):
        classname = m.__class__.__name__
        if classname.find('Linear') != -1:
            torch.nn.init.Xavier(m.weight.data, 0.0, 0.05)
            torch.nn.fill(m.weight.bias, 1.0)
        if classname.find('Conv2d') != -1:
            torch.nn.init.Xavier(m.weight.data, 1.0, 0.05)
            torch.nn.fill(m.weight.bias, 0.0)

    def set_agent(self, agent, lr):
        self.agent = agent
        self.weights_init(self.agent)
        self.target_agent = copy.copy(agent)
        print(self.agent)

        if lr > 0.0:
            self.optimizer = self.optim(lr=lr, weight_decay=0.99, params=self.target_agent.parameters())
        self.memory.set_keys(agent.transition_keys)

    def set_rate(self, lr):
        print("Learning rate: {}".format(lr))
        self.optimizer = self.optim(lr=lr, params=self.agent.parameters())

    def replay_episode(self, episode):
        for t in episode:
            t = cv2.resize(t, (512, 512))
            cv2.imshow("replay", t)
            cv2.waitKey(2)

    #reset all environments
    def reset(self):
        if self.agent == None:
            raise("Need agent")
        states = []
        for env in self.envs:
            env.render()

            state=env.reset()
            for _ in range(self.init_skip):
                state,_,_,info = env.step(1)
            states.append(state)

        if self.ale and ("ale.lives" in info.keys()):
            self.life = info["ale.lives"]
            self.life = self.life
        return states

    def end(self):
        print("\nClosing gym")
        [env.close() for env in self.envs]

    #environment step
    def step(self, actions):
        obs = []
        rewards = []
        dones = []
        infos = []
        #take step for each agent/environment
        for i,env in enumerate(self.envs):
            reward = 0.0
            for _ in range(self.frameskip):
                obv, r, done, info = env.step(int(actions[i]))
                reward += r

            obs.append(obv)
            rewards.append(reward)
            dones.append(done)
            infos.append(info)

        #send each return separately
        return obs, rewards, dones, infos

    def get_keys(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                break
            if event.type == pygame.KEYDOWN:
                # gets the key name
                key = pygame.key.name(event.key)
                if key == 'v':
                    self.debug_render = not self.debug_render
                    print("Render {}".format(self.debug_render))
                if key == 'r':
                    self.replay_episode(self.best_episode)
                if key == 'f':
                    if self.render_frameskip == 1:
                        self.render_frameskip = 10
                        print("Frameskip True")
                    else:
                        self.render_frameskip = 1
                        print("Frameskip False")
                if key == 's':
                    self.single_step = not self.single_step
                    self.debug_render = self.single_step
                    print("Render {}".format(self.debug_render))
                    print("Single step {}".format(self.single_step))

    def render_env(self):
        if self.steps % self.render_frameskip == 0:
            for env in self.envs:
                env.render()

    def learn(self, gamma):
        return self.update(gamma, self.memory, self.optimizer)

    def target_net_update(self):
        print("Agent parameter update.")
        self.agent.load_state_dict(self.target_agent.state_dict())

    def run_episode(self, render=False, gamma=0.99, max_steps=100, explore=False):

        self.render = render

        for env in self.envs:
            env._max_episode_steps = max_steps

        self.last_episode = []

        state = self.reset()
        observation = self.preprocess_frame(state)
        steps = np.zeros(self.n_agents)
        rewards = np.expand_dims(np.zeros(self.n_agents),axis=0)
        score = 0
        confidence = 1.0

        for _ in range(max_steps):
            self.get_keys()

            action, memory_info = self.agent.step(observation, self.memory, confidence, self.render, explore, self.single_step)

            confidence = memory_info['confidence']

            obs, reward, done, info = self.step(action)
            score += reward[0]

            if self.render or self.debug_render:
                self.render_env()

            observation = self.preprocess_frame(obs)

            confidence *= self.caution
            confidence += reward[0]
            confidence = max(min(confidence, 1), 0.2)

            self.memory.add_value(("action",action[0]))

            dones = [not d for d in done]

            steps += dones * np.ones(self.n_agents)
            rewards += np.array(dones) * np.array(reward[0])

            if np.prod(done, 0) or (self.ale and info[0]["ale.lives"] < self.life):
                reward[0] = -1.0
                score -= 1
                for i, r in enumerate(reward):
                    self.memory.add_value(("reward", r))

                self.confidence = 1.0
                self.memory.finish_episode(gamma)
                self.life -= 1
                states = []
                for env in self.envs:
                    for _ in range(self.mid_skip):
                        state, _, _, info = env.step(0)
                    states.append(state)
            else:
                for i, r in enumerate(reward):
                    self.memory.add_value(("reward", r))

            if np.prod(done, 0) or self.life == 0:
                break

        self.agent.steps = 0
        return int(score), int(steps)

    def discount(self, gamma):
        R = 0.0

        values = [[] for _ in range(self.n_agents)]
        for step in reversed(self.memory.rewards):
            for i,r in enumerate(step):
                R = r + R * gamma
                values[i].insert(0,R)

        values = torch.tensor(np.array(values))
        return values


# -*- coding: utf-8 -*-

import simple_draw as sd

# Часть 1.
# Написать функции рисования равносторонних геометрических фигур:
# - треугольника
# - квадрата
# - пятиугольника
# - шестиугольника
# Все функции должны принимать 3 параметра:
# - точка начала рисования
# - угол наклона
# - длина стороны
#
# Использование копи-пасты - обязательно! Даже тем кто уже знает про её пагубность. Для тренировки.
# Как работает копипаста:
#   - одну функцию написали,
#   - копипастим её, меняем название, чуть подправляем код,
#   - копипастим её, меняем название, чуть подправляем код,
#   - и так далее.
# В итоге должен получиться ПОЧТИ одинаковый код в каждой функции

# Пригодятся функции
# sd.get_point()
# sd.get_vector()
# sd.line()
# Результат решения см lesson_004/results/exercise_01_shapes.jpg

# def triangle_first_edition(point=sd.get_point(0, 0), angle=0, length=100):
#     v1 = sd.get_vector(start_point=point, angle=angle, length=length, width=3)
#     v1.draw()
#     v2 = sd.get_vector(start_point=v1.end_point, angle=angle + 120, length=length, width=3)
#     v2.draw()
#     v3 = sd.get_vector(start_point=v2.end_point, angle= angle + 240, length=length, width=3)
#     v3.draw()

# # Вызов функции
# start_point = sd.get_point(300, 300)
# angle = 25
# length = 235
# triangle_first_edition(point=start_point, angle=angle, length=length)
# #===============================================================================================================

# # Рефакторим код: вводим цикл
# def triangle_second_edition(point=sd.get_point(0, 0), angle=0, length=100):
#     first_vector = sd.get_vector(start_point=point, angle=angle, length=length, width=1)
#     first_vector.draw()
#     next_vector = first_vector
#     for i in range(2):
#         angle += 120
#         next_vector = sd.get_vector(start_point=next_vector.end_point, angle=angle, length=length, width=1)
#         next_vector.draw()
#
#
# # Вызов функции
# start_point = sd.get_point(250, 250)
# angle = 23
# length = 272
# triangle_second_edition(point=start_point, angle=angle, length=length)
# #===============================================================================================================

# # Рефакторим код далее: устраняем разрыв в будущих фигурах условием достижения последней грани,
# # которую рисуем линией
# def triangle_third_edition(point=sd.get_point(0, 0), angle=0, length=100):
#     first_vector = sd.get_vector(start_point=point, angle=angle, length=length, width=1)
#     first_vector.draw()
#     next_vector = first_vector
#     for i in range(2):
#         if i == 1:
#             sd.line(start_point=next_vector.end_point, end_point=point)
#         else:
#             angle += 120
#             next_vector = sd.get_vector(start_point=next_vector.end_point, angle=angle, length=length, width=1)
#             next_vector.draw()
#
#
# # Вызов функции
# start_point = sd.get_point(150, 150)
# angle = 45
# length = 287
# triangle_third_edition(point=start_point, angle=angle, length=length)
#
# Навороты из закрученных треугольников
# length_vector = 150
# angle = 0
# center_vector = sd.get_point(300, 300)
# length_draw = 100
# for angle_vector in range(0, 361, 30):
#     draw_line = sd.get_vector(start_point=center_vector, angle=angle_vector, length=length_vector, width=1)
#     angle_vector += 30
#     center_draw = draw_line.end_point
#     for angle in range(0, 361, 20):
#         triangle(point=center_draw, angle=angle, length=length_draw)
# # ===============================================================================================================

# # Рефакторим код далее: делаем задел для построения многоугольников, вводим параметр количество углов
# def triangle_fourth_edition(point=sd.get_point(0, 0), angle=0, length=100, corner=3):
#     first_vector = sd.get_vector(start_point=point, angle=angle, length=length, width=1)
#     first_vector.draw()
#     next_vector = first_vector
#     for i in range(corner - 1):
#         if i == corner - 2:
#             sd.line(start_point=next_vector.end_point, end_point=point)
#         else:
#             angle += int(360 / corner)
#             next_vector = sd.get_vector(start_point=next_vector.end_point, angle=angle, length=length, width=1)
#             next_vector.draw()
#
#
# # Вызов функции
# start_point = sd.get_point(175, 175)
# angle = 49
# length = 302
# triangle_fourth_edition(point=start_point, angle=angle, length=length, corner=3)
#
# #===============================================================================================================

# # Наслаждаемся жизнью, строим любые равносторонние многоугольники
def polygon(point=sd.get_point(0, 0), angle=0, length=100, corner=3):
    first_vector = sd.get_vector(start_point=point, angle=angle, length=length, width=1)
    first_vector.draw()
    next_vector = first_vector
    for i in range(corner - 1):
        if i == corner - 2:
            sd.line(start_point=next_vector.end_point, end_point=point)
        else:
            angle += int(360 / corner)
            next_vector = sd.get_vector(start_point=next_vector.end_point, angle=angle, length=length, width=1)
            next_vector.draw()

# # Вызов функции
# start_point = sd.get_point(300, 200)
# angle = 0
# length = 50
# polygon(point=start_point, angle=angle, length=length, corner=8)
#
# # ===============================================================================================================

def square(point=sd.get_point(0, 0), angle=0, length=100):
    polygon(point=point, angle=angle, length=length, corner=4)

def pentagon(point=sd.get_point(0, 0), angle=0, length=100):
    polygon(point=point, angle=angle, length=length, corner=5)

def hexagon(point=sd.get_point(0, 0), angle=0, length=100):
    polygon(point=point, angle=angle, length=length, corner=6)

# Вызов функций
start_point = sd.get_point(300, 200)
angle = 0
length = 150
polygon(point=start_point, angle=angle, length=length, corner=3)
square(point=start_point, angle=angle, length=length)
pentagon(point=start_point, angle=angle, length=length)
hexagon(point=start_point, angle=angle, length=length)

# Часть 1-бис.
# Попробуйте прикинуть обьем работы, если нужно будет внести изменения в этот код.
# Скажем, связывать точки не линиями, а дугами. Или двойными линиями. Или рисовать круги в угловых точках. Или...
# А если таких функций не 4, а 44?

# Часть 2 (делается после зачета первой части)
#
# Надо сформировать функцию, параметризированную в местах где была "небольшая правка".
# Это называется "Выделить общую часть алгоритма в отдельную функцию"
# Потом надо изменить функции рисования конкретных фигур - вызывать общую функцию вместо "почти" одинакового кода.
#
# В итоге должно получиться:
#   - одна общая функция со множеством параметров,
#   - все функции отрисовки треугольника/квадрата/етс берут 3 параметра и внутри себя ВЫЗЫВАЮТ общую функцию.
#
# Не забудте в этой общей функции придумать, как устранить разрыв
#   в начальной/конечной точках рисуемой фигуры (если он есть)

# Часть 2-бис.
# А теперь - сколько надо работы что бы внести изменения в код? Выгода на лицо :)
# Поэтому среди программистов есть принцип D.R.Y. https://clck.ru/GEsA9
# Будьте ленивыми, не используйте копи-пасту!

sd.pause()


import numpy, pandas, wave, struct
import seqlearn.hmm as seq
import matplotlib.pyplot as plt
from hmmlearn.hmm import GaussianHMM
from pylab import *
from os import listdir
from os.path import isfile, join
from copy import deepcopy

def get_raw_data(file):
    FNAME = 'set_a/' + file
    f = wave.open(FNAME)
    frames = f.readframes(-1)
    samples = struct.unpack('h'*f.getnframes(), frames)
    s = list(samples)
    framerate = f.getframerate()
    t = [float(i)/framerate for i in range(len(samples))]
    return (t, s)

def get_training_data(filename):
    data_frame = pandas.read_csv(filename)
    return data_frame

def generate_training_labels(df, s1, s2):
    xlabels = []
    ylabels = []
    current = 'Systole'
    for i in range (0, len(df)):
        xlabels.append(df[i])
        if i in s1:
            ylabels.append('S1')
            current = 'Systole'
        elif i in s2:
            ylabels.append('S2')
            current = 'Diastole'
        else:
            ylabels.append(current)
    return xlabels, ylabels

def get_set_a_data():
    mypath = 'set_a/'
    filenames = [f for f in listdir(mypath) if (isfile(join(mypath, f)) and f[-4:] == ".wav")]
    samples = []
    times = []

    for file in filenames:
        t, s = get_raw_data(file)
        samples.append(s)
        times.append(t)

    return filenames, times, samples

def make_set_a_labels():
    training_data = get_training_data('set_a_timing.csv')
    training_fnames = list(set(training_data["fname"]))
    s1vals = []
    s2vals = []
    training_xlabels = []
    training_ylabels = []
    training_indices = []
    seq_xlabels = []
    seq_ylabels = []
    seq_lengths = []

    for fname in training_fnames:
        filtered_by_file = training_data.loc[training_data['fname'] == fname]
        s1 = list(filtered_by_file.loc[filtered_by_file['sound'] == 'S1']['location'])
        s2 = list(filtered_by_file.loc[filtered_by_file['sound'] == 'S2']['location'])
        fname_index = filenames.index(fname[6:])
        training_indices.append(fname_index)
        df = samples[fname_index]
        xlabels, ylabels = generate_training_labels(df, s1, s2)

        s1vals.append(s1)
        s2vals.append(s2)
        training_xlabels.append(xlabels)
        training_ylabels.append(ylabels)
        seq_xlabels.extend(xlabels)
        seq_ylabels.extend(ylabels)
        seq_lengths.append(len(df))

    return (s1vals, s2vals, training_xlabels, training_ylabels, training_indices,
            seq_xlabels, seq_ylabels, seq_lengths)

def plot_waves_with_labels(t,s,s1,s2):
    fig = figure()
    plt.plot(t, s)
    for i in range (0, len(s1)):
        axvline(x = t[s1[i]], color = "red")
    for i in range (0, len(s2)):
        axvline(x = t[s2[i]], color = "green")

def HMM_stuff(training_xlabels, training_ylabels):
    X = []
    Y = []
    lengths = []
    for i in range (0,len(training_xlabels)):
        x = numpy.vstack(numpy.array(training_xlabels[i]))
        X.append(x)
        y = numpy.vstack(numpy.array(training_ylabels[i]))
        Y.append(y)
        l = len(training_xlabels[i])
    lengths.append(l)

def find_indices_of(array, target):
    indices = []
    for i in range (0, len(array)):
        if array[i] == target:
            indices.append(i)
    return indices

def calculate_percent_correct(predicted, actual):
    total_correct = 0
    for i in range (0, len(predicted)):
        if predicted[i] == actual[i]:
            total_correct = total_correct + 1
    return total_correct/len(predicted)

filenames, times, samples = get_set_a_data()
s1vals, s2vals, training_xlabels, training_ylabels, training_indices, seq_xlabels, seq_ylabels, seq_lengths = make_set_a_labels()

for i in range(0,len(training_indices)):
    index = training_indices[i]
    plot_waves_with_labels(times[index], samples[index], s1vals[i], s2vals[i])

modelH = GaussianHMM(n_components=4, covariance_type="diag")
modelH.fit(numpy.vstack(numpy.array(training_xlabels[0])))
resultsH = modelH.predict(numpy.vstack(numpy.array(training_xlabels[0])))

actual_results = deepcopy(training_ylabels[0])
actual_results[actual_results == 'S1'] = 0
actual_results[actual_results == 'Systole'] = 1
actual_results[actual_results == 'S2'] = 2
actual_results[actual_results == 'Diastole'] = 3

modelS = seq.MultinomialHMM()
modelS.fit(numpy.vstack(numpy.array(seq_xlabels)), numpy.vstack(numpy.array(seq_ylabels)), numpy.array(seq_lengths))
resultsS = modelS.predict(numpy.vstack(numpy.array(seq_xlabels)), numpy.array(seq_lengths))

HMM_correct = calculate_percent_correct(resultsH, actual_results)
print("Hmmlearn was", HMM_correct, "percent correct\n")
SEQ_correct = calculate_percent_correct(resultsS, seq_ylabels)
print("Seqlearn was", SEQ_correct, "percent correct\n")


"""   QuArK  -  Quake Army Knife

The map editor's "Selection" menu (to be extended by plug-ins)
"""
#
# Copyright (C) 1996-99 Armin Rigo
# THIS FILE IS PROTECTED BY THE GNU GENERAL PUBLIC LICENCE
# FOUND IN FILE "COPYING.TXT"
#

#$Header$

import quarkx
import qmenu
from maputils import *

def getEditorSelection(editor=None):
    if editor is None:
        editor = mapeditor(SS_MAP)
    if editor is None:
        return None, None
    sel = editor.layout.explorer.uniquesel
    return editor, sel

def EscClick(m):
    editor = mapeditor(SS_MAP)
    if editor is None: return
    if editor.layout.mpp.n:
        editor.layout.mpp.viewpage(0)
    else:
        editor.layout.explorer.uniquesel = None

def parentClick(m,editor=None):
    editor, sel = getEditorSelection(editor)
    if sel is None: return
    parent = sel.treeparent
    if parent.name!="worldspawn:b":
        editor.layout.explorer.uniquesel = parent

def nextClick(m,editor=None):
    editor, sel = getEditorSelection(editor)
    if sel is None: return
    next = sel.nextingroup()
    if next is None:
        parent = sel.treeparent
        if parent is not None:
            next=parent.subitems[0]
    editor.layout.explorer.uniquesel=next

def prevClick(m,editor=None):
    editor, sel = getEditorSelection(editor)
    if sel is None: return
    parent=sel.treeparent
    if parent is None: return
    index = parent.subitems.index(sel)
    if index>0:
        prev = parent.subitem(index-1)
    else:
        prev = parent.subitem(len(parent.subitems)-1)
    editor.layout.explorer.uniquesel=prev

removeItem = qmenu.item("Remove selection", EscClick, "|The first time to press Esc, you are sent back to the 1st page; the second time, or if you where already at the 1st page, the currently selected objects are unselected.")
parentItem = qmenu.item("Select Parent", parentClick, "Selects parent")
nextItem = qmenu.item("Select Next", nextClick, "Selects next item in group, cycling")
prevItem = qmenu.item("Select Previous", prevClick, "Selects previous item in group, cycling")

#
# Global variables to update from plug-ins.
#

items = [removeItem, parentItem, nextItem, prevItem]
shortcuts = {}

def onclick(menu):
    editor=mapeditor()
    prevItem.state=nextItem.state=parentItem.state=qmenu.disabled
    removeItem.state=qmenu.disabled
    if editor is not None:
        if editor.layout.explorer.uniquesel:
            prevItem.state=nextItem.state=parentItem.state=qmenu.normal
            removeItem.state=qmenu.normal

def SelectionMenu():
    "The Selection menu, with its shortcuts."

    MapHotKeyList("Remove", removeItem, shortcuts)
    MapHotKeyList("Select Parent", parentItem, shortcuts)
    MapHotKeyList("Select Next", nextItem, shortcuts)
    MapHotKeyList("Select Previous", prevItem, shortcuts)

    return qmenu.popup("Selection", items, onclick), shortcuts

# $Log$
#
#


'''
Created on Dec 19, 2016

@author: Stan
'''

class Console:
    '''
    classdocs
    '''

    def __init__(self,itemctrl,filename):
        '''
        Constructor
        '''
        self.__itemctrl=itemctrl
        self.__filename=filename

    def save_ui(self):
        name=input('Name of the item:')
        productdate=input('Date of production:')
        price=input('Price:')
        self.__itemctrl.save(name,productdate,price)
        print('Succesfully added!')

    def print_ui(self):
        items=self.__itemctrl.get_all()
        if len(items)==0:
            print('We have no items in the repository !')
        for item in items:
            print(item)
    def promotion_by_name(self):
        letter=input('Letter:')
        procentage=input('discount ( a number between 0 and 100):')
        try:
            procentage=int(procentage)
            if procentage<0 or procentage>100:
                raise ValueError('Wrong procentage')
        except:
            raise ValueError('Wrong procentage!')
        self.__itemctrl.promotionbyname(letter,procentage)

    def promotion_by_date(self):
        date=input('date(dd.mm.yyyy)')
        self.__itemctrl.promotionbydate(date)

    def writetofile(self):
        list1=self.__itemctrl.createlistprice()
        dif=[]
        index=0
        for item in self.__itemctrl.get_all():
            minilist=[item.price-list1[index],index]
            dif.append(minilist)
            index+=1
        dif=sorted(dif,key=lambda x: x[0],reverse=False)

        f=open(self.__filename,'w')
        f.write(self.__itemctrl.get_all()[dif[0][1]].name+' '+self.__itemctrl.get_all()[dif[0][1]].productiondate+' '+str(self.__itemctrl.get_all()[dif[0][1]].price))
        f.write(self.__itemctrl.get_all()[dif[1][1]].name+' '+self.__itemctrl.get_all()[dif[1][1]].productiondate+' '+str(self.__itemctrl.get_all()[dif[1][1]].price))
        f.write(self.__itemctrl.get_all()[dif[2][1]].name+' '+self.__itemctrl.get_all()[dif[2][1]].productiondate+' '+str(self.__itemctrl.get_all()[dif[2][1]].price))

    def readcommand(self):
        return input('Command nr:')

    def printmenu(self):
        print('~~~~~~~~~MENU~~~~~~~~~~~~')
        print('1.save an item ')
        print('2.print all the items')
        print('3.Promotion by name')
        print('4.Promotion by date')
        print('9.exit and write to file')
        print('~~~~~~~~~~~~~~~~~~~~~~~~~')
    def run(self):
        cmds={'1':self.save_ui,'2':self.print_ui,'3':self.promotion_by_name,'4':self.promotion_by_date}
        while True:
            self.printmenu()
            cmd=self.readcommand()
            if cmd=='9':
                self.writetofile()
                break
            if cmd in cmds:
                try:
                    cmds[cmd]()
                except Exception as ex:
                    print(ex)
            else:
                print('Invalid command')
            input('Press enter to continue..')

Python/Fundamentals of Programming - 1st semester/Test - December 2016/src/console/console.py


#mongodb에 저장
import json
from pymongo import MongoClient

with open('D:\py\myPythonlearning\py1810\myinfo.json') as f:
    data = json.load(f)

host = data['host']
port = data['port']

#mongodb 접속
client = MongoClient(host, port)
db = client.get_database('mongodb')
col = db.get_collection('aptcol')

#파일 open
with open('apt.json', 'r', encoding='utf-8') as f:
    japt = json.load(f)

print(type(japt))

insert = col.insert(japt)

# print(insert.inserted_id)


import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle('切蛋糕')  #窗口标题
        self.setGeometry(5,30,500,730)  #窗口的大小和位置设置
        self.browser=QWebEngineView()
        #加载外部的web界面
        self.browser.load(QUrl('https://game.redcountry.top/qdg/'))
        self.setCentralWidget(self.browser)
if __name__ == '__main__':
    app=QApplication(sys.argv)
    win=MainWindow()
    win.show()
    app.exit(app.exec_())


# coding: utf-8

import sys
import numpy as np
import pandas as pd
from scraping_weather import get_tables, main

#df = pd.read_csv('/Users/HayatoSumino/Desktop/cloned/disney_tour/lib/others/data/crowds.csv')
weather4, crowds_land4 = main(get_tables(2017, 4)[1])
weather5, crowds_land5 = main(get_tables(2017, 5)[1])

csv_path = sys.argv[1]

fp = pd.read_csv(csv_path, header=None)
fp = fp.rename(columns={0: 'time', 1: 'diff', 2: 'date'})
fp['crowds_land'] = -1
fp['weather'] = -1

for ix, row in fp.iterrows():
    r = str(int(row['date']))
    year, month, day = map(int, [r[:4], r[4:6], r[6:]])
    if month == 4:
        fp.ix[ix, 'crowds_land'] = crowds_land4[day-1]
        fp.ix[ix, 'weather'] = weather4[day-1]
    elif month == 5:
        fp.ix[ix, 'crowds_land'] = crowds_land4[day-1]
        fp.ix[ix, 'weather'] = weather5[day-1]

steps_of_history=10
def create_dataset(dataset, steps_of_history=10, steps_in_future=1):
    X, Y = [], []
    for i in range(0, len(dataset)-steps_of_history, steps_in_future):
        X.append(dataset[i:i+steps_of_history])
        Y.append(dataset[i + steps_of_history])
    #X = np.reshape(np.array(X), [-1, steps_of_history, 1])
    #Y = np.reshape(np.array(Y), [-1, 1])
    return X, Y

days = fp['date'].drop_duplicates()
data = []
for day in days:
    _fp = fp[fp['date'] == day]
    _fp.sort_values(by='time')
    previous, _ = create_dataset(list(_fp['diff']), steps_of_history)
    other = _fp[steps_of_history:]
    for i in range(len(previous)):
        data.append(previous[i] + list(other.iloc[i]))

df = pd.DataFrame(data, columns=list(reversed(range(10)))+list(fp.columns))
df.to_csv(sys.argv[1][:-4]+'_formatted.csv', index=False)


#!/usr/local/bin/python3

from cgitb import enable
enable()

def show_comments():
    from cgi import FieldStorage
    import pymysql as db
    from os import environ

    user_comments = ''
    url = environ.get('SCRIPT_NAME')
    try:
        connection = db.connect('cs1.ucc.ie','dr13','chujohqu','csdipact2017_dr13')
        cursor = connection.cursor(db.cursors.DictCursor)
        form_data = FieldStorage()
        if len(form_data) != 0:
            username = form_data.getfirst('username')
            new_comment = form_data.getfirst('new_comment')
            cursor.execute("""INSERT INTO user_comments (username, url, comment)
                              VALUES (%s, %s, %s)""", (username, url, new_comment))
            connection.commit()
        cursor.execute("""SELECT * FROM user_comments
                          WHERE url = %s
                          ORDER BY comment_id DESC""", (url))
        for row in cursor.fetchall():
            user_comments += '

%s

%s

' % (row['username'], row['comment'])
        cursor.close()
        connection.close()
    except db.Error:
        user_comments = '
User Comments cannot be displayed. Please try again later.
'

    return """

Did you like the Quiz? Have you ideas for a quiz?

            <form action="%s" method="post">
                <fieldset>
                    <legend>Tell us below</legend>
                    Name:
                    <input type="text" name="username" id="username" />
                    Comment:
                    <textarea name="new_comment" id="new_comment" rows="5" cols="50">
                    </textarea>
                    <input type="submit" id="x"/>
                </fieldset>
            </form>

User Comments

            %s

""" % (url, user_comments)


#!/usr/bin/python

import sys,os, re, csv
import pandas as pd
import numpy as np
from collections import defaultdict

residue_name=[]
atom_data=[]
epsi_data=[]
lines_epsi=[]
lines_mass=[]
lines_pdb=[]

def print_full(x):
    pd.set_option('display.max_rows', len(x))
    print(x)
    pd.reset_option('display.max_rows')

########################################################
########################################################
#Temporary files for atoms
#z__atomlist.tmp - list of every atom in every residue from topology file
#z_mass.tmp - types of all atoms and their mass
#z_epsi.tmp - types of atoms and  epsilon and sigma values
#z_atoms.tmp - atom types , mass, epsilon and sigma values in one file.
#
# #Reads residues, atom types and partial charge fromtopology and stores data in temporary file
# with open('aminoacids.rtp','r') as input_topo, open('z_atomlist.tmp','w') as atomlist:
#     for line in input_topo:
#         if line.startswith(';'):
#             continue
#         if line.startswith('[') and line[2:8].isupper():
#             residue_name=line.split()
#         if '.' in line:
#             atoms_list = line.split()
#             data = '{}\t{}\t{}\t{: >}\n'.format(residue_name[1],atoms_list[0],atoms_list[1],atoms_list[2])
#             atomlist.write(data)

# #Reads atom types and mass from atomtypes.tpr
# with open('atomtypes.atp','r') as input_mass, open('z_mass.tmp','w') as zmass:
#     for line in input_mass:
#         if line.startswith(';'):
#             continue
#         if '.' in line:
#             atom_mass = line.split()
#             mass = '{}\t{}\n'.format(atom_mass[0],atom_mass[1])
#             zmass.write(mass)

# #Reads epsilon and sigma from ffnonbonded.itp
# with open('ffnonbonded.itp','r') as input_epsi, open('z_epsi.tmp','w') as epsi:
#     for line in input_epsi:
#         if line.startswith(';'):
#             continue
#         if '.' in line:
#             atom_epsi = line.split()
#             epsi_data = '{}\t{}\n'.format(atom_epsi[5],atom_epsi[6])
#             epsi.write(epsi_data)

# #Main atom output combination
# with open('z_mass.tmp','r') as atom_mass, open('z_epsi.tmp','r') as atom_epsi,open('z_atoms.tmp','w') as output:
#     reader1 = csv.reader(atom_mass, delimiter='\t')
#     reader2 = csv.reader(atom_epsi,delimiter='\t')
#     writer = csv.writer(output,delimiter='\t')
#     for row1, row2 in zip(reader1,reader2):
#         zipped = row1[0],row1[1],row2[0],row2[1]
#         ff='{}\t{}\t{}\t{}\n'.format(row1[0],row1[1],row2[0],row2[1])
#         output.write(ff)

# with open('atom_nom_output.tbl','r') as pdb_names, open ('z_pdb_names.tmp','w')as output:
#     for line in pdb_names:
#         if line.startswith(';'):
#             continue
#         else:
#             lines_pdb = line.split()
#             pdb_data = '{}\t{}\t{}\t{}\t{}\n'.format(lines_pdb[0],lines_pdb[1],lines_pdb[2],lines_pdb[3],lines_pdb[4])
#             output.write(pdb_data)

########################################################
########################################################

with open('z_atomlist.tmp','r') as atom_list:
    df1=pd.read_csv(atom_list, header=None,index_col=None,sep='\t',names=['Residue','AtName','AtType','Charge'])

with open('z_atoms.tmp','r') as atoms:
    df2=pd.read_csv(atoms, header=None,index_col=None,sep='\t',names=['AtType','Mass','Sigma','Epsilon'])

# with open('z_pdb_names.tmp','r') as pdb_names:
    # df3=pd.read_csv(pdb_names, header=None, index_col=None,sep='\t',names=['Residue','XPLOR','MSI','GROMACS','PDB'])

    print_full(df1)

with open ('atoms.par','w') as output:
    df4= pd.merge(df1,df2,on='AtType',how = 'left')
    df4.to_csv(output,sep='\t')

    # df5=pd.merge(df4,df3['PDB'],left_on='AtType',right_on='PDB',left_index=True)
    # print_full(df5)


import psycopg2
from flask import Flask, jsonify, request
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

conn = psycopg2.connect(
        database="postgres", user="postgres", password="*****", host="*****", port="5432")

@app.route('/rest/anon/tasks',methods=['POST'])
def create():
    cur = conn.cursor()
    data = request.get_json()
    cur.execute("insert into taskthree(performer, description, begintime, endtime, state, title) values(%s,%s,%s,%s,%s,%s)",
             (data['performer'], data['description'], data['begintime'], data['endtime'], data['state'], data['title']))
    conn.commit()
    return "1"

@app.route('/rest/anon/tasks',methods=['GET'])
def read():
    cur = conn.cursor()
    cur.execute(
        "select * from taskthree")
    rows = cur.fetchall()
    l = []
    for row in rows:
        print(row)
        dic= {'id': str(row[0]),'description': str(row[1]),'begintime':str(row[2]),'endtime':str(row[3]),'performer':str(row[4]),'state':str(row[5]),'title':str(row[6])}
        l.append(dic)
    return jsonify(l)

@app.route('/rest/anon/tasks/<string:id>', methods=['PUT'])
def update(id):
    cur = conn.cursor()
    data = request.get_json()

    cur.execute("UPDATE taskthree SET performer = '{}', title = '{}', description = '{}', state = '{}', begintime = '{}', endtime = '{}'  WHERE id = {}"
        .format(data['performer'],data['title'],data['description'],data['state'],data['begintime'],data['endtime'], id))

    conn.commit()
    return "1"

@app.route('/rest/anon/tasks/<string:id>', methods=['DELETE'])
def delete(id):
    cur = conn.cursor()
    # cur.execute("DELETE from tasktwo where id=%s", id)
    cur.execute("DELETE from taskthree where id="+ id)
    conn.commit()
    return "1"

if __name__ == '__main__':
    app.run()


# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'MainContentArea.language_code'
        db.add_column(u'widgy_i18n_maincontentarea', 'language_code',
                      self.gf('django.db.models.fields.CharField')(default=u'fi', max_length=2),
                      keep_default=False)

        # Adding field 'SidebarArea.language_code'
        db.add_column(u'widgy_i18n_sidebararea', 'language_code',
                      self.gf('django.db.models.fields.CharField')(default=u'fi', max_length=2),
                      keep_default=False)

    def backwards(self, orm):
        # Deleting field 'MainContentArea.language_code'
        db.delete_column(u'widgy_i18n_maincontentarea', 'language_code')

        # Deleting field 'SidebarArea.language_code'
        db.delete_column(u'widgy_i18n_sidebararea', 'language_code')

    models = {
        u'widgy_i18n.i18nlayout': {
            'Meta': {'object_name': 'I18NLayout'},
            'container_classes': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'language_code': ('django.db.models.fields.CharField', [], {'default': "u'fi'", 'max_length': '2'})
        },
        u'widgy_i18n.i18nlayoutcontainer': {
            'Meta': {'object_name': 'I18NLayoutContainer'},
            'container_classes': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
        },
        u'widgy_i18n.maincontentarea': {
            'Meta': {'object_name': 'MainContentArea'},
            'container_classes': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'language_code': ('django.db.models.fields.CharField', [], {'default': "u'fi'", 'max_length': '2'})
        },
        u'widgy_i18n.multilanguagelayout': {
            'Meta': {'object_name': 'MultiLanguageLayout', '_ormbases': [u'widgy_i18n.I18NLayout']},
            u'i18nlayout_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['widgy_i18n.I18NLayout']", 'unique': 'True', 'primary_key': 'True'})
        },
        u'widgy_i18n.multilanguagelayoutcontainer': {
            'Meta': {'object_name': 'MultiLanguageLayoutContainer', '_ormbases': [u'widgy_i18n.I18NLayoutContainer']},
            u'i18nlayoutcontainer_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['widgy_i18n.I18NLayoutContainer']", 'unique': 'True', 'primary_key': 'True'})
        },
        u'widgy_i18n.sidebararea': {
            'Meta': {'object_name': 'SidebarArea'},
            'container_classes': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'language_code': ('django.db.models.fields.CharField', [], {'default': "u'fi'", 'max_length': '2'})
        }
    }

    complete_apps = ['widgy_i18n']


import copy

from bot.player.enums import TrackType

class Track:
    def __init__(self, service=None, url=None, name=None, format=None, extra_info=None, type=TrackType.Default):
        self.service = service
        self.url = url
        self.name = name
        self.format = format
        self.extra_info = extra_info
        self.type = type
        if service:
            self.type = TrackType.Dynamic
        self._is_fetched = False

    def _fetch_stream_data(self):
        if (not self.service) or self._is_fetched:
            return
        self._original_track = copy.deepcopy(self)
        service = get_service_by_name(self.service)
        track = service.get(self._url, extra_info=self.extra_info, process=True)[0]
        self.url = track.url
        self.name = track.name
        self._original_track.name = track.name
        self.format = track.format
        self.type = track.type
        self._is_fetched = True

    @property
    def url(self):
            self._fetch_stream_data()
            return self._url

    @url.setter
    def url(self, value):
        self._url = value

    @property
    def name(self):
        if not self._name:
            self._fetch_stream_data()
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    def get_meta(self):
        try:
            return {'name': self.name, 'url': self.url}
        except:
            return {'name': None, 'url': ''}

    def get_raw(self):
        if hasattr(self, '_original_track'):
            return self._original_track
        else:
            return self

    def __bool__(self):
        if self.service or self.url:
            return True
        else:
            return False


"""schoolproj URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from testapp import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', views.home_view),
    path('contact/', views.contact_view),
    path('student_info/', views.student_info_view),
    path('enquiry/', views.enquiry_info_view),
    path('ereport/', views.enquiry_report_view),
    path('smupload/', views.SM_upload_view),
    path('rvupload/', views.RV_upload_view),
    path('rlupload/', views.Rlink_upload_view),
    path('auploadset/', views.SM_upload_formset_view),

    path('smreport/', views.SM_report_view),
    path('asreport/', views.AS_report_query_form_view),
    path('rvreport/', views.RV_report_view),
    path('rlreport/', views.Rlink_report_view),
    path('logout/', views.logout_view),
    path('shome/', views.student_home_view),

    path('shomesm/', views.student_home_study_material),
    path('smaths/', views.student_subject_Maths_view), #study material Maths
    path('sscience/', views.student_subject_Science_view), #study material Science
    path('senglish/', views.student_subject_English_view), #study material English
    path('shindi/', views.student_subject_Hindi_view),  #study material Hindi
    path('stelugu/', views.student_subject_Telugu_view), #study material Telugu

    path('sassign/', views.student_assignments_view),
    path('smathsam/', views.student_assignments_maths_view), #assingment  Maths
    path('senglisham/', views.student_assignments_english_view), #assingment  English
    path('sscienceam/', views.student_assignments_science_view), #assingment  Science
    path('shindiam/', views.student_assignments_hindi_view),  #assingment  Hindi
    path('steluguam/', views.student_assignments_telugu_view), #assingment  Telugu

    path('sassignsub/', views.assignment_submission_view),
    path('smathsasm/', views.assignment_submission_maths_view), #assingment submission Maths
    path('senglishasm/', views.assignment_submission_english_view), #assingment submission English
    path('sscienceasm/', views.assignment_submission_science_view), #assingment submission Science
    path('shindiasm/', views.assignment_submission_hindi_view), #assingment submission Hindi
    path('steluguasm/', views.assignment_submission_telugu_view), #assingment submission Telugu

    path('sasreport/', views.assignment_completed_report_view),

    path('testvp/', views.test_video_play_view),

    path('sonline/', views.student_online_view),
    path('accounts/', include('django.contrib.auth.urls')),

]

if settings.DEBUG:
    urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)