Compare commits

...
20 Commits
Author SHA1 Message Date
br 5341379774 doiut 2024-01-12 17:23:30 +01:00
br 75f2635277 4800 2024-01-12 17:16:04 +01:00
br 6b8edbd8ae 4300 2024-01-12 17:08:51 +01:00
br a7b2188a47 doit 2024-01-12 17:05:38 +01:00
br 7a5bc7e5b0 change 2024-01-12 16:55:37 +01:00
br 4fd3f1d322 corr 2024-01-12 16:51:54 +01:00
br 0ab4988964 back 2024-01-12 12:56:25 +01:00
br f6cdbce038 rückwärts 2024-01-12 12:53:21 +01:00
br 630f3920ed 1/4 drehung 2024-01-12 12:52:15 +01:00
br a71924c2e9 doit 2024-01-12 12:45:55 +01:00
br 98bac35ca4 fix 2024-01-11 22:53:01 +01:00
br 1a48c4d1d8 doit 2024-01-11 22:51:10 +01:00
br 3baab5e20a doit 2024-01-11 22:04:06 +01:00
br c09524fec8 gitdir 2024-01-11 21:57:03 +01:00
br 2d7ec8c2fb motor test + qrdocs 2024-01-11 21:54:21 +01:00
br 675d050581 finale Änderungen 2023-12-20 12:14:07 +01:00
br bf0216684d qr pdf 2023-12-19 23:40:33 +01:00
br ccc70e9e4f qiz OK 2023-12-19 16:25:27 +01:00
br 580688a850 Merge branch 'main' of ssh://git.everdc.eu:10022/kinder-college/robotik-wise23 2023-12-19 16:21:23 +01:00
br 8b5f8c963f cmon 2023-12-19 16:20:27 +01:00
11 changed files with 365 additions and 26 deletions

No files matched your search

+1
View File
@@ -1 +1,2 @@
quiz/__pycache__ quiz/__pycache__
quiz/quiz copy.py
+24
View File
@@ -11,3 +11,27 @@ Bau eines Hausaufgaben Robos
* Repo für die Web-App, um den Vokabeltester / Mathe-Checker zu starten. * Repo für die Web-App, um den Vokabeltester / Mathe-Checker zu starten.
## Links ## Links
## Configs
Das Unit file für einen quiz Service (auf Gunicorn Basis)
* vi /etc/systemd/system/quiz.service
~~~
[Unit]
Description=Gunicorn instance to serve quiz
After=network.target
[Service]
User=kico
Group=www-data
WorkingDirectory=/home/kico/git/robotik-wise23/quiz
#Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
#ExecStart=/home/sammy/myproject/myprojectenv/bin/gunicorn --workers 3 --bind unix:myproject.sock -m 007 wsgi:app
ExecStart=/usr/bin/gunicorn --workers 1 --bind 0.0.0.0:8000 quiz:app
[Install]
WantedBy=multi-user.target
~~~
+65
View File
@@ -0,0 +1,65 @@
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
coil_A_1_pin = 24 # pink
coil_A_2_pin = 4 # orange
coil_B_1_pin = 23 # blau
coil_B_2_pin = 25 # gelb
coil2_A_1_pin = 18 # pink
coil2_A_2_pin = 22 # orange
coil2_B_1_pin = 17 # blau
coil2_B_2_pin = 27 # gelb
StepCount = 8
Seq = list(range(0, StepCount))
Seq[0] = [0,1,0,0]
Seq[1] = [0,1,0,1]
Seq[2] = [0,0,0,1]
Seq[3] = [1,0,0,1]
Seq[4] = [1,0,0,0]
Seq[5] = [1,0,1,0]
Seq[6] = [0,0,1,0]
Seq[7] = [0,1,1,0]
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)
GPIO.setup(coil2_A_1_pin, GPIO.OUT)
GPIO.setup(coil2_A_2_pin, GPIO.OUT)
GPIO.setup(coil2_B_1_pin, GPIO.OUT)
GPIO.setup(coil2_B_2_pin, GPIO.OUT)
def setStep(w1, w2, w3, w4):
GPIO.output(coil_A_1_pin, w1)
GPIO.output(coil2_A_1_pin, w1)
GPIO.output(coil_A_2_pin, w2)
GPIO.output(coil2_A_2_pin, w2)
GPIO.output(coil_B_1_pin, w3)
GPIO.output(coil2_B_1_pin, w3)
GPIO.output(coil_B_2_pin, w4)
GPIO.output(coil2_B_2_pin, w4)
def forward(delay, steps):
for i in range(steps):
for j in range(StepCount):
setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
time.sleep(delay)
def backwards(delay, steps):
for i in range(steps):
for j in reversed(range(StepCount)):
setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
time.sleep(delay)
# 20 langsame Schritte Vorwärts
# delay = 20
# steps = 20
# forward(int(delay) / 1000.0, int(steps))
# 200 schnelle Schritte Rückwärts
delay = 1
steps = 1000
backwards(int(delay) / 1000.0, int(steps))
+65
View File
@@ -0,0 +1,65 @@
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{qrcode}
\usepackage{geometry}
\usepackage{fancyhdr}
\usepackage{hyperref}
% Farbdefinitionen
\definecolor{HeaderColor}{rgb}{0.26, 0.45, 0.76} % Dunkelblau
\definecolor{TextColor}{rgb}{0.06, 0.42, 0.13} % Dunkelgrün
\definecolor{LinkColor}{rgb}{0.76, 0.13, 0.28} % Dunkelrot
% Seitenlayout und Ränder
\geometry{
left=20mm,
right=20mm,
top=30mm,
bottom=30mm,
headheight=15mm,
footskip=15mm
}
% Kopf- und Fußzeilen
\pagestyle{fancy}
\fancyhf{}
% \rhead{\includegraphics[width=3cm]{logo.png}} % Logo einfügen
\lhead{\textcolor{HeaderColor}{\Large IQ-O-Mat}}
\lfoot{\textcolor{TextColor}{Kinder-College}}
\rfoot{\thepage}
% Schriftart und Farben
\renewcommand{\familydefault}{\sfdefault} % Serifenlose Schrift
\setlength{\parindent}{0em}
\setlength{\parskip}{1em}
\color{TextColor}
\providecommand{\tightlist}{%
\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
\setcounter{secnumdepth}{0} % Deaktiviert die Nummerierung von Überschriften
% Pandoc spezifische Einstellungen (für Titel, Autoren, Datum, etc.)
$if(title)$
\title{$title$}
$endif$
$if(author)$
\author{$for(author)$$author$$sep$ \and $endfor$}
$endif$
$if(date)$
\date{$date$}
$endif$
\begin{document}
$if(title)$
\maketitle
$endif$
$body$
\end{document}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
ABLAGEDIR=~/Robotik-Ablage
PDFDIR=$ABLAGEDIR/pdfs
mkdir -p $PDFDIR
for i in {01..39}
#for i in {01..02}
do
cat <<EOF > $PDFDIR/kicopi$i.md
---
title: "IQ-O-Mat"
author: "Kinder-College Björn Runden <br@runden.de>"
date: "2024-01-13"
---
## Quiz-Roboter
*Entstanden am Kinder-College als "Hausaufgaben-Robo"*
Wenn der Raspi Hochgefahren ist, gelangt man zur App mit dem URL:
* [http://KiCoPi$i.local/](http://kicopi$i.local/)
Oder dem Link im QR Code folgen:
\\begin{figure}[h]
\\centering
\\qrcode[height=6cm]{http://kicopi$i.local/}
\\end{figure}
*Anmerkungen:* (WLAN am Raspberry einschalten:)
* https://www.elektronik-kompendium.de/sites/raspberry-pi/1912221.htm
* https://www.raspberry-pi-geek.de/ausgaben/rpg/2017/10/ssh-und-wlan-schon-bei-der-installation-konfigurieren/
Der Raspberry kann daheim per LAN Kabel betrieben werden. Danach mittels raspi-config in's heimische WLAN eingebunden werden.
Der Raspberry kann per HDMI am Monitor oder TV betrieben werden. Mit (USB-) Maus und Tastatur lässt er sich ins WLAN einbinden.
EOF
pandoc $PDFDIR/kicopi$i.md -o $PDFDIR/kicopi$i.pdf --template default.latex
done
+12
View File
@@ -0,0 +1,12 @@
# IQ-O-Mat
**Quiz-Roboter**
*Entstanden am Kinder-College als "Hausaufgaben-Robo"*
Wenn der Raspi Hochgefahren ist, gelangt man zur App mit dem URL:
* [KiCoPi{NUM}](http://kicopi{NUM}.local/)
Oder dem Link im QR Code folgen:
* {QRCODE}
+96 -19
View File
@@ -2,26 +2,92 @@ import os
from flask import Flask, redirect, render_template, request, session from flask import Flask, redirect, render_template, request, session
import csv # CSV handling import csv # CSV handling
import random import random
import RPi.GPIO as GPIO
import time
app = Flask(__name__) app = Flask(__name__)
def load_database(): def load_database():
file = os.path.join(os.path.expanduser("~"), "Austausch", "fragen1.csv") file = os.path.join(os.path.expanduser("~"), "Robotik-Ablage", "quiz.csv")
#with open(file, newline="", encoding="utf-8") as csvfile: # #with open(file, newline="", encoding="utf-8") as csvfile: #
with open(file, newline="", encoding="cp1252") as csvfile: # Code wird als Excel Windows-1252 Input CSV gelesen with open(file, newline="", encoding="cp1252") as csvfile: # Code wird als Excel Windows-1252 Input CSV gelesen
database = csv.reader(csvfile, delimiter=";") # Validating the "csvfile" into "database" with the delimiter "," (Comma Seperated Values) database = csv.reader(csvfile, delimiter=";")
q_a = [] # Empty list for all questions and answers q_a = [] # Empty list for all questions and answers
for row in database: # alle Zeilen in der Datenbank durchlaufen for row in database: # alle Zeilen in der Datenbank durchlaufen
index = int(row[0]) # Laufende Nummer index = int(row[0]) # Laufende Nummer
question = str(row[1]) # Frage (ist der erste Teil) question = str(row[1]) # Frage (ist der erste Teil)
answer = str(row[2]) # Antwort (3. Spalte in der CSV Datenbank) answer = str(row[2]) # Antwort (3. Spalte in der CSV Datenbank)
q_a.append({"index": index,"question": question, "answer": answer}) # Eine Liste bauen q_a.append({"index": index,"question": question, "answer": answer}) # Eine Liste bauen
return q_a return q_a
###
# Volle Drehung sind etwa 16400
# 1/4 Drehung = 1 Loch weiter = 4100 / evtl. 4300
ViertelRundeSteps = 4800
# ----------------- MOTOR KRAM
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
coil_A_1_pin = 24 # pink
coil_A_2_pin = 4 # orange
coil_B_1_pin = 23 # blau
coil_B_2_pin = 25 # gelb
coil2_A_1_pin = 18 # pink
coil2_A_2_pin = 22 # orange
coil2_B_1_pin = 17 # blau
coil2_B_2_pin = 27 # gelb
StepCount = 8
Seq = list(range(0, StepCount))
Seq[0] = [0,1,0,0]
Seq[1] = [0,1,0,1]
Seq[2] = [0,0,0,1]
Seq[3] = [1,0,0,1]
Seq[4] = [1,0,0,0]
Seq[5] = [1,0,1,0]
Seq[6] = [0,0,1,0]
Seq[7] = [0,1,1,0]
GPIO.setup(coil_A_1_pin, GPIO.OUT)
GPIO.setup(coil_A_2_pin, GPIO.OUT)
GPIO.setup(coil_B_1_pin, GPIO.OUT)
GPIO.setup(coil_B_2_pin, GPIO.OUT)
GPIO.setup(coil2_A_1_pin, GPIO.OUT)
GPIO.setup(coil2_A_2_pin, GPIO.OUT)
GPIO.setup(coil2_B_1_pin, GPIO.OUT)
GPIO.setup(coil2_B_2_pin, GPIO.OUT)
def setStep(w1, w2, w3, w4):
GPIO.output(coil_A_1_pin, w1)
GPIO.output(coil2_A_1_pin, w1)
GPIO.output(coil_A_2_pin, w2)
GPIO.output(coil2_A_2_pin, w2)
GPIO.output(coil_B_1_pin, w3)
GPIO.output(coil2_B_1_pin, w3)
GPIO.output(coil_B_2_pin, w4)
GPIO.output(coil2_B_2_pin, w4)
def forward(delay, steps):
for i in range(steps):
for j in range(StepCount):
setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
time.sleep(delay)
def backwards(delay, steps):
for i in range(steps):
for j in reversed(range(StepCount)):
setStep(Seq[j][0], Seq[j][1], Seq[j][2], Seq[j][3])
time.sleep(delay)
# ----------------- MOTOR KRAM ENDE
def FahreMotor():
#forward(1.0/1000.0, ViertelRundeSteps)
# falls auf der anderen Seite montiert:
backwards(1.0/1000.0, ViertelRundeSteps)
return True
fragen_liste = load_database() fragen_liste = load_database()
random.shuffle(fragen_liste) random.shuffle(fragen_liste)
@@ -29,40 +95,50 @@ current_index = 0
correct_sum = 0 correct_sum = 0
last_correct = None last_correct = None
max_correct_sum = 5 max_correct_sum = 5
debugtxt="" debugtxt=""
alerttxt=""
successtxt=""
won=False
@app.route('/') @app.route('/')
def quiz(): def quiz():
return render_template('quiz.html', frage=fragen_liste[current_index], return render_template('quiz.html', frage=fragen_liste[current_index],
last_correct=last_correct,debugtxt=debugtxt, correct_sum=correct_sum, last_correct=last_correct,debugtxt=debugtxt, correct_sum=correct_sum,
max_correct_sum = max_correct_sum) max_correct_sum = max_correct_sum,
alerttxt=alerttxt, successtxt=successtxt,
won=won)
@app.route('/submit_quiz', methods=['POST']) @app.route('/submit_quiz', methods=['POST'])
def submit_quiz(): def submit_quiz():
global current_index global current_index
global fragen_liste global fragen_liste
global debugtxt global debugtxt, alerttxt, successtxt
global correct_sum global correct_sum
global won
won=False
# Überprüfen Sie die Antwort und aktualisieren Sie current_index # Überprüfen Sie die Antwort und aktualisieren Sie current_index
user_answer = request.form.get('answer') user_answer = request.form.get('answer')
correct_answer = fragen_liste[current_index]['answer'] correct_answer = fragen_liste[current_index]['answer']
if user_answer.lower() == correct_answer.lower(): if user_answer.strip() == correct_answer.strip():
last_correct = True last_correct = True
correct_sum += 1 correct_sum += 1
debugtxt = correct_answer + " ist richtig! passt zu deiner Angabe: " + user_answer # debugtxt = correct_answer + " ist richtig! passt zu deiner Angabe: " + user_answer
successtxt = correct_answer + " ist richtig! passt zu deiner Angabe: " + user_answer
alerttxt = ""
elif user_answer == "42": elif user_answer == "42":
correct_sum += 1 # EASTEREGG!!! #
debugtxt = "Korrekt! Die Antwort auf alle Fragen ist 42." last_correct = True
correct_sum = 5
successtxt = "Korrekt! Die Antwort auf alle Fragen ist 42."
alerttxt = ""
else: else:
last_correct = False last_correct = False
# debugtxt += "<!-- user_answer = " + user_answer + " -->\n" alerttxt = "falsch: Richtig wäre " +correct_answer + " / und nicht: " + user_answer
# debugtxt += "<!-- correct_anwer = " + correct_answer + " -->\n" successtxt = ""
debugtxt = "falsch: Richtig wäre " +correct_answer + " / und nicht: " + user_answer
correct_sum = 0 correct_sum = 0
current_index += 1 current_index += 1
@@ -77,9 +153,10 @@ def submit_quiz():
fragen_liste = load_database() fragen_liste = load_database()
random.shuffle(fragen_liste) random.shuffle(fragen_liste)
current_index=0 current_index=0
debugtxt += "\nGewonnen! - Gut gemacht!" successtxt += "<br /> <br /> <br /> Gewonnen! - Gut gemacht! <br /> Guten Appetit!"
print ("gewonnen! - Fahre 10 Sek!") # print ("gewonnen! - Fahre 10 Sek!")
correct_sum =0 correct_sum =0
won = True
FahreMotor()
# Leiten Sie den Benutzer zur nächsten Frage weiter
return redirect('/') return redirect('/')
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+61 -5
View File
@@ -73,18 +73,26 @@
} }
button { button {
background-color: rgb(106, 90, 205); background-color: rgb(102, 51, 153);
color: rgb(255, 255, 255); /* Dunkel-lila Hintergrund */
color: white;
/* Weiße Schriftfarbe */
padding: 10px; padding: 10px;
border: none; border: none;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
width: 100%; width: 100%;
transition: background-color 0.3s ease-in-out; transition: background-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
/* Leicht erhabener Effekt */
} }
/* Aktualisierte Stilregel für den Button im Hover-Zustand */
button:hover { button:hover {
background-color: rgb(72, 61, 139); background-color: rgb(72, 61, 139);
/* Dunkleres Lila im Hover-Zustand */
box-shadow: 0px 6px 8px rgba(0, 0, 0, 0.2);
/* Stärkerer erhabener Effekt im Hover-Zustand */
} }
p { p {
@@ -103,6 +111,36 @@
color: rgb(106, 90, 205); color: rgb(106, 90, 205);
text-decoration: underline; text-decoration: underline;
} }
.alert-message {
padding: 10px;
border-radius: 5px;
font-weight: bold;
text-align: center;
}
.alert-success {
background-color: lightgreen;
color: green;
}
.alert-danger {
background-color: lightcoral;
color: red;
}
.image-container {
max-height: 50pt;
overflow: hidden;
text-align: center;
/* Zentriert das Bild horizontal */
}
.image-container img {
max-height: 50pt;
/* max-width: 100%; */
/* height: auto; */
}
</style> </style>
</head> </head>
@@ -110,13 +148,31 @@
<form method="POST" action="/submit_quiz"> <form method="POST" action="/submit_quiz">
<p name="question">{{ frage.index }}. {{ frage.question }}</p> <p name="question">{{ frage.index }}. {{ frage.question }}</p>
<input type="text" name="answer" placeholder="Antwort eingeben..." required> <input type="text" name="answer" placeholder="Antwort eingeben..." required autofocus>
<input type="submit" value="Quiz abschicken"> <button type="submit">Antwort abschicken</button>
<p class="q-amount">{{correct_sum}} von {{max_correct_sum}} nacheinander korrekt.</p> <p class="q-amount">{{correct_sum}} von {{max_correct_sum}} nacheinander korrekt.</p>
<br /> <br />
{% if debugtxt %} {% if debugtxt %}
<p class="debug">{{debugtxt}}</p> <p class="debug">{{debugtxt}}</p>
{% endif %} {% endif %}
{% if alerttxt %}
<div id="message" class="alert-message alert-danger">
{{alerttxt}}
</div>
{% endif %}
{% if successtxt %}
<div id="message" class="alert-message alert-success">
{{successtxt | safe}}
</div>
{% endif %}
{% if won %}
<br />
<br />
<div class="image-container">
<img src="{{ url_for('static', filename='pics/cake.jpg') }}" alt="Suessigkeit">
</div>
{% endif %}
</form> </form>
</body> </body>
+2 -2
View File
@@ -3,8 +3,8 @@
# + Updatefunktion # + Updatefunktion
#GITDIR=~/git/robotSoSe2022 #GITDIR=~/git/robotSoSe2022
#GITDIR=~/git/robotik-wise23 GITDIR=~/git/robotik-wise23
GITDIR=./ #GITDIR=./
Choice=$( whiptail --title "Hausaufgabenrobo Start und Update" --radiolist \ Choice=$( whiptail --title "Hausaufgabenrobo Start und Update" --radiolist \
"Bitte wählen" 20 78 4 \ "Bitte wählen" 20 78 4 \