Merge branch 'coding-horror:main' into csharp-07-basketball

This commit is contained in:
Andrew Cooper
2022-04-15 21:01:02 +10:00
committed by GitHub
13 changed files with 350 additions and 8833 deletions

View File

@@ -17,7 +17,7 @@
overflow-y: scroll;
width: 100%;
max-width: 60rem;
max-width: 640px;
margin: 0 auto;
}
@@ -32,10 +32,7 @@
padding: 0;
}
/* The "terminal" has one "prompt" element.
* This prompt is not any kind of input, but just a simple <span>
* with an id "prompt" and a
*/
/* The "terminal" has one "prompt" input-element. */
@keyframes prompt-blink {
100% {
opacity: 0;
@@ -57,6 +54,15 @@
width: 0.75rem;
opacity: 1;
}
.terminal input#prompt {
text-transform: uppercase;
background: none;
border: none;
outline: none;
caret-color: var(--text);
color: var(--text);
font: var(--terminal-font);
}
/* Terminal scrollbar */

View File

@@ -26,7 +26,7 @@ class HtmlTerminal {
* @private
* @type {HTMLElement}
*/
#$prompt = undefined;
#$prompt;
/**
* Constructor
@@ -45,13 +45,18 @@ class HtmlTerminal {
this.$output.classList.add('terminal');
// Create a prompt element.
// This element gets added if input is needed
this.#$prompt = document.createElement("span");
// This element gets added if input is needed.
this.#$prompt = document.createElement("input");
this.#$prompt.setAttribute("id", "prompt");
this.#$prompt.innerText = "";
this.#$prompt.setAttribute("type", "text");
this.#$prompt.setAttribute("length", "50");
this.#$prompt.addEventListener("keydown", this.#handleKey.bind(this));
//TODO: this handler shouls be only on the propt element and only active if cursor is visible
document.addEventListener("keyup", this.#handleKey.bind(this));
// Force focus on the promt on each click.
// This is needed for mobile support.
document.body.addEventListener('click', () => {
this.#$prompt.focus();
});
}
/**
@@ -77,37 +82,16 @@ class HtmlTerminal {
* @param {*} e
*/
#handleKey(e) {
// if no input-callback is defined
// if no input-callback is defined just return
if (!this.#inputCallback) {
return;
}
if (e.keyCode === 13 /* ENTER */) {
// create a new line with the text input and remove the prompt
const text = this.#$prompt.innerText;
this.write(text + "\n");
this.#$prompt.innerText = "";
if (e.keyCode == 13) {
const text = this.#$prompt.value;
this.#$prompt.value = '';
this.#$prompt.remove();
// return the inputed text
this.#inputCallback(text);
// remove the callback and the key handler
this.#inputCallback = undefined;
} else if (e.keyCode === 8 /* BACKSPACE */) {
this.#$prompt.innerText = this.#$prompt.innerText.slice(0, -1);
} else if (
e.keyCode == 16 // "Shift"
|| e.keyCode == 17 // "Control"
|| e.keyCode == 20 // "CapsLock"
|| !e.key.match(/^[a-z0-9!"§#$%&'()*+,.\/:;<=>?@\[\] ^_`{|}~-]$/i)
) {
// ignore non-visible characters
return e;
} else {
this.#$prompt.innerHtml = '';
const key = e.shiftKey ? e.key.toUpperCase() : e.key;
this.#$prompt.innerText = this.#$prompt.innerText + key;
this.#inputCallback(text + '\n');
}
}
@@ -122,7 +106,7 @@ class HtmlTerminal {
}
/**
* TODO:
* Create a new div and add html content.
*
* @public
* @param {*} htmlContent
@@ -189,7 +173,8 @@ class HtmlTerminal {
*/
input(callback) {
// show prompt with a blinking prompt
this.$output.appendChild(this.#$prompt);
this.#inputCallback = callback;
this.$output.appendChild(this.#$prompt);
this.#$prompt.focus();
}
}

View File

@@ -1,7 +1,7 @@
<html>
<head>
<title>Minimal node.js terminal</title>
<meta name="viewport" content="width=device-width, initial-scale=.75">
<meta name="viewport" content="width=640, initial-scale=1">
<link
rel="stylesheet"
href="../../../00_Utilities/javascript/style_terminal.css"

View File

@@ -57,9 +57,13 @@ export async function input(message = '') {
* First we need to convert it into a string. */
const data = input.toString();
/* add input to terminal
* The data should end with a newline! */
process.stdout.write(data);
/* The result fo onData is a string ending with an `\n`.
* We just need the actual content so let's remove the newline at the end: */
const content = data[data.length] === '\n' ? data.slice(0, -1) : data;
const content = data.endsWith('\n') ? data.slice(0, -1) : data;
resolve(content);
});

View File

@@ -84,143 +84,10 @@ a:hover {
}
/* add all the face flicker effects (only on desktop) */
@media screen and (min-width: 960px) {
@media not screen and (max-width: 960px) and (prefers-reduced-motion) {
main {
padding: 3rem;
}
@keyframes flicker {
0% {
opacity: 0.27861;
}
5% {
opacity: 0.34769;
}
10% {
opacity: 0.23604;
}
15% {
opacity: 0.90626;
}
20% {
opacity: 0.18128;
}
25% {
opacity: 0.83891;
}
30% {
opacity: 0.65583;
}
35% {
opacity: 0.67807;
}
40% {
opacity: 0.26559;
}
45% {
opacity: 0.84693;
}
50% {
opacity: 0.96019;
}
55% {
opacity: 0.08594;
}
60% {
opacity: 0.20313;
}
65% {
opacity: 0.71988;
}
70% {
opacity: 0.53455;
}
75% {
opacity: 0.37288;
}
80% {
opacity: 0.71428;
}
85% {
opacity: 0.70419;
}
90% {
opacity: 0.7003;
}
95% {
opacity: 0.36108;
}
100% {
opacity: 0.24387;
}
}
@keyframes textShadow {
0% {
text-shadow: 0.4389924193300864px 0 1px rgba(0,30,255,0.5), -0.4389924193300864px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
5% {
text-shadow: 2.7928974010788217px 0 1px rgba(0,30,255,0.5), -2.7928974010788217px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
10% {
text-shadow: 0.02956275843481219px 0 1px rgba(0,30,255,0.5), -0.02956275843481219px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
15% {
text-shadow: 0.40218538552878136px 0 1px rgba(0,30,255,0.5), -0.40218538552878136px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
20% {
text-shadow: 3.4794037899852017px 0 1px rgba(0,30,255,0.5), -3.4794037899852017px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
25% {
text-shadow: 1.6125630401149584px 0 1px rgba(0,30,255,0.5), -1.6125630401149584px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
30% {
text-shadow: 0.7015590085143956px 0 1px rgba(0,30,255,0.5), -0.7015590085143956px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
35% {
text-shadow: 3.896914047650351px 0 1px rgba(0,30,255,0.5), -3.896914047650351px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
40% {
text-shadow: 3.870905614848819px 0 1px rgba(0,30,255,0.5), -3.870905614848819px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
45% {
text-shadow: 2.231056963361899px 0 1px rgba(0,30,255,0.5), -2.231056963361899px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
50% {
text-shadow: 0.08084290417898504px 0 1px rgba(0,30,255,0.5), -0.08084290417898504px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
55% {
text-shadow: 2.3758461067427543px 0 1px rgba(0,30,255,0.5), -2.3758461067427543px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
60% {
text-shadow: 2.202193051050636px 0 1px rgba(0,30,255,0.5), -2.202193051050636px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
65% {
text-shadow: 2.8638780614874975px 0 1px rgba(0,30,255,0.5), -2.8638780614874975px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
70% {
text-shadow: 0.48874025155497314px 0 1px rgba(0,30,255,0.5), -0.48874025155497314px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
75% {
text-shadow: 1.8948491305757957px 0 1px rgba(0,30,255,0.5), -1.8948491305757957px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
80% {
text-shadow: 0.0833037308038857px 0 1px rgba(0,30,255,0.5), -0.0833037308038857px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
85% {
text-shadow: 0.09769827255241735px 0 1px rgba(0,30,255,0.5), -0.09769827255241735px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
90% {
text-shadow: 3.443339761481782px 0 1px rgba(0,30,255,0.5), -3.443339761481782px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
95% {
text-shadow: 2.1841838852799786px 0 1px rgba(0,30,255,0.5), -2.1841838852799786px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
100% {
text-shadow: 2.6208764473832513px 0 1px rgba(0,30,255,0.5), -2.6208764473832513px 0 1px rgba(255,0,80,0.3), 0 0 3px;
}
}
#output {
animation: textShadow 1.6s infinite;
}
#output::before {
content: " ";
display: block;
@@ -246,6 +113,5 @@ a:hover {
opacity: 0;
z-index: 2;
pointer-events: none;
animation: flicker 0.15s infinite;
}
}

121
05_Bagels/lua/Bagels.lua Normal file
View File

@@ -0,0 +1,121 @@
---
--- Bagels
--- Ported by Joe Nellis.
--- Text displayed is altered slightly from the original program to allow for
--- more (or less) than three digits to be guessed. Change the difficulty to
--- the number of digits you wish in the secret code.
---
--- difficult is number of digits to use
local difficulty = 3
print [[
BAGELS
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
]]
function getInput(prompt)
io.write(prompt)
io.flush()
local input = io.read("l")
if not input then --- test for EOF
print("GOODBYE")
os.exit(0)
end
return input
end
local needsRules = getInput("WOULD YOU LIKE THE RULES? (YES OR NO) ")
print()
if needsRules:match("[yY].*") then
print(string.format( [[
I AM THINKING OF A %u DIGIT NUMBER. TRY TO GUESS
MY NUMBER AND I WILL GIVE YOU CLUES AS FOLLOWS:
PICO - ONE DIGIT CORRECT BUT IN THE WRONG POSITION
FERMI - ONE DIGIT CORRECT AND IN THE RIGHT POSITION
BAGELS - NO DIGITS
]], difficulty))
end
function play(numDigits, score)
local digits = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" }
--- secret number must not have duplicate digits
--- randomly swap numDigits at the head of this list to create secret number
for i = 1, numDigits do
local j = math.random(1, 10)
digits[i], digits[j] = digits[j], digits[i]
end
print "O.K. I HAVE A NUMBER IN MIND."
for guessNum = 1, 20 do
:: GUESS_AGAIN :: ---<!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
local guess = getInput(string.format("GUESS #%u\t?",guessNum))
if #guess ~= numDigits then
print("TRY GUESSING A", numDigits, "DIGIT NUMBER.")
goto GUESS_AGAIN
elseif not guess:match("^(%d+)$") then
print("WHAT?")
goto GUESS_AGAIN
else
--- check if user has duplicate digits
for i = 1, numDigits - 1 do
for j = i + 1, numDigits do
if (guess:sub(i, i) == guess:sub(j, j)) then
print("OH, I FORGOT TO TELL YOU THAT THE NUMBER I HAVE")
print("IN MIND HAS NO TWO DIGITS THE SAME.")
goto GUESS_AGAIN
end
end
end
end
local report = ""
--- check for picos, right digit, wrong place
for i = 1, numDigits do
for j = i + 1, numDigits - 1 + i do
if (guess:sub(i, i) == digits[(j - 1) % numDigits + 1]) then
report = report .. "PICO "
end
end
end
--- check for fermis, right digit, right place
for i = 1, numDigits do
if (guess:sub(i, i) == digits[i]) then
report = report .. "FERMI "
end
end
if (report == string.rep("FERMI ", numDigits)) then
print "YOU GOT IT!!!"
print ""
score = score + 1
goto PLAY_AGAIN
end
if (report == "") then
print("BAGELS")
else
print(report)
end
end
print "OH WELL."
print("THAT'S TWENTY GUESSES. MY NUMBER WAS "
.. table.concat(digits, "", 1, numDigits))
:: PLAY_AGAIN :: ---<!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
local playAgain = getInput("PLAY AGAIN (YES OR NO)?")
print()
if (playAgain:match("[yY].*")) then
return play(numDigits, score)
else
if (score > 0) then
print("A", score, "POINT BAGELS BUFF!!")
end
print "HOPE YOU HAD FUN. BYE."
end
end
play(difficulty, 0) --- default is numDigits=3, score=0

9
33_Dice/rust/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"

3
33_Dice/rust/README.md Normal file
View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/)

85
33_Dice/rust/src/main.rs Normal file
View File

@@ -0,0 +1,85 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dice
//
// From: BASIC Computer Games (1978)
// Edited by David H. Ahl
//
// "Not exactly a game, this program simulates rolling
// a pair of dice a large number of times and prints out
// the frequency distribution. You simply input the
// number of rolls. It is interesting to see how many
// rolls are necessary to approach the theoretical
// distribution:
//
// 2 1/36 2.7777...%
// 3 2/36 5.5555...%
// 4 3/36 8.3333...%
// etc.
//
// "Daniel Freidus wrote this program while in the
// seventh grade at Harrison Jr-Sr High School,
// Harrison, New York."
//
// Rust Port by Jay, 2022
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
use rand::Rng;
use std::io::{self, Write};
fn main() {
let mut frequency: [i32; 13] = [0; 13];
println!(
"{: >38}\n{: >57}\n\n",
"DICE", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
);
// DANNY FREIDUS
println!("THIS PROGRAM SIMULATES THE ROLLING OF A");
println!("PAIR OF DICE.");
println!("YOU ENTER THE NUMBER OF TIMES YOU WANT THE COMPUTER TO");
println!("'ROLL' THE DICE. WATCH OUT, VERY LARGE NUMBERS TAKE");
println!("A LONG TIME. IN PARTICULAR, NUMBERS OVER 5000.");
let mut playing = true;
while playing {
let n = match readinput(&"HOW MANY ROLLS").trim().parse::<i32>() {
Ok(num) => num,
Err(_) => {
println!("PLEASE ENTER A NUMBER");
continue;
}
};
// Dice Rolled n times
for _i in 0..n {
let die_1 = rand::thread_rng().gen_range(1..=6);
let die_2 = rand::thread_rng().gen_range(1..=6);
let total = die_1 + die_2;
frequency[total] += 1;
}
// Results tabel
println!("\nTOTAL SPOTS NUMBER OF TIMES");
for i in 2..13 {
println!("{:^4}\t\t{}", i, frequency[i]);
}
// Continue the game
let reply = readinput("TRY AGAIN").to_ascii_uppercase();
if reply.starts_with("Y") || reply.eq("YES") {
frequency = [0; 13];
} else {
playing = false;
}
}
}
// function for getting input on same line
fn readinput(str: &str) -> String {
print!("\n{}? ", str);
let mut input = String::new();
io::stdout().flush().unwrap();
io::stdin()
.read_line(&mut input)
.expect("Failed to get Input");
input
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long