Jump to content
LaunchBox Community Forums

HowTo: Custom Playlist creation with Python


phlaange

Recommended Posts

I've been trying to figure out which (Arcade) games to play but the MAME ROMset just has sooo many. Sure, Launchbox lets us filter and sort by Star Rating but this seemed a little problematic to me. Now, I'm sure that the *7* people that gave Super Puzzle Bobble a 5 felt it earned it but that's just not enough sentiment for me to thrust it into the best of the best games.

So I decided I needed another metric to discover the best content. One that, despite the data being present in Launchbox, was not offered as either a filter or sort by option.

Total Community Star Rating Votes.

I figured if enough of you voted for a game, I should probably play it. So I created a Playlist. Well, 2 actually. Here's how.

Caveats:

  • It can be dangerous altering Launchbox's files
  • This requires at least some familiarity with Python
  • Do NOT run this when Launchbox is running
  • You will need to edit the filename paths to match those on your system. There a five places in the code
  • You will need to create each of the Playlists in Launchbox first to get the PlaylistId (from the Playlist XML file), then replace the PlaylistId's in the code 
    • If you decide to use a different Playlist name, change that in the code, too

Code description:

  • Read in Arcade.xml and get the list of all Arcade games
  • Open the first XML file (Most Rated 30-49.xml) and write the XML header and Playlist definition
  • Loop through the list of Arcade games with between 30 and 49 votes, saving each to the XML
  • Write the closing XML tag
  • Open the second XML file (Most Rated 50+.xml) and write the XML header and Playlist definition
  • Loop through the list of Arcade games with 50 or more votes, saving each to the XML
  • Write the closing XML tag

 

from bs4 import BeautifulSoup as soup

filename = 'C:\Emulators\LaunchBox\Data\Platforms\Arcade.xml'
f = open(filename, encoding='UTF-8')

xml_soup = soup(f, 'xml')

games = xml_soup.findAll('Game', {})

filename = 'C:\\Emulators\\LaunchBox\\Data\\Playlists\\Most Rated 30-49.xml'
f = open(filename, 'w')
f.truncate()

header = '''<?xml version="1.0" standalone="yes"?>
<LaunchBox>
  <Playlist>
    <PlaylistId>876c8f1c-1e01-4966-90b6-63d7a87a9a27</PlaylistId>
    <Name>Most Rated 30-49</Name>
    <NestedName>Most Rated 30-49</NestedName>
    <SortBy>Default</SortBy>
    <Notes />
    <VideoPath />
    <IncludeWithPlatforms>true</IncludeWithPlatforms>
    <AutoPopulate>false</AutoPopulate>
    <SortTitle />
    <IsAutogenerated>false</IsAutogenerated>
  </Playlist>
'''
f.write(header)

man_order = 0

for game in games:
    if int(game.CommunityStarRatingTotalVotes.text) > 30 and int(game.CommunityStarRatingTotalVotes.text) < 49:
        g_id = str(game.ID.text)
        lb_id = str(game.DatabaseID.text)
        g_title = str(game.Title.text)
        g_title = g_title.replace('&', '&')
        if len(game.ApplicationPath.text) > 0:
            g_filename = str(game.ApplicationPath.text).replace('G:\\Games\\mame\\roms\\','')
        g_platform = str(game.Platform.text)
        
        xml_string = "  <PlaylistGame>\n    <GameId>" + g_id + "</GameId>\n    <LaunchBoxDbId>" + lb_id + "</LaunchBoxDbId>\n    <GameTitle>" + g_title + "</GameTitle>\n    <GameFileName>" + g_filename + "</GameFileName>\n    <GamePlatform>" + g_platform + "</GamePlatform>\n    <ManualOrder>" + str(man_order) + "</ManualOrder>\n  </PlaylistGame>\n"
        f.write(xml_string)
        man_order += 1

f.write("</LaunchBox>")

filename = 'C:\\Emulators\\LaunchBox\\Data\\Playlists\\Most Rated 50+.xml'
f = open(filename, 'w')
f.truncate()

header = '''<?xml version="1.0" standalone="yes"?>
<LaunchBox>
  <Playlist>
    <PlaylistId>b5cc4b9c-09df-4409-9786-a1c44f43a318</PlaylistId>
    <Name>Most Rated 50+</Name>
    <NestedName>Most Rated 50+</NestedName>
    <SortBy>Default</SortBy>
    <Notes />
    <VideoPath />
    <IncludeWithPlatforms>true</IncludeWithPlatforms>
    <AutoPopulate>false</AutoPopulate>
    <SortTitle />
    <IsAutogenerated>false</IsAutogenerated>
  </Playlist>
'''
f.write(header)

man_order = 0

for game in games:
    if int(game.CommunityStarRatingTotalVotes.text) > 50:
        g_id = str(game.ID.text)
        lb_id = str(game.DatabaseID.text)
        g_title = str(game.Title.text)
        g_title = g_title.replace('&', '&')
        if len(game.ApplicationPath.text) > 0:
            g_filename = str(game.ApplicationPath.text).replace('G:\\Games\\mame\\roms\\','')
        g_platform = str(game.Platform.text)
        
        xml_string = "  <PlaylistGame>\n    <GameId>" + g_id + "</GameId>\n    <LaunchBoxDbId>" + lb_id + "</LaunchBoxDbId>\n    <GameTitle>" + g_title + "</GameTitle>\n    <GameFileName>" + g_filename + "</GameFileName>\n    <GamePlatform>" + g_platform + "</GamePlatform>\n    <ManualOrder>" + str(man_order) + "</ManualOrder>\n  </PlaylistGame>\n"
        f.write(xml_string)
        man_order += 1

f.write("</LaunchBox>")

 

Tips

Python is indent sensitive. I can't guarantee that the forum won't munge the indentation (although it looks okay after posting).

Multiple line strings in Python are denoted by triple quotes. That's how the header variable is defined.

I use a Jupyter Notebook to run this code. This is part of Anaconda (https://www.anaconda.com/distribution/) and is a fairly easy way to get started with Python. I'd link a tutorial but I've learned how to use it on a paid site.

When I initially created the Playlists I did it by adding a single game to the Playlist and entering only the Unique Name and Nested Name.

image.thumb.png.884ebe8eb7c96758f55c1095f00504a1.pngimage.thumb.png.40015f2ec4127219a0ac4d0eca9db664.png

What have I forgotten?

 

 

Edited by phlaange
Checking code formatting.
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...