Compare commits

...

2 Commits
mojo ... master

Author SHA1 Message Date
52f9d258d4 Update master README to contain info on the different branches
Signed-off-by: peteyboy <peteyboy@noreply.localhost>
2022-04-20 07:16:43 +00:00
a38abfdf7e Updated master branch to contain the CGI::Tiny version with mocked
PATH_INFO, but supporting a 'neutral' environment (not SDF), and playing
out of /cgi-bin.
2022-04-20 06:20:34 +00:00
2 changed files with 101 additions and 151 deletions

View File

@ -2,6 +2,12 @@
one-page app that turns wordle shares into standard file format used in the Conway's Game of Life community and sets it up for running in embedded Lifeviewer on the same page one-page app that turns wordle shares into standard file format used in the Conway's Game of Life community and sets it up for running in embedded Lifeviewer on the same page
## Project Branches
There are 3 branches to this project. There is just one CGI file and a version of the README.md in each one. Use the one that works for you. If at SDF, use the sdf branch. Otherwise master or mojo branches will work:
* *sdf* is the original branch, a CGI set up to run on SDF.org. I had to abandon using Mojolicious Lite, but found a nice way to do it using CGI:Tiny and the Mojo Templates. This version also uses a path_info URL parameter to manage routing, and mocks path_info, since is doesn't work on SDF's nginx web server setup.
* *master* is a branch made to be mostly the same as the SDF branch, using CGI::Tiny, but with more normal paths and not trying to pick out a separate user-level perl library. It still uses the path_info parameter, which actuall works pretty well for the simple case, I put it to, at least.
* *mojo* is a rewrite of the CGI part of the script using Mojolicious Lite and expecting that path_info is honored for CGI scripts. It uses routing based off the path_info (it's like *magic*) instead of a url parameter. I got this to run very nice with a handmade Mojolicous Daemon web server script, using the Mojolicous CGI plugin. It would have been so much less sweat to do this from the get-go, but I learned a lot banging my head against the wall, I guess.
## Dependencies ## Dependencies
This app is not at all packaged. You'll have to make sure all the perl modules you need are installed. If you are on a community unix server with just user rights (like, say SDF), you may need to ask an admin to install for you, or alternately, you can make a personal perl library in your user space. This app is not at all packaged. You'll have to make sure all the perl modules you need are installed. If you are on a community unix server with just user rights (like, say SDF), you may need to ask an admin to install for you, or alternately, you can make a personal perl library in your user space.

View File

@ -1,24 +1,25 @@
#!/usr/pkg/bin/perl #!/usr/bin/perl
#Above is the particular location for system binaries in SDF's metaarray, not the usual spot
use strict; use strict;
use warnings; use warnings;
use utf8; use utf8;
#add my user perl library path, this is particular to each person's setup #add my user perl library path, this is particular to each person's setup
use lib qw( /usr/pkg/lib/perl5/5.24.0 /meta/p/peteyboy/perl5/lib/perl5 ); #use lib qw( /usr/pkg/lib/perl5/5.24.0 /meta/p/peteyboy/perl5/lib/perl5 );
#make request for all of the following #make request for all of the following
use CGI::Tiny; use CGI::Tiny;
use Mojo::Template; use Mojo::Template;
use Mojo::Loader 'data_section'; use Mojo::Loader 'data_section';
#use Routes::Tiny; #don't even need
use Readonly; use Readonly;
use List::Util qw(first); #use List::Util qw(first);
use URI;
use experimental 'smartmatch';
#=== #===
# MAKE SURE ORIGIN PAGE MATCHES FILENAME (especially if you are testing changes)! # MAKE SURE ORIGIN PAGE MATCHES FILENAME (especially if you are testing changes)!
# #
#=== #===
my $ORIGIN_PAGE = "/wordle-life.cgi"; my $ORIGIN_PAGE = "/cgi-bin/wordle-life.cgi";
my $defaulttext = "Paste your wordle share here (replace this text)"; my $defaulttext = "Paste your wordle share here (replace this text)";
my $PATH_PARAM = "path_info";
my $WORDLE_INPUT_PARAM = "wordle-result"; my $WORDLE_INPUT_PARAM = "wordle-result";
my $SHARENOTE_PARAM = "share-note"; my $SHARENOTE_PARAM = "share-note";
@ -26,7 +27,6 @@ use List::Util qw(first);
#error handler from the CGI:Tiny cookbook #error handler from the CGI:Tiny cookbook
my $cgi = $_; my $cgi = $_;
$cgi->set_error_handler(sub { $cgi->set_error_handler(sub {
my ($cgi, $error, $rendered) = @_; my ($cgi, $error, $rendered) = @_;
warn $error; warn $error;
@ -46,6 +46,8 @@ use List::Util qw(first);
my $rle = ""; my $rle = "";
my $isshare = 0; #flag for sharing, default false my $isshare = 0; #flag for sharing, default false
my $sharenote = ""; #a note someone can tack onto their share my $sharenote = ""; #a note someone can tack onto their share
my $navigate = 0; #flag to go to different page, default false
#Simple switch: make a one page app, and always go back to the same page. #Simple switch: make a one page app, and always go back to the same page.
#GET or HEAD loads the page blank, POST runs the Life file maker #GET or HEAD loads the page blank, POST runs the Life file maker
@ -53,8 +55,13 @@ use List::Util qw(first);
$wordle = $defaulttext; $wordle = $defaulttext;
} elsif ($method eq 'GET') { } elsif ($method eq 'GET') {
#TODO: if there are query parameters put them in $wordle and activate share page logic #Check path_info to see if we are navigating (ignoring sharing query params if there?)
if (first { $_ eq $WORDLE_INPUT_PARAM } @{$cgi->query_param_names} ){ #if (first { $_ eq $PATH_PARAM } @{$cgi->query_param_names} ){
if ( $PATH_PARAM ~~ @{$cgi->query_param_names} ){
$navigate = mock_path_info($cgi->query_param($PATH_PARAM)); #true and populated
}
#if there are sharing query parameters put them in $wordle and activate share page logic
elsif ($WORDLE_INPUT_PARAM ~~ @{$cgi->query_param_names} ){
$wordle = $cgi->query_param($WORDLE_INPUT_PARAM); $wordle = $cgi->query_param($WORDLE_INPUT_PARAM);
$isshare = 1; #true $isshare = 1; #true
$sharenote = $cgi->query_param($SHARENOTE_PARAM); $sharenote = $cgi->query_param($SHARENOTE_PARAM);
@ -73,9 +80,6 @@ use List::Util qw(first);
}else{ }else{
$rle = generate_rle($wordle); $rle = generate_rle($wordle);
} }
#$sharequery= "?" . $WORDLE_INPUT_PARAM . "=" . url_escape($rle);
#$template = data_section __PACKAGE__, 'sharepage.html.ep';
#$output = $mt->render($template, { ORIGIN_PAGE =>$ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle });
} }
#$output = $mt->render($template, { WORDLE_INPUT_PARAM => $WORDLE_INPUT_PARAM, ORIGIN_PAGE => $ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle, sharenote => $sharenote }); #$output = $mt->render($template, { WORDLE_INPUT_PARAM => $WORDLE_INPUT_PARAM, ORIGIN_PAGE => $ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle, sharenote => $sharenote });
@ -84,22 +88,36 @@ use List::Util qw(first);
exit; exit;
} }
die "Invalid wordle parameter" unless length $wordle; #die "Invalid wordle parameter" unless length $wordle;
#Load template from DATA section and output #Load template from DATA section and output
#my $mt = Mojo::Template->new(auto_escape => 1, vars => 1); #my $mt = Mojo::Template->new(auto_escape => 1, vars => 1);
my $mt = Mojo::Template->new(vars => 1); my $mt = Mojo::Template->new(vars => 1);
my $template = data_section __PACKAGE__, 'index.html.ep'; my $template;
my $output = $mt->render($template, { WORDLE_INPUT_PARAM => $WORDLE_INPUT_PARAM, ORIGIN_PAGE => $ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle, isshare => $isshare, sharenote => $sharenote }); my $output;
#my $output = $mt->render($template, { ORIGIN_PAGE =>$ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle });
#my $output = $mt->render($template, {wordle => $wordle});
#TODO: this is ugly; clean up
if ($method eq 'GET' && $navigate ) {
my $template_name = template_from_path_info ($navigate);
#TODO: Check against a list of valid templates!
#if ( grep ( /^$template_name$/, ('index.html.ep', 'about.html.ep') )) {
if ( $template_name ~~ ['index.html.ep', 'about.html.ep'] ) {
$template = data_section __PACKAGE__, $template_name;
$output = $mt->render($template, { ORIGIN_PAGE => $ORIGIN_PAGE }); #this isn't general purpose, what template needs what variables?
}else{ #TODO: fix so as not to need copied code from the else below?
$template = data_section __PACKAGE__, 'index.html.ep';
$output = $mt->render($template, { WORDLE_INPUT_PARAM => $WORDLE_INPUT_PARAM, ORIGIN_PAGE => $ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle, isshare => $isshare, sharenote => $sharenote });
}
}else{
$template = data_section __PACKAGE__, 'index.html.ep';
$output = $mt->render($template, { WORDLE_INPUT_PARAM => $WORDLE_INPUT_PARAM, ORIGIN_PAGE => $ORIGIN_PAGE, defaulttext => $defaulttext, wordle => $wordle, rle => $rle, isshare => $isshare, sharenote => $sharenote });
}
$cgi->render(html => $output ); $cgi->render(html => $output );
}; };
#Try to Generate the RLE. Makes a lot of assumptions #Try to Generate the RLE. Makes a lot of assumptions
sub generate_rle { sub generate_rle (\$) {
my $headline = ""; my $headline = "";
my $rleline = ""; my $rleline = "";
@ -132,6 +150,7 @@ sub generate_rle {
$myline =~ s/:green_square:/o/g; $myline =~ s/:green_square:/o/g;
$myline =~ s/:blue_square:/o/g; #HC equiv yellow $myline =~ s/:blue_square:/o/g; #HC equiv yellow
$myline =~ s/:orange_square:/o/g; #HC equiv green $myline =~ s/:orange_square:/o/g; #HC equiv green
$myline =~ s/:red_square:/o/g; #wordum red fails
$myline =~ s/:[a-z_]*square:/b/g; $myline =~ s/:[a-z_]*square:/b/g;
@ -140,6 +159,7 @@ sub generate_rle {
$myline =~ s/\N{U+1f7e9}/o/g; #green hit $myline =~ s/\N{U+1f7e9}/o/g; #green hit
$myline =~ s/\N{U+1F7E6}/o/g; #blue $myline =~ s/\N{U+1F7E6}/o/g; #blue
$myline =~ s/\N{U+1F7E7}/o/g; #orange $myline =~ s/\N{U+1F7E7}/o/g; #orange
$myline =~ s/\N{U+1F7E5}/o/g; #red
$myline =~ s/\N{U+2B1B}/b/g; #black $myline =~ s/\N{U+2B1B}/b/g; #black
@ -152,6 +172,7 @@ sub generate_rle {
$myline =~ s/green_square/o/g; $myline =~ s/green_square/o/g;
$myline =~ s/blue_square/o/g; $myline =~ s/blue_square/o/g;
$myline =~ s/orange_square/o/g; $myline =~ s/orange_square/o/g;
$myline =~ s/red_square/o/g; #wordum red fails
@ -168,6 +189,29 @@ sub generate_rle {
} }
#Because SDF's nginx config is broken, we have to use query params to *navigate*
sub mock_path_info {
my $uri = URI->new (shift);
return $uri->path;
}
sub template_from_path_info {
my $template='';
my $path = shift;
if ($path =~ /^\//){
$template = $path;
$template =~ s/^.//;
$template =~ tr/\//./;
$template = $template . ".html.ep";
}
return $template;
}
__DATA__ __DATA__
@@ index.html.ep @@ index.html.ep
<html> <html>
@ -178,22 +222,23 @@ __DATA__
<style> <style>
.lv-rle{ .lv-rle{
min-height:200px; min-height:140px;
} }
</style> </style>
<meta name="LifeViewer" content="viewer textarea"> <!--required tag--> <meta name="LifeViewer" content="viewer textarea"> <!--required tag-->
<script src="lv-plugin.js"></script> <script src="/lv-plugin.js"></script>
</head> </head>
<body><h1>Wordle->Life</h1> <body><h1>Wordle->Life</h1>
<p align= right> <a href="<%=$ORIGIN_PAGE%>?path_info=/about">about</a>
% if ($isshare) { % if ($isshare) {
<span> <span>
<h3> Hey, someone wants to share their Wordle->Life score with you!</h3> <h3> Hey, someone wants to share their Wordle->Life score with you!</h3>
%if ($sharenote){ %if ($sharenote){
<p>They said: <em><%= $sharenote =%></em></p> <p>They said:<em><%= $sharenote %></em></p>
%}; %};
<p><strong>Skip to step 2 of the instructions below and see the shared wordle-life happen!</strong></p> <p><strong>Skip to step 2 of the instructions below and see the shared wordle-life happen!</strong></p>
</span> </span>
@ -230,15 +275,16 @@ __DATA__
<!--viewer container--> <!--viewer container-->
<div class="viewer" class="flow"> <div class="viewer" class="flow">
<label for="wordle"> <label for="wordle">
<p>If the conversion is successful, you should see your Wordle converted to a Run Length Encoded Conway Life file (RLE) in this box:</p> <p>If the conversion is successful, you should see your Wordle converted to a Run Length Encoded Conway Life file in this box:</p>
</label> </label>
<label for="wordle">Converted RLE:</label>
<textarea id="life" name="life-file" rows="12" cols="50" style="vertical-align: middle" class="lv-rle" class="flow"> <textarea id="life" name="life-file" rows="9" cols="50" style="vertical-align: middle" class="lv-rle" class="flow">
<%== $rle %></textarea> <%== $rle %></textarea>
<p>If the RLE is correct, it should be loaded in the Life Viewer, and so you are ready to go!</p> <p>If the RLE is correct, it should be loaded in the Life Viewer, and so you are ready to go!</p>
<ul> <ul>
<li><p>For best results with the Life Viewer, you may adjust the default Zoom and the playback speed, then press the Play button:</p> <li><p>For best results with the Life Viewer, you may adjust the default Zoom and the playback speed, then press the Play button:</p>
<canvas height=400 width=450></canvas></li> <canvas height=400 width=400></canvas></li>
<li><p>Press "[Pause]" when it seems stable. </p> <li><p>Press "[Pause]" when it seems stable. </p>
</li> </li>
</ul> </ul>
@ -258,15 +304,16 @@ __DATA__
% if ($rle ne ""){ % if ($rle ne ""){
<span> <span>
<p><strong> Share your wordle-life!</strong></p>
<p> You can copy/paste the RLE into your favorite social media post or email</p>
<p><em>OR</em></p>
<p> Click this button to go to a share page where you can copy/paste the url to someone</p>
<form id="life-share" name="life-share" action="<%== $ORIGIN_PAGE %>" method="GET" class="flow"> <form id="life-share" name="life-share" action="<%== $ORIGIN_PAGE %>" method="GET" class="flow">
<p><strong> Share your wordle-life!</strong>
<p> You can copy/paste the RLE into your favorite social media post or email
<br><em>OR</em><br>
Click this button to go to a share page where you can copy/paste the URL to someone:</p>
<textarea id="share-rle" name="<%= $WORDLE_INPUT_PARAM %>" rows="9" cols="50" style="display:none;"> <textarea id="share-rle" name="<%= $WORDLE_INPUT_PARAM %>" rows="9" cols="50" style="display:none;">
<%=$rle %></textarea> <%=$rle %>
<input id="share-note" type="text" name="share-note" placeholder="Include a note, if you'd like" style="vertical-align: bottom"> </textarea>
<input type="submit" value="Go to sharing page"> <input type="submit" value="Go to sharing page">
<input id="share-note" type="text" name="share-note" placeholder="Add a note if you'd like" style="vertical-align: bottom">
</form> </form>
% }; % };
</span> </span>
@ -316,143 +363,40 @@ GRID
<p> <p>
<p> @@ about.html.ep
<p>
<hr 100%>
<em>Disclaimer: I made this! People and/or corporations may own their marks or copyrights, etc, on words mentioned on this page I don't claim to</em>
<p>
Questions, kudos or comments, mail me @sdf.org
<p>
Thanks to the community at <a href="https://conwaylife.com">conwaylife.com</a>, and the friendly folks in the forums there,
and for their <a href="https://conwaylife.com/wiki/Tutorials/LifeViewer_JavaScript_plug-in">Javascript Life Viewer</a>, which I use here.
</p>
<p>
Thanks to <a href="https://github.com/hankchizljaw/some-nice-basic-css"> hankchizljaw</a> for making his basic css publicly available
</p>
<p> Made in February 2022</p>
<p>
<center>
Hosted by SDF.org
<p><a href="https://sdf.org"><img src=https://mab.sdf.org/sdfbanner.png alt="SDF.org"></a>
</center>
</body></html>
@@ viewer.html.ep
<html> <html>
<head> <head>
<title>Play Conway's Life with your Wordle Score</title> <title>About Wordle-Life</title>
<link rel="stylesheet" href="https://peteyboy.freeshell.org/air.css"> <link rel="stylesheet" href="https://unpkg.com/some-nice-basic-css/global.css" />
<meta name="LifeViewer" content="viewer textarea"> <!--required tag--> <!-- <link rel="stylesheet" href="https://peteyboy.freeshell.org/air.css"> -->
<script src="lv-plugin.js"></script>
</head> </head>
<body><h1>Wordle->Life</h1> <body><h1>Wordle->Life</h1>
% my $home_path= "$ORIGIN_PAGE";
<p><em>Play your Wordle Share score in <a href=https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life> Conway's Life!</a></em></p> % my $current_path = "$home_path?path_info=/about";
<p>
<p> Hey, nerds, isn't it funny how the Wordle Scores can look like a glider in that old computer programming exercise, Conway's Life?</p> <img src="https://conwaylife.com/w/images/e/e2/Lwss.png" alt="Glider image from Conwaylife.org, it looks like an 8-bit staple gun" align= float />
<ol>
<li>
<p> Paste your wordle share below and submit to convert it to a Conway's Life file so you can run it.</p>
<p> To learn more about Conway's Life, read <a href=https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life> this</a>
</li>
<p> <p>
<p> This is an about page. </p>
<p> Click <a href=<%== $home_path %> >here</a> to go Home </p>
<p> Click <a href=<%== $current_path %> >here</a> to stay put </p>
<form id="wordle-form" name="wordle-form" action="<%== $ORIGIN_PAGE =%>" method="POST" class="flow">
<label for="wordle">Wordle Share Chart:</label>
<textarea id="wordle" name="wordle-result" rows="9" cols="50" placeholder="<%== $defaulttext =%>" style="vertical-align: middle; border:none;">
<%== $wordle %>
</textarea>
</p>
<br>
<li>
<p>Click "Submit" and and RLE format file for Conway's Game of Life will appear below.</p>
<input type="submit" value="Submit">
</li>
</ol>
<label for="life">Your wordle as Conway Life RLE file:</label>
<textarea id="life" name="Life file" rows="9" cols="50" style="vertical-align: middle; border:none;">
<%== $rle %>
</textarea>
<!--viewer container-->
<div class="viewer" class="flow">
<div class="lv-buttons">
<button onclick="document.getElementById('life').innerHTML=''">Clear</button>
<button onclick="updateMe(this)">Show in Viewer</button>
<!--the element that calls updateMe must be in the viewer container-->
</div>
<canvas height=400 width=600></canvas>
</div>
<!--end viewer container-->
</form>
</div>
<p> if there is extra text or lines in your paste, you might not get a valid file here, so look and make sure it looks like a proper RLE file, for example:
<p>
<pre code>
#C Wordle 235 3/6
x = 5,y = 3
boobo$bobbo$ooooo$
</pre code>
<p>For details about the Life RLE file format above, read <a href=https://conwaylife.com/wiki/Run_Length_Encoded>this</a>.
<p>
<strong>Next steps:</strong>
<!-- not embedded -->
<ol>
<li>copy the contents of the Conway Life box above
<li>go to a Conway's Life site, such as <a href= https://copy.sh/life/> this one at copy.sh</a> or <a href="https://lazyslug.com/lifeviewer/">this one at lazyslug.com</a> and load and run your file.</li>
<ol>
<li> specifically for the one at copy.sh:</li>
<li> Press the [Import] button at the top</li>
<li> paste in your Life file contents in the box and press [Import]</li>
<li> It will put up a box telling you it loaded your Wordle, press [OK]</li>
<li> Press the [Run] button and watch your Wordle score play LIFE!</li>
</ol>
</ol>
<p> This should work with the share/copy button in wordle, or copy/pasting your friends' wordles out of Discord or wherever as well. See whose Wordle Score looks coolest!
<p>
<p>
<p> <p>
<hr 100%> <hr 100%>
<em>Disclaimer: I made this! People and/or corporations may own their marks or copyrights, etc, on words mentioned on this page I don't claim to</em> <em>Disclaimer: I made this! People and/or corporations may own their marks or copyrights, etc, on words mentioned on this page I don't claim to</em>
<p>
Questions, kudos or comments, mail me @sdf.org
<p> <p>
Thanks to <a href="https://github.com/hankchizljaw/some-nice-basic-css"> hankchizljaw</a> for making his basic css publicly available Thanks to <a href="https://github.com/hankchizljaw/some-nice-basic-css"> hankchizljaw</a> for making his basic css publicly available
<p> Made in February 2022 <p> Made in February 2022
<p> <p>
<center> <center>
Hosted by SDF.org Hosted by Bisect Hosting
<p><a href="https://sdf.org"><img src=https://mab.sdf.org/sdfbanner.png alt="SDF.org"></a> <p><a href="https://www.bisecthosting.com"><img src=https://www.bisecthosting.com/images/logos/logo.svg alt="bisecthosting.com" height= 10% width=auto></a>
</center> </center>
</body></html> </body></html>