Example #1
0
File: WS.py Project: serereg/nic_cl
    async def run(self):
        self.tasks = [
            asyncio.create_task(self._ensure_web_socket()),
        ]
        await self._ws_connected.wait()
        self.tasks.extend([
            asyncio.create_task(self._receive_commands_from_web_srv_task()),
            asyncio.create_task(self._send_temperature_to_web_srv_task()),
            asyncio.create_task(
                self._send_temperatures_to_telegram()),  # telegram
        ])

        threads = []
        self.read_opc_task_running = True
        # for c_item in self.opc.coolers_arr:
        #     t = Thread(target=self._read_opc_task, args=(c_item,))
        #     threads.append(t)
        #     t.start()

        t = Thread(target=self.read_all_sensors)
        t.start()

        await asyncio.wait(self.tasks)
        for t in self.tasks:
            t.cancel()
Example #2
0
class Mark1DemoSkill(MycroftSkill):
    def __init__(self):
        super(Mark1DemoSkill, self).__init__("Mark1DemoSkill")
        self.animations = []
        self.playing = True
        self.thread = None

    def initialize(self):
        self.emitter.on("mycroft.mark1.demo", self.demo)

    def animate(self, t, often, func, *args):
        t = time.time() + t
        self.animations.append({
            "time": t,
            "often": often,
            "func": func,
            "args": args
        })

    def __get_time(self, often, t):
        return often - t % often

    def run(self):
        while self.playing:
            for animation in self.animations:
                if animation["time"] <= time.time():
                    animation["func"](*animation["args"])
                    if type(animation["often"]) is int:
                        animation["time"] = time.time() + animation["often"]
                    else:
                        often = int(animation["often"])
                        t = animation["time"]
                        animation["time"] = time.time() + self.__get_time(
                            often, t)
            time.sleep(0.1)

    def demo(self, message):
        self.animate(0, 8, self.enclosure.eyes_look, "r")
        self.animate(2, 8, self.enclosure.eyes_look, "l")
        self.animate(4, 8, self.enclosure.eyes_look, "d")
        self.animate(6, 8, self.enclosure.eyes_look, "u")
        self.animate(self.__get_time(120, time.time()), "120",
                     self.emitter.emit, Message("mycroft.sing"))
        self.thread = Thread(None, self.run)
        self.thread.daemon = True
        self.thread.start()

    def stop(self):
        self.playing = False
        if self.thread:
            self.thread.cancel()
        self.enclosure.eyes_reset()
def start_compilation(project_id, verilog_sources, components):
    # only one build per project at a time
    if project_id in running_threads:
        if not running_threads[project_id].is_alive():
            running_threads.pop(project_id)
        else:
            raise CompileError("A build is already running for this project")

    log_queue = Queue()
    log_queue.progress = 1
    cancel_event = Event()
    running_logs[project_id] = log_queue
    t = Thread(target=compile,
               args=(project_id, verilog_sources, components, log_queue,
                     cancel_event),
               daemon=True)
    t.cancel = cancel_event
    running_threads[project_id] = t
    t.start()
Example #4
0
def delayed():
    logging.debug("worker runing")

t1 = threading.Timer(5,delayed)  # 5秒之后 再去执行线程
t1.setName("t1")
t2 = threading.Timer(5,delayed)
t2.setName("t2")

logging.debug("starting timers")
t1.start()
t2.start()

logging.debug("waiting before canceling %s", t2.getName())
time.sleep(2)
logging.debug("canceling %s",t2.getName())
t2.cancel()   # 关闭定时器。
logging.debug("done")

# Timer类 继承于 Thread 类。
# 定时器 线程 在延时期间是可以被关闭的,只需要调用 cancel 方法。
# t2 这个定时器线程,永远不会执行。

11. 限制资源的并发访问--信号量

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种机制。
有时候可能需要允许多个线程同时访问一个资源,但是要限制总数。例如,连接池支持同时连接,但是数目是固定的,或者一个网络应用支持固定数目的并发下载。

一个信号量 管理了一个内部计数器(实际上是一个整数)。调用acquire()方法时 减1 。调用release()方法时,加1 。这个计数器永远不能小于0。
当线程里调用了acquire()发现,内部计数器已经是0了,这个线程会阻塞,直到内部计数大于0。
信号量支持 上下文管理器。
Example #5
0
class LUCKY7( xbmcgui.WindowXML ):
    def __init__( self, *args, **kwargs ):
        xbmcgui.WindowXML.__init__( self, *args, **kwargs )

        self.items_slots  = getFruitsAndNonFruits()
        self.items_slot_1 = sorted( self.items_slots[ 0 ] )
        self.items_slot_2 = Shuffle( sorted( self.items_slots[ 1 ] ) )
        self.items_slot_3 = sorted( self.items_slots[ 2 ], reverse=True )
        self.range_items_slots = range( 21 )

        self.all_slots_stopped = False
        self.slot1_stopped     = False
        self.slot2_stopped     = False
        self.slot3_stopped     = False
        self.is_rolling        = False

        self.game_is_ok = False

    def play_SFX( self, SFX ):
        if not xbmc.getCondVisibility( "Skin.HasSetting(Lucky7_SFX_Muted)" ):
            xbmc.playSFX( SFX )

    def onInit( self ):
        try: 
            if not self.game_is_ok:
                self.onInitShowSampleSlots()
                self.load_credits()

                self.button_auto_spin = self.getControl( 31 )
                #Enable and reset bet 2x gain radio button
                self.button_2x = self.getControl( 62 )
                self.set_button_2x()

                if self.credits[ "jackpot" ] > 0:
                    self.setProperty( "jackpot", "%i" % self.credits[ "jackpot" ] )

                self.setProperty( "autospin", "" )

                self.game_is_ok = True

            self.fill_credits()
        except:
            print_exc()

    def onInitShowSampleSlots( self ):
        try: 
            s1, s2, s3 = random.sample( self.items_slot_1, 3 )
            self.setProperty( "slot1_top", s1 )
            self.setProperty( "slot1_middle", s2 )
            self.setProperty( "slot1_bottom", s3 )

            s1, s2, s3 = random.sample( self.items_slot_2, 3 )
            self.setProperty( "slot2_top", s1 )
            self.setProperty( "slot2_middle", s2 )
            self.setProperty( "slot2_bottom", s3 )

            s1, s2, s3 = random.sample( self.items_slot_3, 3 )
            self.setProperty( "slot3_top", s1 )
            self.setProperty( "slot3_middle", s2 )
            self.setProperty( "slot3_bottom", s3 )
        except:
            print_exc()

    def set_button_2x( self, statut=0 ):
        self.button_2x.setSelected( 0 )
        self.button_2x.setEnabled( statut )
        self.button_2x.setVisible( statut )

    def fill_credits( self ):
        try: 
            xbmcgui.lock()
            last_betting = 0
            if self.cash:
                try: last_betting = self.getCurrentListPosition()
                except: pass
                zero_cash = self.cash
                self.clearList()

                bronze = range( 1, 100 )
                for mise in bronze:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money3.png", thumbnailImage="money3.png" )
                        self.addItem( listitem )

                silver = range( 100, 1000, 25 )
                for mise in silver:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money2.png", thumbnailImage="money2.png" )
                        self.addItem( listitem )

                gold = range( 1000, 11000, 1000 )
                if not self.cash in gold + silver + bronze:
                    gold += [ self.cash ]
                for mise in gold:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money1.png", thumbnailImage="money1.png" )
                        self.addItem( listitem )

                if last_betting > self.getListSize()-1:
                    last_betting = self.getListSize()-1
                self.setCurrentListPosition( last_betting )

        except:
            print_exc()
        xbmcgui.unlock()

        self.check_cash()

    def check_cash( self ):
        if not self.cash:
            self.cash = 0
            self.betting = 0
            self.last_win = 0
            self.set_button_2x()
            if xbmcgui.Dialog().yesno(  _( 0 ), _( 11 ) % _( 1 ), _( 12 ) ):
                self.cash = 5000
                self.fill_credits()
            else:
                self.clearList()

    def onFocus( self, controlID ):
        pass

    def onClick( self, controlID ):
        try:
            if controlID == 20:
                self.stop_slots( 1 )

            elif controlID == 21:
                self.stop_slots( 2 )

            elif controlID == 22:
                self.stop_slots( 3 )

            elif controlID == 23:
                self.stop_slots( 4 )

            elif controlID in ( 24, 25 ):
                self._start_thread()
                self.check_cash()

            elif controlID == 31:
                if self.button_auto_spin.isSelected():
                    self.setProperty( "autospin", "true" )
                else:
                    self.setProperty( "autospin", "" )

            elif controlID == 30:
                self._show_infos()

            elif controlID == 300:
                self._close_game()
        except:
            print_exc()

    def onAction( self, action ):
        if self.cash and xbmc.getCondVisibility( "Container.OnNext | Container.OnPrevious" ):
            self.play_SFX( PLAY_COIN_SFX )

        try: self.getListItem( self.getCurrentListPosition() ).getLabel()
        except: 
            try: self.setCurrentListPosition( self.getListSize()-1 )
            except: print_exc()

        try:
            if not self.is_rolling and KEYMAP[ "close_game" ][ action ]:
                self._close_game()

            if self.is_rolling:
                if KEYMAP[ "action_stop_slot_1" ][ action ]:
                    self.stop_slots( 1 )

                elif KEYMAP[ "action_stop_slot_2" ][ action ]:
                    self.stop_slots( 2 )

                elif KEYMAP[ "action_stop_slot_3" ][ action ]:
                    self.stop_slots( 3 )

                elif KEYMAP[ "action_stop_slots" ][ action ]:
                    self.stop_slots( 4 )

            if KEYMAP[ "action_start_spin" ][ action ]:
                self._start_thread()

            elif KEYMAP[ "action_bet_max" ][ action ]:
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( self.getListSize()-1 )

            elif KEYMAP[ "action_bet_up" ][ action ]:
                listsize = self.getListSize()
                pos = self.getCurrentListPosition() + 1
                if pos >= listsize: pos = listsize - 1
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( pos )

            elif KEYMAP[ "action_bet_down" ][ action ]:
                pos = self.getCurrentListPosition() - 1
                if pos <= 0: pos = 0
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( pos )

            elif KEYMAP[ "action_bet_2x_gain" ][ action ]:
                if xbmc.getCondVisibility( "Control.IsVisible(62)" ):
                    if self.button_2x.isSelected():
                        self.button_2x.setSelected( 0 )
                    else:
                        self.button_2x.setSelected( 1 )

            elif KEYMAP[ "action_auto_spin" ][ action ]:
                if self.button_auto_spin.isSelected():
                    self.button_auto_spin.setSelected( 0 )
                    self.setProperty( "autospin", "" )
                else:
                    self.setProperty( "autospin", "true" )
                    self.button_auto_spin.setSelected( 1 )

            elif KEYMAP[ "show_dialog_infos" ][ action ]:
                self._show_infos()

        except:
            print_exc()

    def _start_thread( self ):
        if not self.button_auto_spin.isSelected():
            self._stop_sub_thread()
        if not self.is_rolling and self.cash:
            self.setProperty( "active_spinner", "true" )
            self.play_SFX( PLAY_SPINNER_SFX )
            if self.last_win and self.button_2x.isSelected():
                self.betting = self.last_win * 2
            else:
                self.betting = self.getListItem( self.getCurrentListPosition() ).getLabel().strip( "$" )
                self.set_button_2x()
            self._stop_thread()
            self.is_rolling = True
            self._thread = Thread( target=self.start_spin )
            self._thread.start()
        if self.button_auto_spin.isSelected():
            self._stop_sub_thread()
            self._sub_thread = Timer( 3, self._start_thread, () )
            self._sub_thread.start()

    def _stop_thread( self ):
        try: self._thread.cancel()
        except: pass

    def _stop_sub_thread( self ):
        try: self._sub_thread.cancel()
        except: pass

    def stop_slots( self, slot=0 ):
        if slot:
            if slot == 1:
                self.slot1_stopped = True
            elif slot == 2:
                self.slot2_stopped = True
            elif slot == 3:
                self.slot3_stopped = True
            else:
                self.all_slots_stopped = True
                self._stop_thread()
            self.play_SFX( PLAY_STOP_SFX )

    def start_spin( self ):
        self.setProperty( "lose", "" )
        self.setProperty( "winning", "" )
        self.setProperty( "pot_win", "" )
        self.setProperty( "all_fruits", "" )
        self.setProperty( "slot1_win", "" )
        self.setProperty( "slot2_win", "" )
        self.setProperty( "slot3_win", "" )

        xbmc.sleep( 1200 )
        self.setProperty( "active_spinner", "" )
        #self.clearProperties()

        self.items_slot_1 = Shuffle( self.items_slot_1 )
        self.items_slot_2 = Shuffle( self.items_slot_2 )
        self.items_slot_3 = Shuffle( self.items_slot_3 )

        self.all_slots_stopped = False
        self.slot1_stopped = False
        self.slot2_stopped = False
        self.slot3_stopped = False

        for time_sleep in range( 1, 4 ):
            if self.all_slots_stopped: break
            self.play_SFX( PLAY_SPIN_SFX )
            time_sleep *= 40
            try:
                for item in self.range_items_slots:
                    if self.all_slots_stopped: break
                    xbmc.sleep( time_sleep )

                    if not self.slot1_stopped:
                        try: slot1_top    = self.items_slot_1[ item + 1 ]
                        except: slot1_top = self.items_slot_1[ 0 ]
                        slot1_middle      = self.items_slot_1[ item ]
                        slot1_bottom      = self.items_slot_1[ item - 1 ]
                        self.setProperty( "slot1_top", slot1_top )
                        self.setProperty( "slot1_middle", slot1_middle )
                        self.setProperty( "slot1_bottom", slot1_bottom )

                    if not self.slot2_stopped:
                        try: slot2_top    = self.items_slot_2[ item + 1 ]
                        except: slot2_top = self.items_slot_2[ 0 ]
                        slot2_middle      = self.items_slot_2[ item ]
                        slot2_bottom      = self.items_slot_2[ item - 1 ]
                        self.setProperty( "slot2_top", slot2_top )
                        self.setProperty( "slot2_middle", slot2_middle )
                        self.setProperty( "slot2_bottom", slot2_bottom )

                    if not self.slot3_stopped:
                        try: slot3_top    = self.items_slot_3[ item + 1 ]
                        except: slot3_top = self.items_slot_3[ 0 ]
                        slot3_middle      = self.items_slot_3[ item ]
                        slot3_bottom      = self.items_slot_3[ item - 1 ]
                        self.setProperty( "slot3_top", slot3_top )
                        self.setProperty( "slot3_middle", slot3_middle )
                        self.setProperty( "slot3_bottom", slot3_bottom )

                    # slots 1, 2 and 3 stopped
                    if self.slot1_stopped and self.slot2_stopped and self.slot3_stopped:
                        self.all_slots_stopped = True
                        break

                    # for debug only if 3 slots is same
                    #if slot1_middle == slot2_middle == slot3_middle:
                    #    self.all_slots_stopped = True
                    #    break

                if not self.all_slots_stopped:
                    if not self.slot1_stopped:
                        self.items_slot_1 = Shuffle( self.items_slot_1 )
                    if not self.slot2_stopped:
                        self.items_slot_2 = Shuffle( self.items_slot_2 )
                    if not self.slot3_stopped:
                        self.items_slot_3 = Shuffle( self.items_slot_3 )
            except:
                print_exc()

        self.set_gain( Gain( slot1_middle, slot2_middle, slot3_middle,
                slot1_top, slot2_top, slot3_top, slot1_bottom, slot2_bottom, slot3_bottom, gui=self ) )

        try:
            if slot1_middle == slot2_middle == slot3_middle:
                if slot1_middle == SEVEN:
                    self.play_SFX( PLAY_7_SFX )
                    xbmc.sleep( 2000 )
                elif slot1_middle == BELL:
                    self.play_SFX( PLAY_BELL_SFX )
                    xbmc.sleep( 4000 )
        except:
            print_exc()

        #xbmc.sleep( 100 )
        self.betting = 0
        self.fill_credits()
        self.is_rolling = False
        self._stop_thread()

    def set_gain( self, slots_infos ):
        #set credits display
        try:
            cash_win = 0
            _jackpot = 0
            if not self.button_2x.isSelected():
                self.cash -= slots_infos.betting
            if slots_infos.win:

                if slots_infos.all_fruits and not slots_infos.gain:
                    self.play_SFX( PLAY_7_SFX )
                    xbmc.sleep( 2000 )

                if slots_infos.all_fruits:
                    self.setProperty( "all_fruits", _( 405 ) )

                if slots_infos.gain:
                    cash_win += slots_infos.gain
                    self.setProperty( "winning", str( cash_win ) )

                if slots_infos.win_jackpot:
                    _jackpot = self.credits[ "jackpot" ]
                    self.setProperty( "jackpot", "" )
                    self.setProperty( "pot_win", str( self.credits[ "jackpot" ] ) )
                    cash_win += self.credits[ "jackpot" ]
                    self.credits[ "jackpot" ] = 0
                self.cash += cash_win
                self.last_win = cash_win

                if slots_infos.win_slots[ 0 ]:
                    self.setProperty( "slot1_win", "true" )
                if slots_infos.win_slots[ 1 ]:
                    self.setProperty( "slot2_win", "true" )
                if slots_infos.win_slots[ 2 ]:
                    self.setProperty( "slot3_win", "true" )

                #Enable and reset bet 2x gain radio button
                self.set_button_2x( 1 )
            else:
                self.last_win = 0
                if self.button_2x.isSelected():
                    slots_infos.betting /= 2
                    self.cash -= slots_infos.betting
                self.credits[ "jackpot" ] += slots_infos.betting
                self.setProperty( "lose", str( slots_infos.betting ) )
                self.setProperty( "jackpot", str( self.credits[ "jackpot" ] ) )

                #Enable and reset bet 2x gain radio button
                self.set_button_2x()

            if slots_infos.win_jackpot:
                #xbmc.executebuiltin( "XBMC.Action(Screenshot)" )
                OK, date_time = self.screenshot()
                if OK: self.dump_winner_jackpot( slots_infos.betting, cash_win, _jackpot, date_time )
            #OK, date_time = self.screenshot()
            #if OK: self.dump_winner_jackpot( slots_infos.betting, cash_win, _jackpot, date_time )
        except:
            print_exc()

    def load_credits( self ):
        test = {}
        self.credits = {}
        defaults = { "jackpot": 0, "last_cash": 0 }
        if os.path.exists( CREDITS_FILE ):
            try:
                f = open( CREDITS_FILE, "rb" )
                test = load( f )
                f.close()
            except:
                print_exc()
                test = {}

        for key, value in defaults.items():
            # add default values for missing settings
            self.credits[ key ] = test.get( key, defaults[ key ] )
        self.save_credits()

        self.cash = 10000
        #demande pour continuer ancienne partie
        if ( self.credits[ "last_cash" ] > 0 ) and xbmcgui.Dialog().yesno(  _( 0 ), _( 5 ) % ( _( 1 ), self.credits[ "last_cash" ] ), _( 6 ), _( 7 ), _( 8 ), _( 9 ) ):
            self.cash = self.credits[ "last_cash" ]
        self.credits[ "last_cash" ] = 0
        self.last_win = 0
        self.betting = 0

    def save_credits( self ):
        try:
            f = open( CREDITS_FILE, "wb" )
            dump( self.credits, f )
            f.close()
        except:
            print_exc()

    def dump_winner_jackpot( self, bet, cash, jackpot, date_time ):
        winners = []
        name = xbmc.getInfoLabel( "System.ProfileName" )#unicode( , 'utf-8')
        thumb = xbmc.getInfoImage( "System.ProfileThumb" )
        if os.path.isfile( WINNER_JACKPOT ):
            try:
                f = open( WINNER_JACKPOT, "rb" )
                winners = load( f )
                f.close()
            except:
                print_exc()
                winners = []
        try:
            winners.append( [ name, thumb, bet, cash, jackpot, date_time ] )
            f = open( WINNER_JACKPOT, "wb" )
            dump( winners, f )
            f.close()
        except:
            print_exc()
        #print winners

    def screenshot( self ):
        xbmc.sleep( 1000 )
        OK = ""
        name = ""
        try: 
            name = str( time.time() )
            # original size
            #filename = name + "-big.jpg"
            W, H = self.getWidth(), self.getHeight()
            #OK = TakeScreenShot( filename, width=W, height=H )
            # thumbs size
            filename = name + ".jpg"
            W, H = 384, ( ( 384 * H ) / W )
            #W, H = 512, ( ( 512 * H ) / W )
            #W, H = int( ( 256 * W ) / H ), 256
            OK = TakeScreenShot( filename, width=W, height=H )
        except:
            print_exc()
        #print OK
        return ( OK == "OK" ), name

    def _show_infos( self ):
        import dialogInfos
        current_skin, force_fallback = getUserSkin()
        w = dialogInfos.DialogInfos( "lucky-7-DialogInfos.xml", CWD, current_skin, force_fallback, close_game=self._close_game )
        w.doModal()
        del w
        del dialogInfos

    def _close_game( self ):
        self._stop_sub_thread()
        self.all_slots_stopped = True
        #self._stop_thread()
        if self.cash > 10000:
            self.credits[ "last_cash" ] = self.cash
        self.cash = 0
        self.save_credits()
        #xbmc.sleep( 100 )
        self.close()
Example #6
0
class LUCKY7( xbmcgui.WindowXML ):
    def __init__( self, *args, **kwargs ):
        xbmcgui.WindowXML.__init__( self, *args, **kwargs )

        self.items_slots  = getFruitsAndNonFruits()
        self.items_slot_1 = sorted( self.items_slots[ 0 ] )
        self.items_slot_2 = Shuffle( sorted( self.items_slots[ 1 ] ) )
        self.items_slot_3 = sorted( self.items_slots[ 2 ], reverse=True )
        self.range_items_slots = range( 21 )

        self.all_slots_stopped = False
        self.slot1_stopped     = False
        self.slot2_stopped     = False
        self.slot3_stopped     = False
        self.is_rolling        = False

        self.game_is_ok = False

    def play_SFX( self, SFX ):
        if not xbmc.getCondVisibility( "Skin.HasSetting(Lucky7_SFX_Muted)" ):
            xbmc.playSFX( SFX )

    def onInit( self ):
        try: 
            if not self.game_is_ok:
                self.onInitShowSampleSlots()
                self.load_credits()

                self.button_auto_spin = self.getControl( 31 )
                #Enable and reset bet 2x gain radio button
                self.button_2x = self.getControl( 62 )
                self.set_button_2x()

                if self.credits[ "jackpot" ] > 0:
                    self.setProperty( "jackpot", "%i" % self.credits[ "jackpot" ] )

                self.setProperty( "autospin", "" )

                self.game_is_ok = True

            self.fill_credits()
        except:
            print_exc()

    def onInitShowSampleSlots( self ):
        try: 
            s1, s2, s3 = random.sample( self.items_slot_1, 3 )
            self.setProperty( "slot1_top", s1 )
            self.setProperty( "slot1_middle", s2 )
            self.setProperty( "slot1_bottom", s3 )

            s1, s2, s3 = random.sample( self.items_slot_2, 3 )
            self.setProperty( "slot2_top", s1 )
            self.setProperty( "slot2_middle", s2 )
            self.setProperty( "slot2_bottom", s3 )

            s1, s2, s3 = random.sample( self.items_slot_3, 3 )
            self.setProperty( "slot3_top", s1 )
            self.setProperty( "slot3_middle", s2 )
            self.setProperty( "slot3_bottom", s3 )
        except:
            print_exc()

    def set_button_2x( self, statut=0 ):
        self.button_2x.setSelected( 0 )
        self.button_2x.setEnabled( statut )
        self.button_2x.setVisible( statut )

    def fill_credits( self ):
        try: 
            xbmcgui.lock()
            last_betting = 0
            if self.cash:
                try: last_betting = self.getCurrentListPosition()
                except: pass
                zero_cash = self.cash
                self.clearList()

                bronze = range( 1, 100 )
                for mise in bronze:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money3.png", thumbnailImage="money3.png" )
                        self.addItem( listitem )

                silver = range( 100, 1000, 25 )
                for mise in silver:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money2.png", thumbnailImage="money2.png" )
                        self.addItem( listitem )

                gold = range( 1000, 11000, 1000 )
                if not self.cash in gold + silver + bronze:
                    gold += [ self.cash ]
                for mise in gold:
                    zero_cash = self.cash - mise
                    label2 = str( zero_cash )
                    if zero_cash >= 0:
                        listitem = xbmcgui.ListItem( str( mise ), label2, iconImage="money1.png", thumbnailImage="money1.png" )
                        self.addItem( listitem )

                if last_betting > self.getListSize()-1:
                    last_betting = self.getListSize()-1
                self.setCurrentListPosition( last_betting )

        except:
            print_exc()
        xbmcgui.unlock()

        self.check_cash()

    def check_cash( self ):
        if not self.cash:
            self.cash = 0
            self.betting = 0
            self.last_win = 0
            self.set_button_2x()
            if xbmcgui.Dialog().yesno(  _( 0 ), _( 11 ) % _( 1 ), _( 12 ) ):
                self.cash = 5000
                self.fill_credits()
            else:
                self.clearList()

    def onFocus( self, controlID ):
        pass

    def onClick( self, controlID ):
        try:
            if controlID == 20:
                self.stop_slots( 1 )

            elif controlID == 21:
                self.stop_slots( 2 )

            elif controlID == 22:
                self.stop_slots( 3 )

            elif controlID == 23:
                self.stop_slots( 4 )

            elif controlID in ( 24, 25 ):
                self._start_thread()
                self.check_cash()

            elif controlID == 31:
                if self.button_auto_spin.isSelected():
                    self.setProperty( "autospin", "true" )
                else:
                    self.setProperty( "autospin", "" )

            elif controlID == 30:
                self._show_infos()

            elif controlID == 300:
                self._close_game()
        except:
            print_exc()

    def onAction( self, action ):
        if self.cash and xbmc.getCondVisibility( "Container.OnNext | Container.OnPrevious" ):
            self.play_SFX( PLAY_COIN_SFX )

        try: self.getListItem( self.getCurrentListPosition() ).getLabel()
        except: 
            try: self.setCurrentListPosition( self.getListSize()-1 )
            except: print_exc()

        try:
            if not self.is_rolling and KEYMAP[ "close_game" ][ action ]:
                self._close_game()

            if self.is_rolling:
                if KEYMAP[ "action_stop_slot_1" ][ action ]:
                    self.stop_slots( 1 )

                elif KEYMAP[ "action_stop_slot_2" ][ action ]:
                    self.stop_slots( 2 )

                elif KEYMAP[ "action_stop_slot_3" ][ action ]:
                    self.stop_slots( 3 )

                elif KEYMAP[ "action_stop_slots" ][ action ]:
                    self.stop_slots( 4 )

            if KEYMAP[ "action_start_spin" ][ action ]:
                self._start_thread()

            elif KEYMAP[ "action_bet_max" ][ action ]:
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( self.getListSize()-1 )

            elif KEYMAP[ "action_bet_up" ][ action ]:
                listsize = self.getListSize()
                pos = self.getCurrentListPosition() + 1
                if pos >= listsize: pos = listsize - 1
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( pos )

            elif KEYMAP[ "action_bet_down" ][ action ]:
                pos = self.getCurrentListPosition() - 1
                if pos <= 0: pos = 0
                self.play_SFX( PLAY_COIN_SFX )
                self.setCurrentListPosition( pos )

            elif KEYMAP[ "action_bet_2x_gain" ][ action ]:
                if xbmc.getCondVisibility( "Control.IsVisible(62)" ):
                    if self.button_2x.isSelected():
                        self.button_2x.setSelected( 0 )
                    else:
                        self.button_2x.setSelected( 1 )

            elif KEYMAP[ "action_auto_spin" ][ action ]:
                if self.button_auto_spin.isSelected():
                    self.button_auto_spin.setSelected( 0 )
                    self.setProperty( "autospin", "" )
                else:
                    self.setProperty( "autospin", "true" )
                    self.button_auto_spin.setSelected( 1 )

            elif KEYMAP[ "show_dialog_infos" ][ action ]:
                self._show_infos()

        except:
            print_exc()

    def _start_thread( self ):
        if not self.button_auto_spin.isSelected():
            self._stop_sub_thread()
        if not self.is_rolling and self.cash:
            self.setProperty( "active_spinner", "true" )
            self.play_SFX( PLAY_SPINNER_SFX )
            if self.last_win and self.button_2x.isSelected():
                self.betting = self.last_win * 2
            else:
                self.betting = self.getListItem( self.getCurrentListPosition() ).getLabel().strip( "$" )
                self.set_button_2x()
            self._stop_thread()
            self.is_rolling = True
            self._thread = Thread( target=self.start_spin )
            self._thread.start()
        if self.button_auto_spin.isSelected():
            self._stop_sub_thread()
            self._sub_thread = Timer( 3, self._start_thread, () )
            self._sub_thread.start()

    def _stop_thread( self ):
        try: self._thread.cancel()
        except: pass

    def _stop_sub_thread( self ):
        try: self._sub_thread.cancel()
        except: pass

    def stop_slots( self, slot=0 ):
        if slot:
            if slot == 1:
                self.slot1_stopped = True
            elif slot == 2:
                self.slot2_stopped = True
            elif slot == 3:
                self.slot3_stopped = True
            else:
                self.all_slots_stopped = True
                self._stop_thread()
            self.play_SFX( PLAY_STOP_SFX )

    def start_spin( self ):
        self.setProperty( "lose", "" )
        self.setProperty( "winning", "" )
        self.setProperty( "pot_win", "" )
        self.setProperty( "all_fruits", "" )
        self.setProperty( "slot1_win", "" )
        self.setProperty( "slot2_win", "" )
        self.setProperty( "slot3_win", "" )

        xbmc.sleep( 1200 )
        self.setProperty( "active_spinner", "" )
        #self.clearProperties()

        self.items_slot_1 = Shuffle( self.items_slot_1 )
        self.items_slot_2 = Shuffle( self.items_slot_2 )
        self.items_slot_3 = Shuffle( self.items_slot_3 )

        self.all_slots_stopped = False
        self.slot1_stopped = False
        self.slot2_stopped = False
        self.slot3_stopped = False

        for time_sleep in range( 1, 4 ):
            if self.all_slots_stopped: break
            self.play_SFX( PLAY_SPIN_SFX )
            time_sleep *= 40
            try:
                for item in self.range_items_slots:
                    if self.all_slots_stopped: break
                    xbmc.sleep( time_sleep )

                    if not self.slot1_stopped:
                        try: slot1_top    = self.items_slot_1[ item + 1 ]
                        except: slot1_top = self.items_slot_1[ 0 ]
                        slot1_middle      = self.items_slot_1[ item ]
                        slot1_bottom      = self.items_slot_1[ item - 1 ]
                        self.setProperty( "slot1_top", slot1_top )
                        self.setProperty( "slot1_middle", slot1_middle )
                        self.setProperty( "slot1_bottom", slot1_bottom )

                    if not self.slot2_stopped:
                        try: slot2_top    = self.items_slot_2[ item + 1 ]
                        except: slot2_top = self.items_slot_2[ 0 ]
                        slot2_middle      = self.items_slot_2[ item ]
                        slot2_bottom      = self.items_slot_2[ item - 1 ]
                        self.setProperty( "slot2_top", slot2_top )
                        self.setProperty( "slot2_middle", slot2_middle )
                        self.setProperty( "slot2_bottom", slot2_bottom )

                    if not self.slot3_stopped:
                        try: slot3_top    = self.items_slot_3[ item + 1 ]
                        except: slot3_top = self.items_slot_3[ 0 ]
                        slot3_middle      = self.items_slot_3[ item ]
                        slot3_bottom      = self.items_slot_3[ item - 1 ]
                        self.setProperty( "slot3_top", slot3_top )
                        self.setProperty( "slot3_middle", slot3_middle )
                        self.setProperty( "slot3_bottom", slot3_bottom )

                    # slots 1, 2 and 3 stopped
                    if self.slot1_stopped and self.slot2_stopped and self.slot3_stopped:
                        self.all_slots_stopped = True
                        break

                    # for debug only if 3 slots is same
                    #if slot1_middle == slot2_middle == slot3_middle:
                    #    self.all_slots_stopped = True
                    #    break

                if not self.all_slots_stopped:
                    if not self.slot1_stopped:
                        self.items_slot_1 = Shuffle( self.items_slot_1 )
                    if not self.slot2_stopped:
                        self.items_slot_2 = Shuffle( self.items_slot_2 )
                    if not self.slot3_stopped:
                        self.items_slot_3 = Shuffle( self.items_slot_3 )
            except:
                print_exc()

        self.set_gain( Gain( slot1_middle, slot2_middle, slot3_middle,
                slot1_top, slot2_top, slot3_top, slot1_bottom, slot2_bottom, slot3_bottom, gui=self ) )

        try:
            if slot1_middle == slot2_middle == slot3_middle:
                if slot1_middle == SEVEN:
                    self.play_SFX( PLAY_7_SFX )
                    xbmc.sleep( 2000 )
                elif slot1_middle == BELL:
                    self.play_SFX( PLAY_BELL_SFX )
                    xbmc.sleep( 4000 )
        except:
            print_exc()

        #xbmc.sleep( 100 )
        self.betting = 0
        self.fill_credits()
        self.is_rolling = False
        self._stop_thread()

    def set_gain( self, slots_infos ):
        #set credits display
        try:
            cash_win = 0
            _jackpot = 0
            if not self.button_2x.isSelected():
                self.cash -= slots_infos.betting
            if slots_infos.win:

                if slots_infos.all_fruits and not slots_infos.gain:
                    self.play_SFX( PLAY_7_SFX )
                    xbmc.sleep( 2000 )

                if slots_infos.all_fruits:
                    self.setProperty( "all_fruits", _( 405 ) )

                if slots_infos.gain:
                    cash_win += slots_infos.gain
                    self.setProperty( "winning", str( cash_win ) )

                if slots_infos.win_jackpot:
                    _jackpot = self.credits[ "jackpot" ]
                    self.setProperty( "jackpot", "" )
                    self.setProperty( "pot_win", str( self.credits[ "jackpot" ] ) )
                    cash_win += self.credits[ "jackpot" ]
                    self.credits[ "jackpot" ] = 0
                self.cash += cash_win
                self.last_win = cash_win

                if slots_infos.win_slots[ 0 ]:
                    self.setProperty( "slot1_win", "true" )
                if slots_infos.win_slots[ 1 ]:
                    self.setProperty( "slot2_win", "true" )
                if slots_infos.win_slots[ 2 ]:
                    self.setProperty( "slot3_win", "true" )

                #Enable and reset bet 2x gain radio button
                self.set_button_2x( 1 )
            else:
                self.last_win = 0
                if self.button_2x.isSelected():
                    slots_infos.betting /= 2
                    self.cash -= slots_infos.betting
                self.credits[ "jackpot" ] += slots_infos.betting
                self.setProperty( "lose", str( slots_infos.betting ) )
                self.setProperty( "jackpot", str( self.credits[ "jackpot" ] ) )

                #Enable and reset bet 2x gain radio button
                self.set_button_2x()

            if slots_infos.win_jackpot:
                #xbmc.executebuiltin( "XBMC.Action(Screenshot)" )
                OK, date_time = self.screenshot()
                if OK: self.dump_winner_jackpot( slots_infos.betting, cash_win, _jackpot, date_time )
            #OK, date_time = self.screenshot()
            #if OK: self.dump_winner_jackpot( slots_infos.betting, cash_win, _jackpot, date_time )
        except:
            print_exc()

    def load_credits( self ):
        test = {}
        self.credits = {}
        defaults = { "jackpot": 0, "last_cash": 0 }
        if os.path.exists( CREDITS_FILE ):
            try:
                f = open( CREDITS_FILE, "rb" )
                test = load( f )
                f.close()
            except:
                print_exc()
                test = {}

        for key, value in defaults.items():
            # add default values for missing settings
            self.credits[ key ] = test.get( key, defaults[ key ] )
        self.save_credits()

        self.cash = 10000
        #demande pour continuer ancienne partie
        if ( self.credits[ "last_cash" ] > 0 ) and xbmcgui.Dialog().yesno(  _( 0 ), _( 5 ) % ( _( 1 ), self.credits[ "last_cash" ] ), _( 6 ), _( 7 ), _( 8 ), _( 9 ) ):
            self.cash = self.credits[ "last_cash" ]
        self.credits[ "last_cash" ] = 0
        self.last_win = 0
        self.betting = 0

    def save_credits( self ):
        try:
            f = open( CREDITS_FILE, "wb" )
            dump( self.credits, f )
            f.close()
        except:
            print_exc()

    def dump_winner_jackpot( self, bet, cash, jackpot, date_time ):
        winners = []
        name = xbmc.getInfoLabel( "System.ProfileName" )#unicode( , 'utf-8')
        thumb = xbmc.getInfoImage( "System.ProfileThumb" )
        if os.path.isfile( WINNER_JACKPOT ):
            try:
                f = open( WINNER_JACKPOT, "rb" )
                winners = load( f )
                f.close()
            except:
                print_exc()
                winners = []
        try:
            winners.append( [ name, thumb, bet, cash, jackpot, date_time ] )
            f = open( WINNER_JACKPOT, "wb" )
            dump( winners, f )
            f.close()
        except:
            print_exc()
        #print winners

    def screenshot( self ):
        xbmc.sleep( 1000 )
        OK = ""
        name = ""
        try: 
            name = str( time.time() )
            # original size
            #filename = name + "-big.jpg"
            W, H = self.getWidth(), self.getHeight()
            #OK = TakeScreenShot( filename, width=W, height=H )
            # thumbs size
            filename = name + ".jpg"
            W, H = 384, ( ( 384 * H ) / W )
            #W, H = 512, ( ( 512 * H ) / W )
            #W, H = int( ( 256 * W ) / H ), 256
            OK = TakeScreenShot( filename, width=W, height=H )
        except:
            print_exc()
        #print OK
        return ( OK == "OK" ), name

    def _show_infos( self ):
        import dialogInfos
        current_skin, force_fallback = getUserSkin()
        try: w = dialogInfos.DialogInfos( "lucky-7-DialogInfos.xml", CWD, current_skin, "PAL", close_game=self._close_game )
        except: w = dialogInfos.DialogInfos( "lucky-7-DialogInfos.xml", CWD, current_skin, force_fallback, close_game=self._close_game )
        w.doModal()
        del w
        del dialogInfos

    def _close_game( self ):
        self._stop_sub_thread()
        self.all_slots_stopped = True
        #self._stop_thread()
        if self.cash > 10000:
            self.credits[ "last_cash" ] = self.cash
        self.cash = 0
        self.save_credits()
        #xbmc.sleep( 100 )
        self.close()
Example #7
0
class OBCI_board_simulator():
    def __init__(self,
                 filepath,
                 FS=250.0,
                 factorOriginalSpeed=1,
                 skipSeconds=0,
                 daisy=False):
        # QtCore.QThread.__init__(self)
        self.simulationCSVFilepath = filepath
        self.simulationFactorOriginalSpeed = factorOriginalSpeed
        self.simulateFromCSVskipSeconds = skipSeconds
        self.fs = FS
        self.daisy = daisy
        self.streaming = False
        self.read_csv_state_ready = False
        self.start_time = -100000
        self.lastSampleTime = -1
        self.sampleSupposedDelay = (
            1.0 / self.fs) / self.simulationFactorOriginalSpeed
        self.state_read_trough = False
        self.sample = OpenBCISample(0, (), ())
        self.thread = None

    def getSkipedSeconds(self):
        return self.simulateFromCSVskipSeconds

    def getSkipedLines(self):
        return self.nSkipDataLines

    def read_csv_data_init(self):
        self.nSkipDataLines = int(self.simulateFromCSVskipSeconds * self.fs)

        self.read_csv_state_ready = False
        self.simulationCSVFile = open(self.simulationCSVFilepath,
                                      'rb',
                                      buffering=20000000)  # opens the csv file
        # try:
        #self.inputiSample = 0
        self.reader = csv.reader(self.simulationCSVFile,
                                 delimiter=';')  # creates the reader object
        for row in self.reader:  # iterates the rows of the file in orders
            # print(row)  # prints each row
            if self.reader.line_num == 1:
                # index;time_sec;ringpar;ch1;ch2;ch3;ch4;ch5;ch6;ch7;ch8
                continue  # skip the first header line
            if self.reader.line_num <= self.nSkipDataLines + 1:
                continue
            else:
                break
        self.read_csv_state_ready = True
        # except:
        # f.close()  # closing
        return self.read_csv_state_ready

    def readSamples(self):
        if not self.state_read_trough:
            self.next_call_time = timeit.default_timer()
            try:
                while True:
                    if self.reading:
                        row = next(self.reader)
                        self.sample = namedtuple("Sample",
                                                 "id channel_data time")
                        self.sample.time = timeit.default_timer()

                        self.sample.id = int(row[2])
                        if self.daisy and len(row) < 19:
                            print "you chose a 16 channel setup, but the file " + self.simulationCSVFilepath + " probably only a 8 channel recording or not the right file. Choose another 8 channel setup, or another 16 channel recording."
                            sys.exit(0)
                        if self.daisy:
                            self.sample.channel_data = [
                                float(row[3]),
                                float(row[4]),
                                float(row[5]),
                                float(row[6]),
                                float(row[7]),
                                float(row[8]),
                                float(row[9]),
                                float(row[10]),
                                float(row[11]),
                                float(row[12]),
                                float(row[13]),
                                float(row[14]),
                                float(row[15]),
                                float(row[16]),
                                float(row[17]),
                                float(row[18])
                            ]
                            if len(row) == 22:
                                self.sample.aux_data = [
                                    float(row[19]),
                                    float(row[20]),
                                    float(row[21])
                                ]
                            else:
                                self.sample.aux_data = [0.0, 0.0, 0.0]
                        else:
                            self.sample.channel_data = [
                                float(row[3]),
                                float(row[4]),
                                float(row[5]),
                                float(row[6]),
                                float(row[7]),
                                float(row[8]),
                                float(row[9]),
                                float(row[10])
                            ]
                            if len(self.sample.channel_data) == 14:
                                self.sample.aux_data = [
                                    float(row[11]),
                                    float(row[12]),
                                    float(row[13])
                                ]
                            else:
                                self.sample.aux_data = [0.0, 0.0, 0.0]

                    self.lastSampleTime = self.sample.time
                    for call in self.callback:
                        call(self.sample)

                    self.next_call_time = self.next_call_time + self.sampleSupposedDelay

                    #print "sleep delay: " + str(intendedSleep) + " next_call_time : " + str(self.next_call_time) + " sampleSupposedDelay: " + str(self.sampleSupposedDelay)

                    while self.next_call_time <= timeit.default_timer():
                        self.next_call_time = timeit.default_timer(
                        ) + self.sampleSupposedDelay
                        #intendedSleep = self.next_call_time - timeit.default_timer()
                        self.reading = False

                    self.reading = True

                    # print "sleep delay: " + str(self.next_call_time - timeit.default_timer())
                    intendedSleep = self.next_call_time - timeit.default_timer(
                    )
                    time.sleep(max(intendedSleep, 0))

            except StopIteration:
                self.state_read_trough = True

    def start_streaming(self, callback, lapse=-1):

        if not self.streaming:
            self.streaming = True

        self.start_time = timeit.default_timer()

        # Enclose callback funtion in a list if it comes alone
        if not isinstance(callback, list):
            callback = [callback]
        self.callback = callback

        if not self.read_csv_state_ready:
            self.read_csv_data_init()

        self.state_read_trough = False

        self.reading = True

        self.thread = Thread(target=self.readSamples)
        self.thread.daemon = True
        self.thread.start()

        # self.thread = Timer(self.sampleSupposedDelay, self.readNextSample)
        # self.thread.start()

    def run(self):
        # Initialize
        self.read_csv_data_init()

    # def init(self):
    #     # Initialize
    #     self.read_csv_data_init()

    def cancel(self):
        self.simulationCSVFile.close()  # closing
        self.thread.cancel()
Example #8
0
class PyWeather(object):
    def __init__(self):

        try:
            cf = open('config.json', 'r')
            configstr = cf.read()
            cf.close()
            config = json.loads(configstr)
            self.config = config
            daynum = str(datetime.datetime.now().day)
            logging.basicConfig(filename=config['logFilePath'] + 'pyWeather' +
                                daynum + '.log',
                                level=logging.INFO)

        except KeyboardInterrupt:
            print('^C received')
            ws.stop()
            time.sleep(5)

        except Exception as e:
            ws.stop()
            Logger.error(e)
            time.sleep(5)

    def start(self):
        Logger.info('starting')

        self.vpstation = VPStation(self.config)

        self.vpThrd = Thread(target=self.vpstation.start, args=())
        self.vpThrd.start()

        self.isServing = True
        self.startWebServer()

    def stop(self):
        self.vpstation.stop()
        time.sleep(5)
        self.vpThrd.cancel()
        self.isServing = False

    def startWebServer(self):
        port = self.config['webPort']
        self.server = HTTPServer(('', port),
                                 PyWeather.makeHandlerClass(self.vpstation))

        print('server port ' + str(port))
        while self.isServing:
            self.server.handle_request()

    def makeHandlerClass(vpstation):
        class RequestHandler(BaseHTTPRequestHandler, object):
            def __init__(self, *args, **kwargs):
                self.vpstation = vpstation
                super(RequestHandler, self).__init__(*args, **kwargs)

            def do_HEAD(self, contentType):
                self.send_response(200)
                self.send_header('Content-type', contentType)
                self.end_headers()

            def do_GET(self):
                global vpstation
                req = self.path[1:]
                if req == 'current':
                    self.do_HEAD('application/json')
                    self.wfile.write(
                        bytes(self.vpstation.current.toJSON(), 'utf-8'))
                elif req == 'hilows':
                    self.do_HEAD('application/json')
                    self.wfile.write(json.dumps(self.vpstation.hilows))
                elif req == 'alerts':
                    self.do_HEAD('application/json')
                    self.wfile.write(json.dumps(self.vpstation.alerts))
                else:
                    self.do_HEAD('text/html')
                    self.send_response(404)

            def do_POST(self):
                cmd = self.path[1:]
                content_length = int(self.headers['Content-Length'])
                post_data = self.rfile.read(content_length)
                self.do_HEAD('application/json')
#self.wfile.write(json.dumps(retval))

        return RequestHandler
Example #9
0
from threading import Thread, current_thread


def fn(tname, count):
    th = current_thread()
    for i in range(count):
        if hasattr(th, "cancel") and getattr(th, "cancel") == True:
            break
        print("In {} counting {}".format(tname, i))
        sleep(0.5)


t1 = Thread(target=fn, args=("foo", 10))
t2 = Thread(target=fn, args=("bar", 15))

t1.start()
t2.start()

fn("main", 5)
t1.cancel = True
t1.join()
print("Main: t1 completed...")

sleep(2)
t2.cancel = True
t2.join()
print("Main: t2 completed...")

print("Main complete...")
Example #10
0
class LoggerPlugin:
    """
    Args:
        logger (RTLogger): The parent RTLogger-instance
    """
    def __init__(self, logger=None, *args, **kwargs):
        # Plugin setup
        # self.setDeviceName()
        self._devicename = "noDevice"
        self.rtoc = rtoc
        if logger is not None:
            self.logger = logger
            self._cb = logger.database.addDataCallback
            self._ev = logger.database.addNewEvent
            self._plt = logger.database.plot
            self._bot = logger.telegramBot
        else:
            self._logger = None
            self._cb = None
            self._ev = None
            self._plt = None
            self._bot = None
        self.widget = None
        self._pluginThread = None
        self._oldPerpetualTimer = False
        self.lockPerpetialTimer = Lock()
        self._log = deque([], 100)
        # -------------
        self.run = False  # False -> stops thread
        """ Use this parameter to start/stop threads. This makes sure, RTOC can close your plugin correctly."""
        self.smallGUI = False
        """ If this is True, the plugin-GUI will be shown in a dropdown menu (GUI related)"""
        self.widget = None
        """ Replace this with your QWidget to enable the plugin-GUI"""
        self._samplerate = 1

    def getDir(self, dir=None):
        """
        Returns:
            Path of your plugin
        """
        if dir is None:
            dir = __file__
        if getattr(sys, 'frozen', False):
            # frozen
            packagedir = os.path.dirname(sys.executable)+'/RTOC/plugins'
        else:
            # unfrozen
            packagedir = os.path.dirname(os.path.realpath(dir))

        return packagedir

    def updateInfo(self):
        self.logger.analysePlugins()

    def stream(self, y=[], snames=[], dname=None, unit=None, x=None, slist=None, sdict=None):
        """
        Use this function to send new measurements to RTOC. You can send multiple signals at once.

        This function is a wrapper for :py:meth:`.RT_data.addData`


        You can choose one of three ways to send measurements.

        **dict**

        Args:
            sdict (dict): A dict containing keys like this: `{'Temperature':[28,'°C'], 'Voltage':[12,'V']}`
            dname (str): The devicename of this signal, e.g: `'Freezer'`

        **list**

        Args:
            slist (list): A list containing these lists: `[y, dname, unit]`. E.g: `[[28,'Temperature','°C'],[12,'Voltage','V']]`
            dname (str): The devicename of this signal, e.g: `'Freezer'`

        **seperate**

        Args:
            y (list): A list containing all measured values, e.g: `[28, 12]`
            snames (list): A list containing all signalnames, e.g: `['Temperature','Voltage']`
            dname (str): The devicename of this signal, e.g: `'Freezer'`
            unit [optional] (list): A list containing all units, e.g: `['°C', 'V']`
            x [optional] (list): A list containing all x-data. In a normal dataseries x is always set to time.time().

        Returns:
            bool: True, if data was sent successfully, False, if not.

        """

        if self._cb:
            now = time.time()
            if dname is None:
                dname = self._devicename
            if slist is None and sdict is None:
                if type(y) == int or type(y) == float:
                    y = [y]
                if type(x) != list:
                    x = [now]*len(y)
                if len(y) != len(x):
                    x = [now]*len(y)

                self._cb(y=y, snames=snames, dname=dname, unit=unit, x=x)
                return True
            elif slist is not None:
                y = []
                x = []
                unit = []
                snames = []
                for sig in slist:
                    if type(sig) == list:
                        if len(sig) == 3:
                            y.append(sig[0])
                            snames.append(sig[1])
                            unit.append(sig[2])
                            x.append(now)
                self._cb(y=y, snames=snames, dname=dname, unit=unit, x=x)
                return True
            elif sdict is not None:
                for dev in sdict.keys():
                    dname = dev
                    y = []
                    x = []
                    unit = []
                    snames = []
                    if type(sdict[dev]) == dict:
                        for sig in sdict[dev].keys():
                            if type(sdict[dev][sig]) == list:
                                if len(sdict[dev][sig]) == 2:
                                    y.append(sdict[dev][sig][0])
                                    snames.append(sig)
                                    unit.append(sdict[dev][sig][1])
                                    x.append(now)
                                else:
                                    logging.error('STREAM ERROR, signal {}.{} has not this format: [y, "unit"]'.format(dname, sig))
                            else:
                                logging.error('STREAM_ERROR:signal {}.{} was malformed.'.format(dname, sig))
                        self._cb(y=y, snames=snames, dname=dname, unit=unit, x=x)
                    else:
                        logging.error('STREAM_ERROR: device {} was malformed.'.format(dname))
                return True
            else:
                logging.error('STREAM_ERROR: The data you provided with in your plugin was wrong."')
        else:
            logging.error('STREAM_ERROR: cannot stream signals. No callback connected')
        return False

    def plot(self, x=[], y=[], sname='noName', dname=None, unit='', hold='off', autoResize=False):
        """
        Use this function to send a signal to RTOC. You can send multiple x-y-pairs for one signal.
        You can either replace the data, which is currently stored in RTOC, if the parameter `hold` is `off` (default).

        Or you can append the data to the existing data with `hold ='on'`.

        `hold='mergeX'` will only add xy-pairs, if the x-value is not in the existing data.

        `hold='mergeY'` will only add xy-pairs, if the y-value is not in the existing data.


        This function is a wrapper for :py:meth:`.RT_data.plot`

        Args:
            x (list): A list containing all x values, e.g: `[1, 2, 3, 4, 5, 6, 7, 8]`
            y (list): A list containing all y values, e.g: `[28,26,25,24,23,22,22,21]`
            sname (str): The devicename of this signal, e.g: `'Temperature'`
            dname (str): The devicename of this signal, e.g: `'Freezer'`
            unit (str): The signal unit, e.g: `'°C'`
            hold ('off','on','mergeX' or 'mergeY'): Defines, how RTOC handles the data. (Default: 'off')
            autoResize (bool): Tell RTOC, to resize the recordLength, if data is too long. (Default: False)

        Returns:
            bool: True, if data was sent successfully, False, if not.

        """
        if y == []:
            y = x
            x = list(range(len(x)))
        if dname is None:
            dname = self._devicename
        if self._plt:
            self._plt(x, y, sname, dname, unit, hold=hold, autoResize=autoResize)
            return True
        else:
            logging.warning("No event connected")
            return False

    def event(self, text='', sname=None, dname=None, priority=0, id=None, value=None, x=None):
        """
        Use this function to send an event to RTOC.

        This function is a wrapper for :py:meth:`.RT_data.addNewEvent`

        Args:
            text (str): A description of this event, e.g: `'Freezer door opened'`
            sname (str): The devicename of this event, e.g: `'Temperature'`
            dname (str): The devicename of this event, e.g: `'Freezer'`
            priority (int): 0: Information, 1: Warning, 2: Error
            id (str): Apply an id to this event. This id is used to trigger **Actions**
            value (any): Unused
            x (float): Set a custom timestamp (Default: time.time())

        Returns:
            bool: True, if data was sent successfully, False, if not.

        """

        if sname is None:
            sname = "unknownEvent"
        if dname is None:
            dname = self._devicename
        if self._ev:
            self._ev(text, sname, dname, x, priority, value=value, id=id)
            return True
        else:
            logging.warning("No event connected")
            return False

    def setDeviceName(self, devicename="noDevice"):
        """
        Use this function to set a default devicename. If you do this, you don't need to submit the devicename with any call of any function

        Args:
            devicename (str): Default: `'noDevice'`

        Returns:
            None
        """
        self._devicename = devicename    # Is shown in GUI

    def close(self):
        """
        This function stops threads using `self.run`. It also closes the QWidget.

        Normally this function is only called by RTOC, when disconnecting plugins, but you can also call it.
        """
        self.run = False
        if self.widget:
            self.widget.hide()
            self.widget.close()
        if self._pluginThread and not self._oldPerpetualTimer:
            self._pluginThread.cancel()

    def setSamplerate(self, rate):
        """
        Sets the samplerate [Hz] of the defined perpetual timer.

        Args:
            rate (float)

        Returns:
            bool: True, if perpetual timer was already configured, False, if not.

        """
        if self._pluginThread is not None:
            self.samplerate = rate
            return True
        else:
            return False

    def setInterval(self, interval):
        """
        Sets the interval [s] of the defined perpetual timer.

        Args:
            interval (float)

        Returns:
            bool: True, if perpetual timer was already configured, False, if not.

        """
        if self._pluginThread is not None:
            self.samplerate = 1/interval
            return True
        else:
            return False

    @property
    def samplerate(self):
        return self._samplerate

    @samplerate.setter
    def samplerate(self, samplerate):
        self._samplerate = samplerate
        if self._pluginThread is not None and not self._oldPerpetualTimer:
            self._pluginThread.setSamplerate(samplerate)

    def info(self, msg):
        date = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        message = [date, 0, str(msg)]
        self._log.append(message)
        logging.info(msg)

    def warning(self, msg):
        date = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        message = [date, 1, str(msg)]
        self._log.append(message)
        logging.warning(msg)

    def error(self, msg):
        date = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        message = [date, 2, str(msg)]
        self._log.append(message)
        logging.error(msg)

    def debug(self, msg):
        date = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        message = [date, -1, str(msg)]
        self._log.append(message)
        logging.debug(msg)

    def createPersistentVariable(self, name, fallback=None, dname=None, docs=None):
        """
        Creates a persistent variable, which can be edited and will be restored after restart/reboot.
        You can create it like this:
        self.createPersistentVariable('perVar', 5)

        After this, you can access it's value with 'self.perVar' and edit it in the same way.

        Args:
            name (str): Name of the parameter,
            fallback (any): Alternative value, if parname is not available (for initialization),
            dname (str): Devicename, selected by default

        Returns:
            PersistentVariable: Parameter to be used in Logger.

        """
        # if dname == None:
        #     dname = self._devicename
        # return PersistentVariable(self.logger, parname, fallback, dname)
        
        # Create 'private' parameter with _ in front: self._name
        if self.logger.isPersistentVariable(name, dname):
            fallback = self.logger.loadPersistentVariable(name, None, dname)
        
        setattr(self.__class__, '_'+name, fallback)

        # This intermediate function handles the strange double self arguments
        def setter(self, name, dname, selfself, value):
            self._setPersistentAttribute(name, value, dname)

        # Make sure, that the parameters are "the values, which would be represented at this point with print(...)"
        setpart = partial(setter, self, name, dname)
        getpart = partial(getattr, self, '_'+name)

        # Create an attribute with the actual name. The getter refers to it's self._name attribute. The setter function to self._setGroupAttribute(name, value, parameter)
        setattr(self.__class__, name, property(getpart, setpart))
        
        # If contains docs, create a third attribute at self.__doc_PARNAME__
        if docs != None:
            setattr(self, '__doc_'+name+'__', docs)
    
    def _setPersistentAttribute(self, name, value, dname):
        setattr(self.__class__, '_'+name, value)
        self.logger.savePersistentVariable(name, value, dname)


    def initPersistentVariable(self, parname, value=None, dname=None):
        if dname == None:
            dname = self._devicename
        return self.logger.initPersistentVariable(parname, value, dname)

    def loadPersistentVariable(self, parname, fallback=None, dname=None):
        """
        Loads a persistent variable, which can be edited and will be restored after restart/reboot.

        Args:
            parname (str): Name of the parameter,
            fallback (any): Alternative value, if parname is not available (for initialization),
            dname (str): Devicename, selected by default

        Returns:
            any: Parameter-value

        """
        if dname == None:
            dname = self._devicename
        return self.logger.loadPersistentVariable(parname, fallback, dname)

    def savePersistentVariable(self, parname, value, dname=None):
        """
        Saves a persistent variable to a file in RTOC-directory.

        Args:
            parname (str): Name of the parameter,
            fallback (any): Alternative value, if parname is not available (for initialization),
            dname (str): Devicename, selected by default

        Returns:
            bool: True, if variable successfully saved.

        """
        if dname == None:
            dname = self._devicename
        return self.logger.savePersistentVariable(parname, value, dname)
        

    def setPerpetualTimer(self, fun, samplerate=None, interval = None, old = False):
        """
        Configures a perpetual timer. A perpetual timer is a thread, which is repeated infinitly in a specified time-interval or samplerate.

        Args:
            fun (function): The function to be called periodically.
            samplerate (float): The desired samplerate.
            interval (float): The desired time-delay interval.
            old (bool): If True, an old method for perpetual timer is used (based on :mod:`threading.Thread`). If False, the new method will be used (based on :mod:`threading.Timer`).

        Returns:
            bool: True, if perpetual timer could be configured, False, if not.

        """
        if old:
            self._oldPerpetualTimer = True
        else:
            self._oldPerpetualTimer = False

        if samplerate is None and interval is None:
            samplerate = self.samplerate
        elif samplerate is None:
            samplerate = 1/interval

        if not self._oldPerpetualTimer:
            try:
                self._samplerate = samplerate
                self._pluginThread = _perpetualTimer(fun, samplerate, self.lockPerpetialTimer)
                return True
            except Exception:
                self._pluginThread = None
                return False
        else:
            try:
                self._samplerate = samplerate
                self._pluginThread = Thread(target=self.__updateT, args=(fun,))
                return True
            except Exception:
                self._pluginThread = None
                return False

    def start(self):
        """
        Starts the perpetual timer

        Returns:
            bool: True, if perpetual timer was already configured, False, if not.

        """
        if self._pluginThread:
            self.run = True
            self._pluginThread.start()
            return True
        else:
            self.run = False
            return False

    def cancel(self):
        """
        Stops the perpetual timer

        Returns:
            bool: True, if perpetual timer was already configured, False, if not.

        """
        if self._pluginThread:
            if not self._oldPerpetualTimer:
                self._pluginThread.cancel()
            self.run = False
            return True
        else:
            self.run = False
            return False

    def __updateT(self, func):
        diff = 0
        while self.run:
            if diff < 1/self._samplerate:
                time.sleep(1/self._samplerate-diff)
            start_time = time.time()
            func()
            diff = (time.time() - start_time)

    def telegram_send_message(self, text, priority=0, permission='write'):
        """
        Sends a message to all clients with given permission and higher permission.

        Args:
            text (str): Text to be send to the clients.
            priority (int): Priority to decide, which allow each client to disable notifications (0: Information, 1: Warning, 2: Error)
            permission (str): Choose user-permission (blocked, read, write, admin)
        """
        if self._bot is not None:
            self._bot.send_message_to_all(self._devicename+': '+str(text), priority, permission)
        else:
            logging.warning('TelegramBot is not enabled or wrong configured! Can not send message "{}"'.format(text))

    def telegram_send_photo(self, path, priority=0, permission='write'):
        """
        Sends the picture at a given path to all clients with given permission and higher permission.

        Args:
            path (str): Path to the picture to send.
            priority (int): Priority to decide, which allow each client to disable notifications (0: Information, 1: Warning, 2: Error)
            permission (str): Choose user-permission (blocked, read, write, admin)
        """
        if self._bot is not None:
            self._bot.send_photo(path, priority, permission)
        else:
            logging.warning('TelegramBot is not enabled or wrong configured! Can not send photo "{}"'.format(path))

    def telegram_send_document(self, path, priority=0, permission='write'):
        """
        Sends any document at a given path to all clients with given permission and higher permission.

        Args:
            path (str): Path to the file to send.
            priority (int): Priority to decide, which allow each client to disable notifications (0: Information, 1: Warning, 2: Error)
            permission (str): Choose user-permission (blocked, read, write, admin)
        """
        if self._bot is not None:
            self._bot.send_document(path, priority, permission)
        else:
            logging.warning('TelegramBot is not enabled or wrong configured! Can not send file "{}"'.format(path))

    def telegram_send_plot(self, signals={}, title='', text='', events=[], dpi=300, priority=0, permission='write'):
        """
        Sends any document at a given path to all clients with given permission and higher permission.

        Args:
            signals (dict): Contains multiple sets of x-y data, e.g. ``{'signal1':[1,2,3,4,5],[4,3,6,5,7]}``
            title (str): The title displayed above the graph.
            text (str): The plot-description text
            events (list): A list containing pseudo-events (text+vertical-line), e.g. ``[[10, 'Hello world at x=10']]``
            dpi (int): Resolution of plot.
            priority (int): Priority to decide, which allow each client to disable notifications (0: Information, 1: Warning, 2: Error)
            permission (str): Choose user-permission (blocked, read, write, admin)
        """
        if self._bot is not None:
            self._bot.send_plot(signals, title, text, events, dpi, priority, permission)
        else:
            logging.warning('TelegramBot is not enabled or wrong configured! Can not send plot')
Example #11
0
class BasePolicy(object):
    """
    Template Policy that implements minimal functionality to run an argument
    """
    def __init__(self, name="base", argument=None):
        """

        Args:
            name:
            argument:
        """
        self.name = name
        self.current_statement = None
        self.current_premise = None
        self._cache = []
        self.last_dialog = None
        self.finished = False
        self._in_agreement = True
        self.argument = argument
        self._output = ""
        self._input = ""
        self._async_thread = None
        self._skip_feedback = False
        self._last_prompt = ""

    # lib
    def bind(self, argument):
        """

        Args:
            argument:
        """
        self.argument = argument
        self.argument.load()

    def reset(self):
        """

        """
        self._in_agreement = True
        self.current_premise = None
        self.current_statement = None
        self._cache = []
        self.last_dialog = None
        self.finished = False

    def speak(self, text):
        """
        - normalize text
        - cache response, self._cache_this(text)
        - manage output, self._output += text
        - return normalized text

         """
        text = str(text).strip()
        self._cache_this(text)
        if self._output and not self._output.endswith("\n"):
            self._output += "\n"
        self._output += text
        return text

    def is_cached(self, entry):
        """
        check if entry was used already

        Args:
            entry: text or Statement

        Returns: is_cached (bool)

        """
        entry = str(entry).strip()
        return entry in self.already_spoken

    def _cache_this(self, entry):
        """

        Args:
            entry:
        """
        entry = str(entry).strip()
        self._cache.append(entry)

    def _clean_prompt(self, prompt):
        """

        Args:
            prompt:

        Returns:

        """
        prompt = prompt or "Do you agree with {{statement}} ?"
        if isinstance(prompt, list):
            prompt = random.choice(prompt)
        if self.current_statement is not None:
            current_statement = self.current_statement.text.strip()
        else:
            current_statement = "what i just said"
        prompt = prompt \
            .replace("{{statement}}", current_statement) \
            .replace("{statement}", current_statement) \
            .replace("{{ statement }}", current_statement) \
            .replace("{ statement }", current_statement)
        return prompt + " "

    # dialog data
    @property
    def user_agrees(self):
        """
        Does the user agree with the argument

        Returns: in_agreement (bool)

        """
        return self._in_agreement

    @property
    def already_spoken(self):
        """

        Returns: already spoken responses (list)

        """
        return self._cache

    @property
    def output(self):
        """

        Returns: current bot dialog (str)

        """
        return self._output

    @property
    def intro_statement(self):
        """

        Returns: argument introduction (str)

        """
        if self.argument is not None:
            return str(self.argument.intro_statement)
        return ""

    @property
    def conclusion_statement(self):
        """

        Returns: argument conclusion (str)

        """
        if self.argument is not None:
            return self.argument.conclusion_statement
        return ""

    @property
    def premises(self):
        """

        Returns: all premises of this argument (list)

        """
        if self.argument is not None:
            return self.argument.premises
        return []

    # dialog actions
    def start(self):
        """ prepare context of dialog

        - reset policy, self.reset()
        - set running flag, self.finished = False
        - speak intro statement

        Returns: intro statement (str)

        """
        self.reset()
        self.finished = False
        return self.speak(self.intro_statement)

    def end(self):
        """ handle outcome of dialog

        - unset running flag, self.finished = True
        - return speak conclusion statement

        Returns: conclusion statement (str)

        """
        self.finished = True
        return self.speak(self.conclusion_statement)

    def choose_premise(self, argument=None):
        """
        select which Premise to tackle next

        Returns: next premise (Premise)
        """
        argument = argument or self.argument
        choices = [t for t in argument.premises if not self.is_cached(t)]
        if not len(choices):
            return None
        assertion = random.choice(choices)
        self._cache_this(assertion)  # remember assertion
        return assertion

    def choose_next_statement(self, premise=None):
        """
        select which Statement to tackle next

        Returns: next statement (Statement)
        """
        premise = premise or self.current_premise
        choices = [t for t in premise.statements if not self.is_cached(t)]
        if not len(choices):
            # go to next premise
            next_assertion = self.choose_premise()
            if next_assertion is None:
                self.finished = True
                return None  # no statements left
            self.current_premise = next_assertion
            return self.choose_next_statement()

        statement = random.choice(choices)
        self.current_statement = statement
        return statement

    def agree(self):
        """
        Agree with current premise
        """
        self._in_agreement = True

    def disagree(self):
        """
        Disagree with current premise
        """
        self._in_agreement = False

    def what(self, default_answer="i don't know how to explain"):
        """ explain current statement """
        answer = default_answer
        choices = [
            t for t in self.current_premise.what if not self.is_cached(t)
        ]
        if len(choices):
            answer = random.choice(choices)
        return self.speak(answer)

    def why(self, default_answer="i don't know why"):
        """ explain cause of current statement """
        answer = default_answer
        choices = [
            t for t in self.current_premise.why if not self.is_cached(t)
        ]
        if len(choices):
            answer = choices[0]

        return self.speak(answer)

    def how(self, default_answer="i don't know how"):
        """ explain how current statement """
        answer = default_answer
        choices = [
            t for t in self.current_premise.how if not self.is_cached(t)
        ]
        if len(choices):
            answer = random.choice(choices)

        return self.speak(answer)

    def when(self, default_answer="i don't know when"):
        """ explain when current statement happened """
        answer = default_answer
        choices = [
            t for t in self.current_premise.when if not self.is_cached(t)
        ]
        if len(choices):
            answer = random.choice(choices)

        return self.speak(answer)

    def where(self, default_answer="i don't know where"):
        """ explain where current statement happened """
        answer = default_answer
        choices = [
            t for t in self.current_premise.where if not self.is_cached(t)
        ]
        if len(choices):
            answer = random.choice(choices)

        return self.speak(answer)

    def sources(self, default_answer="i don't remember where i learned this"):
        """ sources of current statement """
        answer = default_answer
        if len(self.current_premise.sources):
            answer = " ".join(self.current_premise.sources)
        return answer

    def skip_feedback(self):
        """
        Do not ask for user feedback
        """
        self._skip_feedback = True

    def reprompt(self):
        """

        Speak last used prompt

        Returns: last prompt (str)

        """
        return self.speak(self._last_prompt)

    # sync
    def _run_once(self):
        """

        Returns:

        """
        # check if argument is fully exposed
        if self.finished:
            return None

        # check if we have an assertion
        if self.current_premise is None:
            current_assertion = self.choose_premise()
            self.current_premise = current_assertion

        # pick action
        if not self.user_agrees:
            return self.on_negative_feedback()
        else:
            return self.on_positive_feedback()

    def run(self):
        """ run the interaction, ask if user agrees or not after every
        statement

        NOTE: ignores on user input callback, mostly meant for quick testing
        """
        # introduce argument
        print(self.start())
        while not self.finished:
            try:
                # choose output
                output = self._run_once()
                if output is None:
                    # wait for output
                    continue
                print(output)
                if self.finished:
                    break
                # get user feedback
                if self._skip_feedback:
                    self._skip_feedback = False
                    continue
                if self.get_feedback():
                    self.agree()
                else:
                    self.disagree()

            except Exception as e:
                log.exception(e)
        # finish off argument
        print(self.end())

    def get_feedback(self, prompt=None):
        """
        used in run(), if running async wait_for_feedback is used instead

        ask user if he agrees with current statement or not

        prompt is a string or list of strings, if it's a list a random entry will be picked

        return True or False """
        prompt = self._clean_prompt(prompt)
        self._last_prompt = prompt
        return "y" in input(prompt).lower()

    # async
    def wait_for_input(self):
        """
        wait until self.submit_input is called
        """
        self._input = ""
        while not self._input:
            sleep(0.5)

    def wait_for_feedback(self, prompt=None):
        """
        ask user if he agrees with current statement or not

        prompt is a string or list of strings, if it's a list a random entry will be picked

        return True or False """
        prompt = self._clean_prompt(prompt)
        self._output += "\n" + prompt
        self._last_prompt = prompt
        self.wait_for_input()
        return "y" in self._input.lower()

    def submit_input(self, text):
        """

        Args:
            text: utterance (str)
        """
        self._output = ""
        if self.on_user_input(text):
            self._input = text

    def run_async(self):
        """
        Start listening for user input
        """
        self._async_thread = Thread(target=self._async_loop)
        self._async_thread.setDaemon(True)
        self._async_thread.start()

    def stop(self):
        """
        Stop listening for user input
        """
        self.finished = True
        try:
            self._async_thread.join()
            self._async_thread.cancel()
        except:
            pass
        self._async_thread = None

    def _async_loop(self):
        """ run the interaction async """
        # introduce argument
        self.start()
        while not self.finished:
            try:
                # choose output
                if not self._run_once():
                    continue

                if self._skip_feedback:
                    self._skip_feedback = False
                    continue
                # get user feedback
                if self.wait_for_feedback():
                    self.agree()
                else:
                    self.disagree()
            except Exception as e:
                log.exception(e)
        # finish off argument
        self.end()

    # events
    def on_user_input(self, text):
        """ handle user input

        intent parsing should be done here

        typical actions are

        - calling self.agree() or self.disagree() to direct the policy (return True)
        - calling self.what(), self.why(), self.how(), self.when(),
        self.where() and setting the output (return False)

        NOTE: only when running async

        return True or False, this determines if dialog should proceed or
        wait for different user input

        """
        return True

    def on_positive_feedback(self):
        """ react to positive feedback

        by default goes to next statement

        """
        statement = self.choose_next_statement()
        if not statement:
            return None
        return self.speak(statement)

    def on_negative_feedback(self):
        """ react to negative feedback

        by default goes to next statement
        """
        statement = self.choose_next_statement()
        if not statement:
            return None
        return self.speak(statement)