• Drizzel

    @JonB great, thanks a lot!

    posted in Pythonista read more
  • Drizzel

    I changed my code up a bit, so here’s the main script:

    from scene import *
    import sound
    import random
    import math
    import extension
    A = Action
    history = []
    
    entitiesPerGeneration = 5
    
    class MyScene (Scene):
        def setup(self):
            self.position = self.size/2
            self.background_color = 'white'
            self.target = ShapeNode(rect(0,0,10,10))
            self.target.color = 'blue'
            self.target.size = (10, 10)
            self.target.position = self.size/2-(self.size.x-10,10)
            self.add_child(self.target)
            self.obstacles = []
            self.entities = []
            for entity in range(entitiesPerGeneration):
                extension.createEntity(self, [])
            pass
        
        def did_change_size(self):
            pass
        
        def update(self):
            if extension.allDone(self):
                fitness = extension.calculateFitness(self)
                parent = extension.chooseParent(self)
                extension.killEntities(self)
                for i in range(entitiesPerGeneration):
                    extension.createEntity(self, parent.moves)
                    extension.mutate(self, self.entities[i])
                    print(self.entities[i].moves, '\n')
                print('------------------------------------------------------------------------\n')
                #entity.moves are different for every entity up to here
                
                for i in range(len(self.entities)-1): #checks if all entities have the same moves
                    print(self.entities[i+1].moves == self.entities[i].moves)
                    print(self.entities[i].moves)
                
                    
            else:
                for entity in self.entities:
                    if entity.done == False:
                        extension.move(self, entity)
                        extension.checkCollision(self, entity)
            pass
        
    if __name__ == '__main__':
        run(MyScene(), show_fps=False)
    

    And here’s the extension script:

    from scene import *
    import sound
    import random
    import math
    import time
    
    maxVel = 200
    accIncrease = 15
    mutationPercentage = 100
    
    def calculateDistance(a, b):
        x1 = a[0]  
        x2 = b[0]
        y1 = a[1]
        y2 = b[1]
        dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)  
        return dist 
    
                
    def move(self, sprite):
        if sprite.currentMove <= len(sprite.moves)-1:
            sprite.acc = sprite.moves[sprite.currentMove]
        else:
            angle = random.randint(0, 360)
            changeX = round(math.sin(math.radians(angle)), 4)
            changeY = round(math.cos(math.radians(angle)), 4)
            sprite.acc = Vector2(changeX, changeY) * accIncrease
            sprite.moves.append(sprite.acc)
            
        sprite.vel += sprite.acc
    
        if sprite.vel[0] <= -maxVel or sprite.vel[0] >= maxVel:  #checks that velocity won't exceed maxVel
            if sprite.vel[0] < 0: sprite.vel = Vector2(-maxVel, sprite.vel[1])
            else: sprite.vel = Vector2(maxVel, sprite.vel[1])       
        if sprite.vel[1] <= -maxVel or sprite.vel[1] >= maxVel:
            if sprite.vel[1] < 0: sprite.vel = Vector2(sprite.vel[0], -maxVel)
            else: sprite.vel = Vector2(sprite.vel[0], maxVel)
    
        sprite.currentMove = sprite.currentMove + 1
        sprite.run_action(Action.move_by(sprite.vel[0]*self.dt, sprite.vel[1]*self.dt,self.dt))
        
    def allDone(self):
        allDone = True
        for entity in self.entities:
            if entity.done == False:
                allDone = False
                break
        return allDone
        
    def calculateFitness(self):
        for entity in self.entities:
            try:
                distance = calculateDistance(entity.position, self.target.position)
                sprite.fitness = 1000/distance
            except: ZeroDivisionError
            
    
    def checkCollision(self, entity):
        if entity.frame.intersects(self.target.frame): 
            entity.done = True
            entity.color = '#00ff00'
        if entity.position.x < -self.size.x/2 + entity.size.x/2 or entity.position.x > self.size.x/2 - entity.size.x/2 or entity.position.y < -self.size.y/2 + entity.size.y/2 or entity.position.y > self.size.y/2 - entity.size.y/2:
            entity.done = True
            entity.color = 'red'
        for obstacle in self.obstacles:
            if entity.frame.intersects(obstacle.frame): 
                entity.done = True
                entity.color = 'red'
                
    def chooseParent(self):
        parents = []
        for i in range(len(self.entities)):
            for a in range(round(self.entities[i].fitness)+1):
                parents.append(i)
        parent = random.choice(parents)
        return self.entities[parent]
        
    def killEntities(self):
        for sprite in self.entities:
            sprite.remove_from_parent()
        self.entities = []
        
    def createEntity(self, moves):
        self.entities.append(ShapeNode(rect(0,0,10,10)))
        self.entities[len(self.entities)-1].color = 'black'
        self.entities[len(self.entities)-1].size = (10,10)
        self.entities[len(self.entities)-1].position = (0,0)
        self.entities[len(self.entities)-1].vel = Vector2(0,0)
        self.entities[len(self.entities)-1].acc = Vector2(0,0)
        self.entities[len(self.entities)-1].moves = moves
        self.entities[len(self.entities)-1].currentMove = 0
        self.entities[len(self.entities)-1].fitness = 0
        self.entities[len(self.entities)-1].done = False
        self.add_child(self.entities[len(self.entities)-1])
        
    def mutate(self, entity):
        for i in range(len(entity.moves)):
            if random.randint(1, 100) <= mutationPercentage:
                angle = random.randint(0, 360)
                changeX = round(math.sin(math.radians(angle)), 4)
                changeY = round(math.cos(math.radians(angle)), 4)
                move = Vector2(changeX, changeY) * accIncrease
                entity.moves[i] = move
    

    I really have no idea why this happens,but this happened before. Although the mutate() function does actually change the path of the squares (verified by printing out the path of every square and comparing them manually), all of these paths change to the path of the last entity in the self.entities array. I check this with 3 lines of code just after printing out all of the paths, and somehow they all are the same without some command to do that. There has to be some statement that causes this, but I have absolutely no clue how/ where/ why this occurs.

    posted in Pythonista read more
  • Drizzel

    I just watched a video of codeBullet yesterday where he explained the basics of coding a simple “intelligent” algorithm that I wanted to recreate. The idea is that the black squares (I don’t know how to make dots) try to find their way to the blue target in the top left corner. Here’s the code of my main script:

    from scene import *
    import sound
    import random
    import math
    import extension
    A = Action
    
    entitiesPerGeneration = 5
    
    class MyScene (Scene):
        def setup(self):
            self.position = self.size/2
            self.background_color = 'white'
            self.target = ShapeNode(rect(0,0,10,10))
            self.target.color = 'blue'
            self.target.size = (10, 10)
            self.target.position = self.size/2-(self.size.x-10,10)
            self.add_child(self.target)
            self.obstacles = []
            self.entities = []
            for entity in range(entitiesPerGeneration):
                self.entities.append(ShapeNode(rect(0,0,10,10)))
                self.entities[entity].color = 'black'
                self.entities[entity].size = (10,10)
                self.entities[entity].position = (0,0)
                self.entities[entity].vel = Vector2(0, 0)
                self.entities[entity].acc = Vector2(0, 0)
                self.entities[entity].moves = []
                self.entities[entity].currentMove = 0
                self.entities[entity].fitness = 0
                self.entities[entity].done = False
                self.add_child(self.entities[entity])
            pass
        
        def did_change_size(self):
            pass
        
        def update(self):
            if extension.allDone(self):
                fitness = extension.calculateFitness(self)
                parent = extension.chooseParent(self)
                extension.killEntities(self)
                for i in range(entitiesPerGeneration-1):
                    extension.createEntity(self, parent.moves, parent.vel, parent.acc)
                for entity in self.entities:
                    extension.mutate(self, entity)
                extension.createEntity(self, parent.moves, parent.vel, parent.acc)
                self.entities[len(self.entities)-1].color = 'pink'
                
                
            else:
                for entity in self.entities:
                    if entity.done == False:
                        extension.move(self, entity)
                        extension.checkCollision(self, entity)
            
            pass
        
        def touch_began(self, touch):
            pass
        
        def touch_moved(self, touch):
            pass
        
        def touch_ended(self, touch):
            pass
    
    if __name__ == '__main__':
        run(MyScene(), show_fps=False)
    

    and here’s extension.py

    from scene import *
    import sound
    import random
    import math
    import time
    
    maxVel = 100
    accIncrease = 15
    mutationPercentage = 5
    
    def calculateDistance(a, b):
        x1 = a[0]  
        x2 = b[0]
        y1 = a[1]
        y2 = b[1]
        dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)  
        return dist 
    
                
    def move(self, sprite):
        if sprite.currentMove <= len(sprite.moves)-1:
            sprite.acc = sprite.moves[sprite.currentMove]
            
        else:
            angle = random.randint(0, 360)
            changeX = round(math.sin(math.radians(angle)), 4)
            changeY = round(math.cos(math.radians(angle)), 4)
            sprite.acc = Vector2(changeX, changeY) * accIncrease
            
        sprite.vel += sprite.acc
    
        if sprite.vel[0] <= -maxVel or sprite.vel[0] >= maxVel:  #checks that velocity won't exceed maxVel
            if sprite.vel[0] < 0: sprite.vel = Vector2(-maxVel, sprite.vel[1])
            else: sprite.vel = Vector2(maxVel, sprite.vel[1])
                
        if sprite.vel[1] <= -maxVel or sprite.vel[1] >= maxVel:
            if sprite.vel[1] < 0: sprite.vel = Vector2(sprite.vel[0], -maxVel)
            else: sprite.vel = Vector2(sprite.vel[0], maxVel)
    
        sprite.moves.append(sprite.acc)
            
        sprite.currentMove = sprite.currentMove + 1
        sprite.run_action(Action.move_by(sprite.vel[0]*self.dt, sprite.vel[1]*self.dt,self.dt))
        
    def allDone(self):
        allDone = True
        for entity in self.entities:
            if entity.done == False:
                allDone = False
                break
        return allDone
        
    def calculateFitness(self):
        for entity in self.entities:
            try:
                distance = calculateDistance(entity.position, self.target.position)
                sprite.fitness = 1000/distance
            except: ZeroDivisionError
            
    
    def checkCollision(self, entity):
        if entity.frame.intersects(self.target.frame): 
            entity.done = True
            entity.color = '#00ff00'
        if entity.position.x < -self.size.x/2 + entity.size.x/2 or entity.position.x > self.size.x/2 - entity.size.x/2 or entity.position.y < -self.size.y/2 + entity.size.y/2 or entity.position.y > self.size.y/2 - entity.size.y/2:
            entity.done = True
            entity.color = 'red'
        for obstacle in self.obstacles:
            if entity.frame.intersects(obstacle.frame): 
                entity.done = True
                entity.color = 'red'
                
    def chooseParent(self):
        parents = []
        for i in range(len(self.entities)):
            for a in range(round(self.entities[i].fitness)+1):
                parents.append(i)
        parent = random.choice(parents)
        return self.entities[parent]
        
    def killEntities(self):
        for sprite in self.entities:
            sprite.remove_from_parent()
        self.entities = []
        
    def createEntity(self, moves, vel, acc):
        self.entities.append(ShapeNode(rect(0,0,10,10)))
        self.entities[len(self.entities)-1].color = 'black'
        self.entities[len(self.entities)-1].size = (10,10)
        self.entities[len(self.entities)-1].position = (0,0)
        self.entities[len(self.entities)-1].vel = vel
        self.entities[len(self.entities)-1].acc = acc
        self.entities[len(self.entities)-1].moves = moves
        self.entities[len(self.entities)-1].currentMove = 0
        self.entities[len(self.entities)-1].fitness = 0
        self.entities[len(self.entities)-1].done = False
        self.add_child(self.entities[len(self.entities)-1])
        
    def mutate(self, entity):
        for i in range(len(entity.moves)):
            if random.randint(1, 100) <= mutationPercentage:
                
                angle = random.randint(0, 360)
                changeX = round(math.sin(math.radians(angle)), 4)
                changeY = round(math.cos(math.radians(angle)), 4)
                move = Vector2(changeX, changeY) * accIncrease
                entity.moves[i] = move
                print('mutated')
    
    

    I know it’s not the shortest and most beautiful code out there, but I hope the smart ones here can solve my issue :)

    In theory, if the whole generation is dead, a new generation is created from one of the many squares. This new generation then mutates randomly. Therefore all squares have a slightly different path, even though they have the same parent. Somehow the whole generation follows the same path (which didn’t even change from the parent’s path). I tried to set the mutationPercentage to 100, so that 100% of all directions in the path are changed, but nothing changed. And afterwards pythonista crashes, again no idea why :D

    posted in Pythonista read more
  • Drizzel

    @cvp

    import ui
    import os
    import time
    import threading
    
    class my_thread(threading.Thread):
      def __init__(self,my_view):
          threading.Thread.__init__(self)
          self.my_view = my_view
      def run(self):
          while not self.stop:
              time.sleep(1)
              try:
                  d = webview.eval_js('document.getElementById("myaudio").duration;')
                  if d == 'NaN':
                      continue
                  c = webview.eval_js('document.getElementById("myaudio").currentTime;')
                  c = float(c)
                  d = float(d)
                  self.my_view['currentTime'].value = c/d
                  self.my_view['timers'].text = str(int(c)) + '/' + str(int(d)) + ' sec.'
              except Exception as e:
                  pass
    
    path = 'Johnny Rivers - John Lee Hooker - Live At The Whiskey A Go Go.mp3'
    absfilepath=os.path.abspath(path)
    
    TEMPLATE='''
    <audio id="myaudio" autoplay preload="auto">
        <source src="file://{{FPATH}}" type="audio/mp3">
    </audio>
    '''
    
    webview = ui.WebView(name='webview')
    
    bplay = ui.ButtonItem()
    bplay.image = ui.Image.named('iob:play_32')
    def bplay_action(sender):
      webview.eval_js('document.getElementById("myaudio").play();')
    bplay.action = bplay_action
    
    bpause = ui.ButtonItem()
    bpause.image = ui.Image.named('iob:ios7_pause_32')
    def bpause_action(sender):
      webview.eval_js('document.getElementById("myaudio").pause();')
    bpause.action = bpause_action
    
    bstop = ui.ButtonItem()
    bstop.image = ui.Image.named('iob:stop_32')
    def bstop_action(sender):
      # audio player of html5 does not have a stop function
      webview.eval_js('document.getElementById("myaudio").pause();')
      webview.eval_js('document.getElementById("myaudio").currentTime = 0;')
    bstop.action = bstop_action
    
    webview.right_button_items = [bplay,bpause,bstop]
    
    currentTime = ui.Slider(name='currentTime')
    currentTime.frame = (10,10,200,32)
    def currentTime_action(sender):
      d = webview.eval_js('document.getElementById("myaudio").duration;')
      c = currentTime.value * float(d)
      webview.eval_js('document.getElementById("myaudio").currentTime = ' + str(c) + ';') 
    currentTime.action = currentTime_action
    webview.add_subview(currentTime)
    
    timers = ui.Label(name='timers')
    timers.frame = (220,10,370,32)
    webview.add_subview(timers)
    
    html = TEMPLATE.replace('{{FPATH}}', absfilepath)
    webview.load_html(html)
    webview.name = path
    webview.frame = (0,0,600,100)
    
    webview.present('sheet')
    t = my_thread(webview)
    t.stop = False
    t.start()
    webview.wait_modal()
    # force stop player if not done
    webview.eval_js('document.getElementById("myaudio").pause();')
    webview.eval_js('document.getElementById("myaudio").currentTime = 0;')
    t.stop = True # force end of thread```
    

    Apologies if this seems like a stupid question, but how do I another song? Like, if a ui button is pressed, another song starts playing. I’m relatively new to coding in general, as I started learning python 2 years ago

    posted in Pythonista read more
  • Drizzel

    @cvp impressive, I wouldn’t have managed that this quickly :)

    This question may be a bit off topic, but do you have any idea why YouTube-dl downloads files with twice the length of the original YouTube video? The first half contains the audio, and the second half simply contains no sound.

    from __future__ import unicode_literals
    import youtube_dl
    import os
    from sys import argv
    
    
    
    # Download data and config
    download_options = {
        'format': 'm4a',
        'outtmpl': '%(title)s.%(ext)s',
        'nocheckcertificate': True,
        'preferredcodec': 'best',
    }
    
    # Download Songs
    with youtube_dl.YoutubeDL(download_options) as dl:
        with open('songs.txt', 'r') as f:
            for song_url in f:
                dl.download([song_url])
    

    posted in Pythonista read more
  • Drizzel

    Thanks a lot to both of you, that helped me loads! My html skills are rather limited and JavaScript is absolutely unfamiliar to me, but I will manage somehow, now that I have a good base I can start from :)

    posted in Pythonista read more
  • Drizzel

    @cvp great, that actually works :)
    Is there any way to stop, skip, and see information like how long the audio is and for how long it has been playing for? I have been searching for these things, but I can’t really find them. There is a stop() function, but for some reason it doesn’t change anything

    posted in Pythonista read more
  • Drizzel

    My goal is just play it offline, I’m trying to code something of a Spotify alternative for myself. Although I will at some point implement it in a ui

    posted in Pythonista read more
  • Drizzel

    I can play the audio if I manually quickplay it in the file browser.

    This here is the code to download and play a song from YouTube:

    from __future__ import unicode_literals
    import youtube_dl
    import os
    from sys import argv
    
    
    
    # Download data and config
    download_options = {
        'format': 'm4a',
        'outtmpl': '%(title)s.%(ext)s',
        'nocheckcertificate': True,
        'preferredcodec': 'best',
    }
    
    # Download Songs
    with youtube_dl.YoutubeDL(download_options) as dl:
        with open('songs.txt', 'r') as f:
            for song_url in f:
                dl.download([song_url])
                
    import sound
    path = os.listdir()[0]
    audio = sound.Player(path)
    audio.play()
    print(audio.playing)
    

    songs.txt just contains some links to music on YouTube.

    Every time I run this, I get this message:
    WARNING: aAiVsqfbn5g: writing DASH m4a. Only some players support this container. Install ffmpeg or avconv to fix this automatically.
    The last line of code always prints that the Audio is not playing when trying it with m4a fields downloaded from YouTube. The file @cvp used works flawlessly, just as some mp3 file I used for testing.
    Thanks a lot for trying to solve this, really

    posted in Pythonista read more
  • Drizzel

    @cvp No idea why, but I put the brackets, ran it once, got the error, removed the brackets, restarted pythonista, ran it, and it worked. Honestly, I can’t explain it. Nevertheless, thanks a lot.
    However, it won’t run m4a files (it doesn’t give me an error, but I just don’t hear anything). Do you know how to fix that? Or do I have to convert it to mp3 first?

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!