Coding

Code Project – JavaScript Drum Kit

The second actual project from the class I’ve been doing is a simple clickable drum kit. Part of the purpose was to work with signs and to work with clickable elements. Like the dice roller game, the basic HTML and images were provided, though there was some freedom in arranging the icons and sounds.

It feel a bit flaky, when it comes to overlapping sounds, but that also feels like a bit of a limitation with the code itself, or at least, the simplicity of what is being done here. I’m sure it’s “fixable” with some more advanced work. But for now it’s pretty neat. Works with clicks and keyboard presses.

It can be played by going here, and the full repository can be found here.

var w = new Audio('sounds/snare.mp3');
var a = new Audio('sounds/tom-1.mp3');
var s = new Audio('sounds/tom-3.mp3');
var d = new Audio('sounds/kick-bass.mp3');
var j = new Audio('sounds/tom-4.mp3');
var k = new Audio('sounds/tom-2.mp3');
var l = new Audio('sounds/crash.mp3');

for(var i=0 ; i < document.querySelectorAll(".drum").length; i++) {
    document.querySelectorAll(".drum")[i].addEventListener("click", function(event) {
    clickHandler(event.target.innerHTML)});
}

document.addEventListener("keydown", function(event) {
    clickHandler(event.key);
});

function clickHandler(which_sound) {
//    console.log(which_sound)
//    alert("Clicked!"); 
    flashButton(which_sound);

    switch (which_sound){
    case "w":
        w.play();
        break;
    case "a":
        a.play();
        break;
    case "s":
        s.play();
        break;
    case "d":
        d.play();
        break;
    case "j":
        k.play();
        break;
    case "k":
        k.play();
        break;
    case "l":
        l.play();
        break;
    default:
        console.log(which_sound)
        break;
    }
}

function flashButton (whichFlash) {
    var activeButton = document.querySelector("."+whichFlash);
    activeButton.classList.add("pressed");
    setTimeout(function(){ activeButton.classList.remove("pressed"); },0.3);
}

The large bulk of the code here is handling the sound. I feel like there could almost be a more elegant way of handling this process with a list, but I’m not positive since it would mean taking the text of a list element and using it as the name of a variable. The top chunk of definitions manages creating the sound elements themselves, and the switch statement in the middle plays one based on what the user did.

This function:

function flashButton (whichFlash) {
    var activeButton = document.querySelector("."+whichFlash);
    activeButton.classList.add("pressed");
    setTimeout(function(){ activeButton.classList.remove("pressed"); },0.3);
}

Makes the flash happen. Like I did for the Python class, I tried to construct most of these on my own, so had to do a bit of research to find a way to make the button add the “pressed” class, to get the bright effect, then shortly after, remove it. This seemed to be the appropriate method based on a couple of sources.

The real “meat” of this lesson was this bit of code.

for(var i=0 ; i < document.querySelectorAll(".drum").length; i++) {
    document.querySelectorAll(".drum")[i].addEventListener("click", function(event) {
    clickHandler(event.target.innerHTML)});
}

document.addEventListener("keydown", function(event) {
    clickHandler(event.key);
});

Specifically, using the event listener function, to call an embedded function in order to pass data around. Its similar in concept to some things I’d done in Python, and I am sure it’s nothing super fancy in technique, but its “new to me” in the Javascript sense. Also, I think the instructor handled this a different way, but I’ve set these two event listeners, one for the buttons for clicks, and one for the page for key presses, in a way that made the clickHandler a lot simpler, since they both work off of the same bit of data.

Code Project – JavaScript Dice Roller Game

I mentioned in my Python Class posts that I really enjoyed the instructor and I planned to eventually move to doing her Web Dev Course. Well, I’ve started working on that one. It’s not a “100 Days of Projects” so I’ve not been quite blitzing through it like I did the Python Course, and it’s a lot of material I am already way more familiar with. Hell, I skipped over the first third of the course because it was the same HTML/CSS content included int he Python Course.

My main goal here, is to get much more familiar with JavaScript. I have dabbled, lightly, in JavaScript (ok, let’s go with JS from here on), and well, it’s a coding language, so I already have a lot of the “logic” side down. At some point, learning new programming languages just becomes about learning the syntax and maybe some of the special uses for a particular language. I’d only say I am Intermediate or above in Python and HTML/PHP, but I’m familiar with several other languages including BASIC, C, C++, LSL (Linden Scripting Language), Arduino (mostly just C), Bash Shell scripting, SQL, Cold Fusion, and probably some other I am forgetting.

It all mostly works the same on the base level, a loop is a loop, conditionals are conditional, and it’s just a matter of remembering if the language uses braces or parenthesis or semi colons and if tabs matter. And that’s where Google becomes your friend.

Anyway, the first real stand along project of this course is a simple Dice rolling game. And I have to say, “game” is the loosest sense of the word. It’s a webpage you refresh to see if Player 1 or Player 2 has the higher dice face. I might actually try to make a more complex version of this later where you select from different Dice and it rolls them, for you know, gaming. Sure there are plenty of D&D Dice roller apps, but it would be a fun exercise.

The class provided the basic HTML Structure and graphics, since the focus was on the JavaScript side of things. It’s not an overly complex project, but here is the JS Code.

function setImage(diceImage, roll) {
    console.log(roll);
    if(roll === 1) { rolled = "images/dice1.png"; }
    else if(roll === 2) { rolled = "images/dice2.png"; }
    else if(roll === 3) { rolled = "images/dice3.png"; }
    else if(roll === 4) { rolled = "images/dice4.png"; }
    else if(roll === 5) { rolled = "images/dice5.png"; }
    else { rolled = "images/dice6.png"; }


    diceImage.src = rolled;
}

let player1Roll = Math.floor(Math.random()*6)+1;
let player2Roll = Math.floor(Math.random()*6)+1;

let dice1Image = document.querySelector("img.img1");
let dice2Image = document.querySelector("img.img2");

if( player1Roll > player2Roll) {
    document.getElementById("headtext").textContent = "Player 1 Wins!";
}
else if (player2Roll > player1Roll) {
    document.getElementById("headtext").textContent = "Player 2 Wins!";
}
else {
    document.getElementById("headtext").textContent = "Its a Tie!";
}

setImage(dice1Image,player1Roll);
setImage(dice2Image,player2Roll);

So what’s the process here. Let’s skip the function at the top for now. Step one is to roll two dice. This is done with Math.random, which selects a random value between 0 and 1. Dice have 6 sides, so we multiply this by 6, to get a number between 0 and 6. But technically it’s a number between 0 and 5.999999~ into infinity, not 6. And Math.floor rounds things down, so it’s actually between 0 and 5. So we need to add one.

let player1Roll = Math.floor(Math.random()*6)+1;
let player2Roll = Math.floor(Math.random()*6)+1;

After this is some selectors to pick the the two dice images off the page, so they can be updated to reflect the rolls later.

let dice1Image = document.querySelector("img.img1");
let dice2Image = document.querySelector("img.img2");

Next we get to use a conditional chain to determine the winner and update the h1 tag on the webpage to display the winner, or if it was a tie. I’m not going to repeat that code here again.

Lastly we make two calls to that function I mentioned before, the one at the top of the script, that updates the image for each dice. The function takes the document selector, and the value of each roll as an input. It runs the roll value (1-6) through a selector and then sets the dice image on the HTML document to the appropriate image.

Could this code all be cleaner, probably, but it gets the job done and is easy to follow. There is probably a simpler way to set the images. The image selector could also just look for 0-5 mapped to 1-6 instead of adding 1. But what if I needed this function to do more based on these rolls. Maybe it becomes part of a larger game and deals damage or something. Personally, this is why I prefer code like this, that isn’t perfectly compact, because it becomes functionally more useful down the road.

Also, the game is available to play at this link.

Code Project: Fresh RSS to WordPress Digest

I actually briefly mentioned this project when I write about moving from TinyTinyRSS to FreshRSS. This has become a bit of an evolving and ongoing project however, so I’ve decided to catalogue it in it’s own page. This little script worked out much better than I expected, and I’ve modified it a bit over time, and have ideas to modify it going forward even more. Starting off, the code can be found here in this Github GIST.

I’ve left a bit of commented out code that i might use later for troubleshooting or adding additional features. The general gist of the code, it pulls the last 24 hours worth of news stories I have favorited from my FreshRSS install, then formats them into a digest format and posts it here, in this blog. They get sorted into their own category, you can find them here.

This is basically a thing I’ve seen others do that I’ve wanted to do for a while. It’s also partially just for my reference more than anything, it’s sort of a log of everything I have found interesting on a particular day more than anything. Others may or may not find it interest, which is why I also filter that category out of the home page feed.

Originally, it was just a list of URLs and titles. I realized that it might be useful to have SOME idea what the link was about before clicking it, so I have been playing with the summary as well. My first attempt was a bit dodgy because it actually posted the entire article as the summary. Currently, it just arbitrarily chops it off at a few hundred characters. I want to improve it even farther at some point by pushing it through some summarizing AI and getting an actual proper summary but I have not gotten there yet.

There re a few other things I want to add but I’m not sure they re easily possible. Firstly, I would love to be able to parse some sort of categories into the digest. So say, all the “Video Game” links are together and Music links are together. FreshRSS has categories but they don’t seem to show up in the feed anywhere.

This would also allow me to split these posts between this blog and my other blog, Lameazoid. I do share interesting video games news from FreshRSS, but I mostly don’t share Toy related articles, because it feels a little TOO FAR out there for what I want to post to this blog. If there were a way to have the categories, I could easily have the script split the feed by categories and post a digest to each blog.

I also wish there was a way to add my own notes and commentary occasionally. I don’t think it showed up in the feed either, but TinyTinyRSS had a notes feature. I am not sure if FreshRSS has that as well. I probably should try to at least suggest these features to the creators on GitHub, or maybe get really adventurous and create my own plug-ins for FreshRSS to accomplish these tasks.

Code Project: VLC Portable Playlist to Text Dump

It’s kind of funny how one post can lead to another sometimes.  This one is pretty basic but it also just shows a bit how useful I find knowing my way around computer systems to be.  Yesterday I posted about my little annual music playlists.  And as part of that, I wanted to actually post the playlist. I am pretty sure there is a fairly universal “playlist file type” out there and being open source, I had assumed that VLC on my phone stored the playlists somewhere in playlist files.

That assumption was wrong, it uses a .db file.  A little portable database.  There is an option to dump this file to the root of the phone, presumably for backup purposes, but it’s also useful to just browse it like I am doing here.  The file itself can be opened and browsed with SQL Lite’s DB manager.  It’s standard databases inside for tracks and artists and playlists.

Fortunately, I have had some experience dealing with database queries, so I set about building what was needed tog et the data I wanted.  Pull the Playlist I want, in this case “2023 Best” but I could change that to do any available Playlist.  This gives the tracks by id, but the tracks themselves are stored in a separate table for media.  So that needs joined in.  The media table stores track names, but not artist names, so an additional join is needed to get the artist names.  This complicated things a bit because both the playlist table and artist table have a column “name” so more clarity needed to be added.

The result was this little query that dumps out a basic table of Artist and Song title.

SELECT Artist.name, Media.title 
FROM Playlist
Inner Join playlistmediarelation ON playlist_id=id_playlist
Inner Join Media ON id_media=media_id
Inner Join Artist ON media.artist_id=Artist.id_artist
WHERE Playlist.name = '2023 Best'
ORDER BY Artist.name

Now, I could have done some cute clever trick now to merge the two into a new column and add in a ” – ” between but it was easier to drop it all into a notepad file and do a fine/replace on the weird space character that it stick in between the Artist and track title.

The added bonus here is I can easily use this query again anytime I want to dump a Playlist to text.

Code Project: Automated List From Reddit Comments

This is one of those quick and kind of dirty projects I’ve been meaning to do for a while. Basically, I wanted a script that would scrape all of the top level comments from a Reddit post and push them out to a list. Most commonly, to use on /r/AskReddit style threads like, well, for this example, “What is a song from the 90s that young people should listen to.”

Basically, threads that ask for useful opinions on list. Sometimes it’s lists of websites or something. Often it’s music. The script here is made for music but could be adjusted for any thread. Here is the script, I’ll touch on it a bit in more detail after.

## Create an APP for Secrets here:
## https://www.reddit.com/prefs/apps

import praw

## Thread to scrape goes here, replace the one below
url = "https://www.reddit.com/r/Music/comments/10c4ki0/name_one_90s_song_kids_born_after_2000_should_add/"

## Fill in API Information here
reddit = praw.Reddit(
    client_id="",
    client_secret= "",
    user_agent= "script by u/", # Your Username, not really required though
    redirect_uri= "http://localhost:8080",
)


submission = reddit.submission(url=url)
submission.comments.replace_more(limit=0)
submission.comment_limit = 1

for x in submission.comments:
    with open("output.txt", mode="a", encoding="UTF-8") as file:
        if "-" in x.body:
            file.write(str(x.body)+"\n")
            # print(x.body)

The script uses praw, Python Reddit API Wrapper. A Library made for use in Python and the Reddit API. It requires free keys which can be gotten here: https://www.reddit.com/prefs/apps. Just create an app, the Client ID is a jumble of letters under the name, the secret is labeled. User Agent can be whatever really, but it’s meant to be informative.

The thread URL also needs filled in.

The script then pulls the thread data and pulls the top level comments.

I’m interested in text file lists mostly, though for the sake of music based lists, if I used Spotify, I might combine it with the Spotify Playlist maker from my 100 Days of Python course. Like I said before though, this script is made for pulling music suggestions, with this but of code:

        if "-" in x.body:
            file.write(str(x.body)+"\n")
            # print(x.body)

It’s simple, but if the comment contains a dash, as in “Taylor Swift – Shake it Off” or “ACDC – Back in Black”, it writes it to the file. Otherwise it discards it. There is a chance it means discarding some submissions, but this isn’t precision work so I’m OK with that to filter out the chaff. If I were looking for URLs or something, I might look for “http” in the comment. I could also eliminate the “if” statement and just have it write all the comments to a file.