You are not logged in.
Hi,
I wanted to use this script for some learning. ->
https://bbs.archlinux.org/viewtopic.php?id=51375
It needs a textfile based on the scheme
"question" "answer" "extended answer"
"question" "answer" "extended answer"
"question" "answer" "extended answer"
Every line resembles a flashcard/cuecard.
The stuff I want to learn is based on whole sentences, so I had to modify the script. It originally uses cut, which counts spaces and tabs as delimiters. Bad, if you want to use more than one word for questions and answers. I replaced the cut-part with awk and used ">" as delimiters. Sadly it still doesn't work. Although it recognizes the fields correctly, it makes no difference, if I give correct answers or not, it always states "false". My bashscripting skills are nonexistent, it would be kind, if someone could give me a hint whats wrong. Or maybe point me to another script with the same abilitys (flat textfiles as database and no dependencies like java/python etc.)
Thanks a lot.
ink
Last edited by inknoir (2010-09-09 08:32:01)
Offline
awk works really well with these things.
It can even read entries (question + answer + extra info) as paragraphs (delimited by a blank line) and fields as lines simply by setting the variables
RS=""
FS="\n"
I wrote a small example script:
Dictionary:
Question A
Answer A
Extra A
More Extra A
Question B
Answer B
Extra B
Question c
Answer c
Extra c
Question d
Answer d
Extra d
Question e
Answer e
Extra e
Question f
Answer f
Extra f
Question g
Answer g
Extra g
Question h
Answer h
Extra h
Script:
#! /bin/awk -f
function prompt(PS) {
printf( PS )
read = "read; echo $REPLY"
read | getline user
close(read)
return user
}
function random_list( max, amount ) {
for ( i = 1; i < amount + 1; i++ ) {
while ( 1 ) {
random_unique = int( rand() * max ) + 1
unique = 1
for ( key in rlist )
if ( rlist[key] == random_unique ) unique = 0
if ( unique ) break
}
rlist[i] = random_unique
}
}
BEGIN {
#Paragraph delimited mode
RS = ""
FS = "\n"
srand()
}
{
#Store the entire file as separate lists
question[NR] = $1
answer[NR] = $2
extra[NR] = $3
for ( i = 4; i < NF + 1; i++ ) extra[NR] = extra[NR] "\n" $i
}
END {
MC_amount = 5
if ( MC_amount > NR ) MC_amount = NR
while ( 1 ) {
random_list( NR, MC_amount ) # populate `rlist'
right_answer = int( rand() * MC_amount ) + 1
print "Q: " question[rlist[right_answer]]
for ( i = 1; i < MC_amount + 1; i++)
print "\t" i ") " answer[rlist[i]]
user = prompt( "> " )
if ( user == "q" ) break
if ( user == right_answer ) printf( "Great Jorb\nExtra Information: %s\n", extra[rlist[right_answer]] )
else printf( "Incorrect\nThe answer should have been: '%s) %s'\n", right_answer, answer[rlist[right_answer]] )
prompt( "-Enter-" )
printf( "\x1b[A\r-------\n" )
}
}
Usage:
chmod +x quiz.awk
./quiz.awk dictionary.txt
Offline
As a pure-bash alternative...
I typically use '|' as a delimiter, combined with a while read loop to populate some arrays for use in the script:
#!/bin/bash
#
# example input:
#
# question 1|answer 1|extended 1
# question 2|answer 2|extended 2
# ...
#
###
file="/input/file.txt"
# read the file into array variables:
while IFS='|' read -r question answer extended; do
questions+=( "$question" )
answers+=( "$answer" )
extendeds+=( "$extended" )
done < "$file"
# now you can access any one question by number
get_random() {
# go google "getting random integer bash" or something
}
while true; do
rand=$(get_random)
read -p "${question[$rand]}? " response
[[ "$response" =~ q|quit ]] && break
if [[ "$response" == "${answer[$rand]}" ]]; then
# correct answer logic...
else
# wrong answer logic...
fi
done
you get the idea
//github/
Offline
Cool, thank you Procyon. Tried it and like it. I hope it doesn't sound picky...but the script that I referred to works a little different. It asks for value "answer" first and lets me then pass the multiplechoicetest with random values "extended answers".
Background is, that I study law (<--reason for my nonexistent scriptingskills, too little time right now). Here is examples of what I need to learn:
General information connected to laws, I only have to know the laws:
question:
"Which laws in the civil law grant compensation, if your fresh bought pc is broken?"
answer:
"The § 437 Nr.3 BGB on connection to §§ 280 Abs.1, 3; 281 BGB"
Schemes I have to know exactly, because they are the abstract structure, some answers have to be given in:
question:
"You bought a new pc. After starting it for the first time, you realize its harddrive is damaged. Do you get compensation?"
answer, that has to correspond to the scheme for compensation:
"I. Exists a title?
1. Purchasing-agreement [yes, we had a valid purchasing-agreement]
a. Valid offer [yes, the seller offered it in his store for 1000 $]
b. Valid acceptande [yes I am old enough to accept and accepted]
2. Property-damage [yes, the pc is physically broken]
3. At the passing of risk [yes the pc was already damaged, when the seller gave it to me]
4. Warrantyexclusion [no, he sold it as new and didn't exclude warranty]
5. Compensationdemand [yes, I demanded compensation]
II. Is the title enforcable? [yes, there is no plea of the seller]
III. Yes I get compensation according to § 437 Nr.3 BGB on connection to §§ 280 Abs.1, 3; 281 BGB."
definitions I have to know exactly:
question:
"Define 'compensatory damages'."
answer:
"Compensatory damages, also called actual damages, are paid to compensate
the claimant for loss, injury, or harm suffered by another's breach of duty."
I hoped I could write all these different informations in simple flat textfiles so I could reuse them, change them and exchange them easily on any platform.
..and thanks brisbin33, I will look further into it.
Last edited by inknoir (2010-09-08 09:55:19)
Offline
You want to type entire strings like
Ask for compensation according to §§ 437 Nr.3, 280 Abs.1, 3, 281 BGB, if Y happend.
?
I tried out the original script, and here is an update:
#! /bin/awk -f
function prompt(PS) {
printf( PS )
read = "read; echo $REPLY"
read | getline user
close(read)
return user
}
function random_list( max, amount ) {
for ( i = 1; i < amount + 1; i++ ) {
while ( 1 ) {
random_unique = int( rand() * max ) + 1
unique = 1
for ( key in rlist )
if ( rlist[key] == random_unique ) unique = 0
if ( unique ) break
}
rlist[i] = random_unique
}
}
BEGIN {
#Paragraph delimited mode
RS = ""
FS = "\n"
srand()
}
{
#Store the entire file as separate lists
question[NR] = $1
answer[NR] = $2
extra[NR] = $3
for ( i = 4; i < NF + 1; i++ ) extra[NR] = extra[NR] "\n" $i
}
END {
MC_amount = 5
if ( MC_amount > NR ) MC_amount = NR
while ( 1 ) {
random_list( NR, MC_amount ) # populate `rlist'
right_answer = int( rand() * MC_amount ) + 1
print "Q: " question[rlist[right_answer]]
user = prompt("A: ")
if ( user == "q" ) break
if ( user == answer[rlist[right_answer]] ) typing_correct = 1
else typing_correct = 0
for ( i = 1; i < MC_amount + 1; i++)
print "\t" i ") " extra[rlist[i]]
user = prompt( "> " )
if ( user == "q" ) break
if ( user == right_answer && typing_correct ) print "A Jorb Well Done!"
else {
printf( "Incorrect\nThe answer should have been: '%s' and '(%s) %s'\n", answer[rlist[right_answer]], right_answer, extra[rlist[right_answer]] )
printf( "%s\n%s\n%s\n\n", question[rlist[right_answer]], answer[rlist[right_answer]], extra[rlist[right_answer]] ) | "cat >> error.log"
}
prompt( "-Enter-" )
printf( "\x1b[A\r-------\n" )
}
}
Try this one for if you want both with multiple choice:
(unfortunately you can't return an entire array in AWK)
#! /bin/awk -f
function prompt(PS) {
printf( PS )
read = "read -n 1; echo $REPLY"
success = read | getline user
close(read)
if ( success != 1 ) user = ""
return user
}
function random_list( max, amount ) {
for ( i=0; i < amount; i++) {
delete answer_random[i]
delete extra_random
}
for ( i = 1; i < amount + 1; i++ ) {
while ( 1 ) {
random_unique = int( rand() * max ) + 1
unique = 1
for ( key in answer_random )
if ( answer_random[key] == random_unique ) unique = 0
if ( unique ) break
}
answer_random[i] = random_unique
}
for ( i = 1; i < amount + 1; i++ ) {
while ( 1 ) {
random_unique = int( rand() * max ) + 1
unique = 1
for ( key in extra_random )
if ( extra_random[key] == random_unique ) unique = 0
if ( unique ) break
}
extra_random[i] = random_unique
}
}
BEGIN {
#Paragraph delimited mode
RS = ""
FS = "\n"
srand()
}
{
#Store the entire file as separate lists
question[NR] = $1
answer[NR] = $2
extra[NR] = $3
for ( i = 4; i < NF + 1; i++ ) extra[NR] = extra[NR] "\n" $i
}
END {
MC_amount = 5
if ( MC_amount > NR ) MC_amount = NR
while ( 1 ) {
random_list( NR, MC_amount ) # populate `extra_random' and `answer_random'
answer_key = int( rand() * MC_amount ) + 1
answer_in_extra = 0
for ( key in extra_random )
if ( extra_random[key] == answer_random[answer_key] ) {
answer_in_extra = 1
extra_key = key
break
}
if ( answer_in_extra == 0 ) {
extra_key = int( rand() * MC_amount ) + 1
extra_random[extra_key] = answer_random[answer_key]
}
print "Q: " question[extra_random[extra_key]]
for ( i = 1; i < MC_amount + 1; i++)
print "\t" i ") " answer[answer_random[i]]
user = prompt( "> " )
printf( "\n" )
if ( user == "q" ) break
if ( user == answer_key ) typing_correct = 1
else typing_correct = 0
for ( i = 1; i < MC_amount + 1; i++)
print "\t" i ") " extra[extra_random[i]]
user = prompt( "> " )
printf( "\n" )
if ( user == "q" ) break
if ( user == extra_key && typing_correct ) print "A Jorb Well Done!"
else {
printf( "Incorrect\nThe answer should have been: '%s' and '(%s) %s'\n", answer[extra_random[extra_key]], extra_key, extra[extra_random[extra_key]] )
printf( "%s\n%s\n%s\n\n", question[extra_random[extra_key]], answer[extra_random[extra_key]], extra[extra_random[extra_key]] ) | "cat >> error.log"
}
prompt( "-any key-" )
printf( "\r----------\n" )
}
}
EDIT:
By the way I didn't understand anything what you said after "Schemes I have to know exactly".
If there are problems, rephrase that information in a way how you expect the script to work.
Last edited by Procyon (2010-09-07 22:23:42)
Offline
Thanks Procyon, you made my day. The second script has, what I was looking for. I am sorry for causing
confusion. My problem is, that I am not quite sure, how the script should work to achive the goal.
I have little knowledge of the abilities of bash/awk and I was afraid of asking the wrong questions.
I will try to make the needs clear:
- Theres are three different types of information I have to learn, as seen in the three examples above.
- There are two ways, how I have to reproduce these informations. Some informations have to be reproduced exactly. Others don't. Differentiation is important, since it is uneconomic to learn everything equally good. Its way too much information.
- It is nessecary to have the different types of information in one file, they all are needed in the process of solving a single lawcase.
- The file should be plain text and stay humanreadable. So one can work with the file with the editor of choice and converting into other formats stays possible.
- It would be nice but it is not nessecary, if wrong answers cause the script to copy the entire array into a new textfile for further repetition (with the same script so it again builds a new textfile).
- It would be nice but it is not nessecary, if the script would be so easy a nonprogrammer can understand it, so further configuration is possible after a little learning.
Your second script seems to have the requirements. Definitions and (shortened) schemes can be learnd where one has to reproduce information exactly. Other informations that don't have to be known exactly can be learned with multiplechoice. Informations belonging to each other stay together, in a flat textfile.
Maybe someone has a better idea of how these informations can be learned, but your script seems right. I owe you a pizza/beer!
Offline