_ _ | |_ ___ __| |____ ___ _ _ | __/ _ \/ _` |_ / / _ \ | | | | || __/ (_| |/ / | __/ |_| | \__\___|\__,_/___(_)___|\__,_|
The following C program prints a random 4-character alphanumeric code:
//
// random_string.c - Written by Ted Burke - 18-Apr-2023
// Prints a random 4-character alphanumeric string
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char **argv)
{
int m, n;
srand(clock());
for (m=0 ; m<4 ; ++m)
{
// Generate random alphanumeric character
// characters 0-9 are ascii 48-57
// characters A-Z are ascii 65-90
// characters a-z are ascii 97-122
n = (rand() % 62) + 48;
if (n > 57) n += 7;
if (n > 90) n += 6;
printf("%c", n);
}
return 0;
}
With the aid of a Vim macro, I ran the above program once for each line of a text file containing a list of student numbers. I then edited the file further to create Bash script that generated a set of video files using the program below (the program creates one video file each time it runs).
//
// create_video.c - Written by Ted Burke - 18-Apr-2023
//
// Example command to run this program for a student C12345678 with code word "x7fh":
//
// ./create_video C12345678 x7fh
//
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#define W 640
#define H 480
#define L 256
uint8_t p[2][H*W*3] = {0};
int main(int argc, char** argv)
{
const char *student = argv[1]; // student number
const char *codeword = argv[2]; // 4-character code word
int x, y, a, b, i;
int bits[40];
// Parse bits from 4 character code supplied as argv[2]
for (a=0 ; a<4 ; ++a)
{
char c = codeword[a];
bits[a*10] = 1; // start bit
for (b=0 ; b<8 ; ++b) bits[a*10+1+b] = (c >> b) & 1u; // 8 data bits
bits[a*10+9] = 0; // stop bit
}
for (b=0 ; b<40 ; ++b)
{
if (b%10 == 0) printf(" ");
printf("%d", bits[b]);
}
printf("\n");
// Render "zero" frame
fprintf(stderr, "Creating zero frame\n");
char command[1024];
sprintf(command, "convert -background black -fill white -size 640x480 -pointsize 64 -gravity South -depth 24 label:%s gray:temp.bin", argv[1]);
system(command);
FILE *f = fopen("temp.bin", "rb");
fread(&p[0][0], H*W*3, 1, f);
fclose(f);
// Render "one" frame
fprintf(stderr, "Creating one frame\n");
memcpy(&p[1][0], &p[0][0], H*W*3);
for (y=H/2-L/2 ; y<H/2+L/2 ; ++y) for (x=W/2-L/2 ; x<W/2+L/2 ; ++x)
{
i = 3*(y*W+x);
p[1][i] = 255;
p[1][++i] = 255;
p[1][++i] = 255;
}
// Write frames to video by piping them to ffmpeg
fprintf(stderr, "Writing frames to video\n");
errno = 0;
sprintf(command, "ffmpeg -y -f rawvideo -vcodec rawvideo -pix_fmt rgb24 -s %dx%d -r 30 -i - -f mp4 -q:v 5 -an -vcodec mpeg4 %s.mp4", W, H, argv[1]);
fprintf(stderr, "Command: %s\n", command);
FILE *pout = popen(command, "w");
//FILE *pout = popen("ffmpeg -y -f rawvideo -vcodec rawvideo -pix_fmt rgb24 -s 640x480 -r 30 -i - -f mp4 -q:v 5 -an -vcodec mpeg4 C12345678.mp4", "w");
if (!pout)
{
fprintf(stderr, "Error opening pipe to ffmpeg. errno=%d\n", errno);
}
// Write the equivalent of 20 zero bits as preamble before transmission
fprintf(stderr, "Writing preamble zero frames\n");
for (b=0 ; b<20 ; ++b) for (i=0 ; i<6 ; ++i) fwrite(&p[0][0], W*H*3, 1, pout);
// Write frames for the 40 bits in the transmission (n frames per bit)
fprintf(stderr, "Writing data frames\n");
for (b=0 ; b<40 ; ++b)
{
// Write whichever frame n times to ffmpeg via pipe
for (i=0 ; i<6 ; ++i) fwrite(&p[bits[b]][0], W*H*3, 1, pout);
}
// Write the equivalent of 20 zero bits as padding after transmission
fprintf(stderr, "Writing padding zero frames\n");
for (b=0 ; b<20 ; ++b) for (i=0 ; i<6 ; ++i) fwrite(&p[0][0], W*H*3, 1, pout);
// Flush and close pipe to ffmpeg
fprintf(stderr, "Flushing and closing pipe\n");
fflush(pout);
pclose(pout);
return 0;
}
To create all videos, I created a Bash script (video_script.sh) with a line for each student in the following format:
#!/bin/bash
./create_video C12345678 Demo
./create_video C87654321 abcd
etc etc
To make the Bash script executable and then run it:
chmod +x video_script.sh
./video_script
To convert a video from MP4 to a browser-friendly .webm format:
ffmpeg -i C12345678.mp4 -f webm -vcodec libvpx-vp9 -vb 1024k test.webm
To do that automatically to every mp4 file in the current diirectory, use the following bash script:
#!/bin/bash
for file in *.mp4; do
ffmpeg -i "$file" -f webm -vcodec libvpx-vp9 -vb 1024k "${file%.mp4}.webm"
done
This is the PHP code for the online validator (validator.php):
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Array containing code words
$codes = [
"C12345678" => "Demo",
"C87654321" => "abcd",
"C12341234" => "bl4h",
];
// Default strings
$correct_code = 0;
$student_id = "";
$code_word = "";
// Max length for each submitted string
$max_length = 100;
// If form was submitted, update strings
if ( $_SERVER['REQUEST_METHOD'] === 'POST' &&
isset($_POST['student_id']) && isset($_POST['code_word']))
{
// Retrieve student_id and code_word from POST request parameters
// Limit the length in characters of each time to $max_length (set above)
$student_id = strtoupper(substr(trim($_POST['student_id']), 0, $max_length));
$code_word = substr(trim($_POST['code_word']), 0, $max_length);
if (array_key_exists($student_id, $codes))
{
if ($codes[$student_id] == $code_word && $code_word != "")
{
$correct_code = 1;
}
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../jotz.css">
<title>EEPP2 Binary Signal Detective validator</title>
</head>
<body>
<pre class="asciiart">
____ _ ____ _ _
| __ )(_)_ __ __ _ _ __ _ _ / ___|(_) __ _ _ __ __ _| |
| _ \| | '_ \ / _` | '__| | | | \___ \| |/ _` | '_ \ / _` | |
| |_) | | | | | (_| | | | |_| | ___) | | (_| | | | | (_| | |
|____/|_|_| |_|\__,_|_| \__, | |____/|_|\__, |_| |_|\__,_|_|
|___/ |___/
____ _ _ _
| _ \ ___| |_ ___ ___| |_(_)_ _____
| | | |/ _ \ __/ _ \/ __| __| \ \ / / _ \
| |_| | __/ || __/ (__| |_| |\ V / __/
|____/ \___|\__\___|\___|\__|_| \_/ \___|
</pre>
<h1>Binary Signal Detective Validator</h1>
<?php
$video_filename = "$student_id.webm";
if (file_exists($video_filename))
{
echo "<a href=\"$video_filename\">$video_filename</a><br><br>";
}
?>
<form action="validator.php" id="validator_form" method="post">
<label for="student_id">Student number:</label><br>
<input type="text" id="student_id" name="student_id" value="<?php echo($student_id) ?>"><br>
<label for="lname">4-character code word:</label><br>
<input type="text" id="code_word" name="code_word" value="<?php echo($code_word) ?>"><br><br>
<input type="submit" value="Validate code word / Get video link">
</form>
<div style="font-size:200%;">
<?php
if ($correct_code)
{
echo "<br>Congratulations $student_id,<br>\"$code_word\" is the correct code! 🎉🎉🎉<br>";
}
else if ($code_word != "" && $student_id != "")
{
echo "Sorry $student_id,<br>\"$code_word\" is not the correct code. 😢<br>";
}
echo "<br>";
?>
</div>
<?php
if (file_exists($video_filename))
{
echo "<video controls autoplay loop>";
echo "<source src=\"$video_filename\" type=\"video/webm\">";
echo "Your browser does not support the video tag.";
echo "</video>";
}
?>
</body>
</html>