|
#!/usr/bin/env bash |
|
# Inspired from [flash.sh](https://github.com/tallguyjenks/fla.sh) |
|
# See original license further down |
|
# |
|
# Copyright © 2024, Lucien Grondin (grondilu on github) |
|
# |
|
# Permission is hereby granted, free of charge, to any person obtaining a copy |
|
# of this software and associated documentation files (the “Software”), to deal |
|
# in the Software without restriction, including without limitation the rights |
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
# copies of the Software, and to permit persons to whom the Software is |
|
# furnished to do so, subject to the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be included in |
|
# all copies or substantial portions of the Software. |
|
|
|
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
# AUTHORS OR COPYRIGHT HOLDERS X BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
# SOFTWARE. |
|
# |
|
# Original license: |
|
# |
|
## MIT License |
|
## |
|
## Copyright (c) 2020 Bryan Jenks |
|
## |
|
## Permission is hereby granted, free of charge, to any person obtaining a copy |
|
## of this software and associated documentation files (the "Software"), to deal |
|
## in the Software without restriction, including without limitation the rights |
|
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
## copies of the Software, and to permit persons to whom the Software is |
|
## furnished to do so, subject to the following conditions: |
|
## |
|
## The above copyright notice and this permission notice shall be included in all |
|
## copies or substantial portions of the Software. |
|
## |
|
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
## SOFTWARE. |
|
|
|
set -u |
|
|
|
declare -r ALPHA=10 |
|
declare -ri TIME_SCALE=3600*24*365 |
|
|
|
declare -ra DECK=( |
|
"History:When was the declaration of independence signed?:1776:0" |
|
"Math:What is the square root of 4?:2:4" |
|
"Science:What is the charge on a proton?:Positive 1:2" |
|
"Philosophy:What was Socrates known as?:The Gadfly of Athens:0" |
|
"Programming:What is the typical starting index of an array?:0:5" |
|
"History:What did Abraham Lincoln typically keep in his hat?:Mail:0" |
|
"Math:What is the value of PI to 2 decimal places?:3.14:4" |
|
"Science:What is the charge on an electron?:Negative 1:3" |
|
"Programming:What does OOP stand for?:Object Oriented Programming:2" |
|
"History:What did Socrates drink to commit suicide?:Hemlock Tea:2" |
|
"Math:What is the general equation for the slope of a line?:y=mx+b:4" |
|
"Science:What is the charge on a neutron?:Neutral:1" |
|
"Programming:What is Vim?:God's Text Editor:999" |
|
"History:What were the British known by during the American Revolution?:The Redcoats:1" |
|
"Math:What is the value of this equation - log10(100)?:2:0" |
|
"Science:What are protons and neutrons made of?:quarks:5" |
|
"Programming:What does RAM stand for?:Random Access Memory:1" |
|
"History:What was the year 2000 also known as?:Y2K:0" |
|
"Math:What is the formula for the mean?:Sum/count:4" |
|
"Science:What is cold?:The absence of heat:3" |
|
"Programming:What languages are the worst?:Proprietary:999" |
|
"History:When did man land on the moon?:1969:4" |
|
"Math:10^3=?:1000:1" |
|
"Science:The _____ ______ Project mapped all of man's genes.:Human Genome:3" |
|
"Programming:What is the best computer to program on?:Thinkpad:999" |
|
"History:When was fla.sh created?:April 2020:999" |
|
"Math:What do you call a number only divisible by itself and 1?:Prime:0" |
|
"Science:What is the distance between the Earth and Sol called?:An Astronomical Unit (AU):1" |
|
"Programming:What is the best operating system?:Arch, because BTW i run Arch:999" |
|
) |
|
|
|
declare -a LOG=() |
|
|
|
center() { |
|
local line="$1" |
|
echo "$line" | |
|
sed $'s/\e\[[0-9;]*m//g' | |
|
{ |
|
read -r |
|
echo -e "\e[$(( (${COLUMNS:-$(tput cols)}-${#REPLY})/2 + 1))G$line" |
|
} |
|
} |
|
|
|
softmax() { |
|
local alpha="${1:-1.0}" |
|
local -i limit=50 |
|
awk -v alpha="$alpha" -v limit=$limit -e '{ |
|
x = alpha*$1; |
|
sum += e[$2] = exp(x<-limit ? -limit : (x > limit ? limit : x)) |
|
} |
|
END { for (i in e) { print e[i]/sum, i } }' |
|
} |
|
|
|
if ((${#LOG[@]} == 0)) |
|
then |
|
# Log is empty, so to get started |
|
# we'll fill it with failed attempts an hour ago. |
|
declare -i i timestamp=$(date +%s)-3600 |
|
for ((i=0;i<${#DECK[@]};i++)) |
|
do LOG+=("$timestamp:$timestamp:$i:0") |
|
done |
|
fi |
|
|
|
# hiding the cursor |
|
echo -ne "\e[?25l" |
|
|
|
declare line |
|
while |
|
for line in "${LOG[@]}" |
|
do echo "$line" |
|
done | |
|
awk -F: -v now=$(date +%s) -v tScale=$TIME_SCALE -e '{ |
|
deltaT = now - $1; |
|
if ($4) { s[$3]=-deltaT/tScale } else { |
|
if (s[$3] < 0) { s[$3]=tScale/deltaT } else { s[$3]+=tScale/deltaT } |
|
} |
|
} |
|
END { for (i in s) print +s[i], i }' | |
|
softmax "-$ALPHA" | |
|
LANG=C sort -t' ' -g -k1 | |
|
awk -v x="$((RANDOM%32768))" -e 'BEGIN { x /= 32768 } |
|
{ if ( (s+=$1) > x ) { print $2; found=1; exit } } |
|
END { if (found==0) { print $2 } } |
|
' | |
|
{ |
|
declare -i line_choice |
|
read -r line_choice |
|
|
|
declare -a record |
|
IFS=: read -ra record <<<"${DECK[line_choice]}" |
|
|
|
declare -i t1=$(date +%s) width |
|
(( |
|
width=${COLUMNS:-$(tput cols)}, |
|
width=width < 80 ? width : 80 |
|
)) |
|
clear |
|
echo -n "${record[1]}" | |
|
fmt -w $width | |
|
{ |
|
mapfile -t |
|
echo -ne "\e[H" |
|
echo -ne "\e[$(( (${LINES:-$(tput lines)}-${#MAPFILE[@]})/2))B" |
|
for line in "${MAPFILE[@]}" |
|
do center "$line" |
|
done |
|
read -sn1 </dev/tty |
|
echo -ne "\e[1A\e[2J" |
|
|
|
declare -i t2=$(date +%s) |
|
case "$REPLY" in |
|
$' ') |
|
center $'\e[31m'"${record[2]}"$'\e[0m' |
|
LOG+=("$t1:$t2:$line_choice:1") |
|
sleep 1 |
|
;; |
|
$'') |
|
center $'\e[32m'"${record[2]}"$'\e[0m' |
|
LOG+=("$t1:$t2:$line_choice:0") |
|
sleep .2 |
|
;; |
|
*) |
|
# show the cursor |
|
echo -e "\e[?25h" |
|
exit 1 |
|
esac |
|
} |
|
} |
|
do sleep .01 |
|
done |
|
|