Peter’s blog ✴ Week 103 ✴ 8 March 2021

THE WEEKLY CHALLENGE
Zodiac and music

The Perl Camel

Task 2

What’s playing?

You have created a playlist containing several audio tracks. It started playing at a known time in the past $T and continuously repeats when it finishes. There are no gaps between the tracks or between successive plays of the playlist.

You are given a list of the durations in milliseconds and titles of the tracks.

You are given the time (as seconds since 00:00 on 01.01.1970) when the streamer started and a CSV file containing the tracks in the playlist with one line per track containing the length in milliseconds and the title.

Write a script to show which track is playing now.

(Summarised from the original description)

Examples


Example 1
Streamer started at 1606134123 ms after the epoch.
Track list as shown in the DATA of the source listing.

Analysis

This is a simple enough challenge, but it requires a lot of conversions to and fro between seconds since the epoch and conventionally expressed dates and times.

The code:

  • Calculates how long ago, in seconds, the stream started.
  • Calculates the length in seconds of the playlist.
  • From that, calculates the number of complete iterations of the playlist have occurred, and the time since the last iteration completed.
  • Finds out how far along the current iteration has got, and thus which track is playing right now.

I am sorry that the 'Try it' feature is currently working very slowly or not at all owing to some issue with my web hosting provider.

Try it 

Try running the script now:

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2021-03-08
use utf8;     # Week 103 - task 2 - What's playing?
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Time::Local;
use Encode;

whats_playing();

sub whats_playing {

    my ($current, $d, $list_length, $ms, $start, $t, $this_play, $times, %d, @pd, @t, 
        @track, @track_length);
    
    # initialise
    $t = <DATA>;
    
    # find when stream started
    $t = int($t);
    @t = localtime($t);
    $start = qq[Streaming started on ] . sprintf('%02d.%02d.%04d at %02d:%02d:%02d',
        $t[3], $t[4] + 1, $t[5] + 1900, $t[2], $t[1], $t[0]);

    # find length of one play of list
    $list_length = 0;
    while ($d = <DATA>) {
        $d =~ m|(\d+),"(.*)"|;
        push @track_length, $1 / 1000;
        push @track, $2;
        $list_length += $1 / 1000;  
    }
    $list_length = int($list_length);
    $pd[1] = int($list_length / 60);
    $pd[0] = $list_length - $pd[1] * 60;
    $pd[2] = int($pd[1] / 60);
    $pd[1] -= $pd[2] * 60;
    
    # find how often list has been played
    $times = int(($^T - $t) / $list_length);
    $this_play = ($^T - $t) - ($times * $list_length);
        
    # and find where we are in this play
    for $t (0 .. $#track) {
        if ($this_play < $track_length[$t]) {
            say qq[Input:  $start];
            say qq[        Playlist length is: ] . sprintf('%d:%02d:%02d', $pd[2], $pd[1], $pd[0]);
            say qq[Output: Playlist has completed: $times times];
            say qq[        Playing now: $track[$t]];
            return;
        }
        $this_play -= $track_length[$t];
    }
}

__DATA__
1606134123
1709363,"Les Miserables Episode 1: The Bishop"
1723781,"Les Miserables Episode 2: Javert"
1723781,"Les Miserables Episode 3: The Trial"
1678356,"Les Miserables Episode 4: Cosette"
1646043,"Les Miserables Episode 5: The Grave"
1714640,"Les Miserables Episode 6: The Barricade"
1714640,"Les Miserables Episode 7: Conclusion"

38 lines of code
Completed after the closing date and not submitted to GitHub

Output from script


Input:  Streaming started on 23.11.2020 at 12:22:03
        Playlist length is: 3:18:30
Output: Playlist has completed: 14364 times
        Playing now: Les Miserables Episode 2: Javert 

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain