Software
Name | Description | Price | Download |
---|---|---|---|
StraightPool | Billard app. | ? | Android |
Software Developer
Name | Description | Price | Download |
---|---|---|---|
StraightPool | Billard app. | ? | Android |
My name is Mirko Marx, a software developer for desktop applications and embedded devices. I've specialized in cross platform development with C++ and Qt for serveral years. I'm interested in the most recent development methods, blog posts and language standards around C++.
Das Kontaktformular ist wegen der neu inkraftgetretenen Datenschutz-Grundverordnung bis zur Klärung der Rechtslage deaktiviert worden.
Ordner finden:
$ find / -type d name "*.zip"
Text in Datei finden:
$ grep 'word' <file>
Komprimieren und Symbolische Links erhalten:
$ tar -czvf example.tar.gz example/
Dekomprimieren und Symbolische Links erhalten:
$ tar -xhzvf example.tar.gz
Man pages: tar
Aktuelle CPU- und Speicher-Auslastung:
$ top -bc | grep <process_name>
Durchschnittliche CPU- und Speicher-Auslastung:
$ ps -C <process_name> -o %cpu,%mem,cmd
CPU-Informationen:
$ cat /proc/cpuinfo
$ rsync -auv --log-file=/var/log/rsync_backup --delete /source/path /target/path
-a umfasst die Optionen r (rekursiv), l (symbolische Links mitkopieren), p (Rechte der Dateien und Ordner übernehmen), t (Zeitstempel übernehmen), g (Gruppenrechte übernehmen) und D (Gerätedateien mitkopieren). Das –u steht für Update und sorgt dafür das nur neuere Dateien kopiert werden. Das -v steht für verbose und gibt Details auf der Konsole aus was gerade passiert.
Last change: Sat, 17 Nov 2018 13:42:00 +0000
Als Betriebssystem soll ArchLinux auf der SD-Karte installiert werden.
$ sudo dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=32
$ sudo fdisk /dev/mmcblk0
"o" -> Partionen löschen
"p" -> Partionen anzeigen (sollte keine Partitionen zeigen)
"n", "p" für primary, "1", "32768", ENTER
"w"
$ sudo mkfs.ext4 /dev/mmcblk0p1
$ mkdir root
$ sudo mount /dev/mmcblk0p1 root
$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
$ su
# bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C root
# sync
# wget http://os.archlinuxarm.org/os/rockchip/boot/rock64/boot.scr -O root/boot/boot.scr
# umount root
$ wget http://os.archlinuxarm.org/os/rockchip/boot/rock64/idbloader.img
$ wget http://os.archlinuxarm.org/os/rockchip/boot/rock64/uboot.img
$ wget http://os.archlinuxarm.org/os/rockchip/boot/rock64/trust.img
$ dd if=idbloader.img of=/dev/mmcblk0 seek=64 conv=notrunc
$ dd if=uboot.img of=/dev/mmcblk0 seek=16384 conv=notrunc
$ dd if=trust.img of=/dev/mmcblk0 seek=24576 conv=notrunc
Jetzt kann die SD-Karte in den Rock64 eingesetzt werden und die Stromversorgung eingeschaltet werden. Das System sollte nun hochfahren.
Achtung: Da die HDMI-Unterstützung für den Rock64 unter ArchLinux nicht funktioniert, kann nur über SSH auf den Rock64 zugegriffen werden.
Die Standard-Benutzer und Standardpasswörter sind:
Falls die Tastaturbelegung nicht stimmt:
$ loadkeys de
Entferne die Datei boot.scr die zuvor manuell heruntergeladen wurde und installiere das U-Boot-Package:
# rm /boot/boot.scr
# pacman -Sy uboot-rock64
"y" -> um den letzten Bootloader zu installieren
# exit
Sprache und Zeitzone ändern:
# echo LANG=de_DE.UTF-8 > /etc/locale.conf
# echo KEYMAP=de-latin1-nodeadkeys > /etc/vconsole.conf
# ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
# nano /etc/locale.gen
# locale-gen
Passwörter ändern:
$ passwd
# passwd
Hostnamen ändern:
# hostnamectl set-hostname rock64
Archlinux Krypto-Schlüssel aktualisieren:
# pacman-key --init
# pacman-key --populate archlinuxarm
Angenommen es soll von einem PC auf den Rock64 per SSH zugegriffen werden. Dann muss auf dem PC und als auch auf dem Rock64 OpenSSH installiert werden.
# pacman -S openssh
Falls noch nicht vorhanden müssen SSH-Keys auf dem PC generiert werden:
# ssh-keygen -t rsa
Im Ordner ~/.ssh sollte sich jetzt ein Private-Key id_rsa
und ein Public-Key id_rsa.pub
befinden. Nun muss der Inhalt des Public-Keys vom PC in die ~/.ssh/authorized_keys
-Datei des Rock64 hinzugefügt werden.
Soll auf dem PC Putty als SSH-Client verwendet werden, so muss noch eine *.ppk-Version des Private-Keys mit puttygen
generiert werden, welche bei der Verwendung von Putty angegeben werden muss.
Last change: Sun, 15 Nov 2019 09:55:50 +0000
Web-Server installieren:
# pacman -S nginx
# systemctl start nginx.service
# systemctl enable nginx.service
Das Standard-Webseiten-Verzeichnis ist /srv/http.
Beachte, dass die Portweiterleitung für Port 80 zur Nutzung von HTTP im Router aktiviert ist.
Soll der Server von außen erreichbar sein, so ist es eher störend über die IP-Adresse zuzugreifen. Besser ist es über eine Domain zugreifen zu können. Domains lassen sich bei diversen Anbietern mieten.
Falls der Web-Server an einem Internet-Anschluss mit dynamischer IP-Adresse hängt, muss die aktuelle IP für die Domain aktuell gehalten werden. Dies wird durch die Nutzung eines DynDNS-Service erreicht, der im Router des Internet-Anschlusses konfiguriert und unterstützt werden muss. Wie das konkret umgesetzt wird soll hier nicht erklärt werden.
Um ein Let's Encrypt-Zertifikat erstellen zu können muss das Tool certbot installiert werden.
# pacman -S certbot
Angenommen die Website liegt auf dem Webserver unter /src/http/yourdomain.com und die Website ist unter den zwei Domains yourdomain.com und www.yourdomain.com erreichbar. Die Zertifikatserstellung erfolgt dann durch:
# certbot certonly --webroot -w /srv/http/yourdomain.com
-d yourdomain.com -d www.yourdomain.com
Wenn die Zertifikatserstellung erfolgreich war, so wurden die Zertifikate unter /etc/letsencrypt/live/yourdomain.com abgelegt. Nun muss nur noch die Webserver-Konfiguration (unter /etc/nginx/nginx.conf) ähnlich der folgenden angepasst werden.
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80 default_server;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
location / {
root /srv/http/yourdomain.com;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
server {
listen 443 ssl default_server;
server_name yourdomain.com;
# SSL
ssl on;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_ciphers HIGH:!aNULL:!MD5:!RC4;
# HSTS
add_header Strict-Transport-Security "max-age=3156000; includeSubDomains" always;
# global
location / {
root /srv/http/yourdomain.com;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
Damit der Web-Server die Änderungen übernimmt, sollte er neugestartet werden.
# systemctl restart nginx.service
Beachte, dass die Portweiterleitung für Port 443 zur Nutzung von HTTPS im Router aktiviert ist.
Nun ist die Website über ein kostenloses Let's Encrypt Zertifikat komplett SSL verschlüsselt.
Ein Let's Encrypt-Zertifikat ist immer 90 Tage gültig und muss deshalb regelmäßig mit dem Befehl certbot renew --quiet
erneuert und der Webserver neugestartet werden.
Das lässt sich per Systemd automatisieren.
Zuerst wird der tatsächliche Dienst zum Erneunern angelegt:
# nano /etc/systemd/system/certbot.service
[Unit]
Description=Let's Encrypt renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
ExecStartPost=/bin/systemctl reload nginx.service
Danach wird ein Timer angelegt, der täglich den Prozess ausführt. Certbot prüft selbstständig, ob eine Verlängerung notwendig ist.
# nano /etc/systemd/system/certbot.timer
[Unit]
Description=Daily renewal of Let's Encrypt's certificates
[Timer]
OnCalendar=daily
RandomizedDelaySec=1day
Persistent=true
[Install]
WantedBy=timers.target
Zuletzt muss der Timer gestartet und aktviert werden (so dass dieser auch bei einen System-Reboot ausgeführt wird).
# systemctl start certbot.timer
# systemctl enable certbot.timer
Der Status der Ausführung lässt sich wie folgt prüfen:
# journalctl -u certbot
Häufig sollen neben der normalen Website weitere Dienste angeboten werden, die unter einem separaten Webserver unter einer anderen Port-Nummer laufen.
Beispielsweise läuft ein Service auf Port 12345. Nun soll dieser einfach über http[s]://[www.]yourdomain.com/Service
erreichbar sein. Dazu müsste die Server-Konfiguration (/etc/nginx/nginx.conf) wie folgt angepasst werden:
server {
listen 80 default_server;
...
location /Service {
proxy_pass http://localhost:12345;
}
...
}
server {
listen 443 default_server;
...
location /Service {
proxy_pass http://localhost:12345;
}
...
}
Hierbei wird das zu sichernde System heruntergefahren und der Datenträger an ein anderes System eingehangen. Anschließend wird ein Image-Abbild davon erstellt:
$ dd if=/dev/<device-id> of=/path/to/image.img bs=4M status=progress
Hierbei wird das zu sichernde System nicht heruntergefahren sondern nur alle Dienste und Prozesse angehalten die auf den Datenträger schreiben könnten. Anschließend erstellt das laufende System von seinem eigenen Datenträger ein Image-Abbild und schreibt es auf einen anderen Datenträger. Nach dem Abschluss werden die zuvor beendeten Dienste und Prozess wieder gestartet.
Beispiel Backup-Skript:
#!/bin/bash
TIMESTAMP=`date +%Y%m%d-%H%M%S`
DESDIR=/mnt/hdd/BACKUPS/images
BACKUP_ANZAHL="5"
BACKUP_NAME="RaspberryPiBackup"
DIENSTE_START_STOP="service mysql"
# Stoppe Dienste vor Backup
#${DIENSTE_START_STOP} stop
# Backup mit Hilfe von dd erstellen und im angegebenen Pfad speichern
dd if=/dev/mmcblk0 of=${DESDIR}/${BACKUP_NAME}-${TIMESTAMP}.img bs=1MB
# Starte Dienste nach Backup
#${START_SERVICES} start
# Alte Sicherungen die nach X neuen Sicherungen entfernen
#pushd ${DESDIR}; ls -tr ${DESDIR}/${BACKUP_NAME}* | head -n -${BACKUP_ANZAHL} | xargs rm; popd
sync
Mit folgendem Cron-Job kann das Backup-Skript wiederkehrend automatisiert ausgeführt werden:
# export VISUAL=nano; crontab -e
Um das Backup-Skript bspw. jeden Sonnabend um 2:00 Uhr auszuführen ist folgender Eintrag für den Cron-Job erforderlich:
0 2 * * * /path/to/backup_image.sh
Load loopback kernel module:
# modprobe loop
Find a unused loopback device:
# losetup -f
Create a new loopback device for the image:
# losetup /dev/loop0 image.img
Trigger kernel to load the new loopback device:
# partprobe /dev/loop0
Open GParted and shrink filesystem and partition:
# gparted /dev/loop0
Release the loopback device:
# losetup -d /dev/loop0
Display the partion table:
# fdisk -l image.img
You will see something like this:
Disk image.img: 29.7 GiB, 31914983424 bytes, 62333952 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe948a605
Device Boot Start End Sectors Size Id Type
image.img1 2048 206847 204800 100M c W95 FAT32 (LBA)
image.img2 206848 31023103 30816256 14.7G 83 Linux
Finally the image file has to be truncated (use the number of sectors and blocksize from your fdisk output):
# truncate --size=$[(31023103+1)*512] image.img
Last change: Sun, 28 Oct 2018 10:33:19 +0000
$ dd if=/path/to/image.img of=/dev/<device-id> bs=4M status=progress
Use GParted to make this:
# gparted /dev/<device-id>
Last change: Sun, 28 Oct 2018 10:34:47 +0000
Falls der Datenträger eine NTFS-Formatierung hat, muss der NTFS-Treiber installiert werden:
# pacman -S ntfs-3g
Verzeichnis für das Mounten des Datenträgers erstellen:
# mkdir /mnt/hdd
Datenträger mounten:
# mount -t auto /dev/sdx1 /mnt/hdd
Permanentes Mounten eines Datenträgers durch Hinzufügen des folgenden Eintrages in /etc/fstab
:
UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" /mnt/hdd1 auto defaults,nofail 0 0
Achtung: Die Option "nofail" ist wichtig, da das Booten nicht klappt, falls der Datenträger nicht angeschlossen ist!:
Die UUID des Datenträgers lässt sich durch folgenden Befehl herausfinden:
# fdisk -l
# blkid /dev/<Geräte-Bezeichnung>
# pacman -S hdparm
Den Status der Festplatte kann man wie folgt abrufen:
# hdparm -C /dev/sdx
Um eine Festplatte in den Standby zu schicken muss folgendes aufgerufen werden:
# hdparm -y /dev/sdx
Will ein Prozess auf die Festplatte zugreifen wird sie automatisch wieder anlaufen.
Soll eine Festplatte nach einer gewissen Zeit automatisch in den Standby geschickt werden, so muss folgendes aufgerufen werden:
# hdparm -S 60 /dev/sdx
Hierbei steht 60 für eine Zeit von 60 * 5 Sekunden.
Um diese Einstellung permanent zu setzen muss in /etc/hdparm.conf
folgender Eintrag hinzugefügt werden:
/dev/disk/by-uuid/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx {
spindown_time = 60
}
Last change: Wed, 28 Nov 2018 11:05:21 +0000
Samba einrichten:
# pacman -S samba
# cp /etc/samba/smb.conf.default /etc/samba/smb.conf
Allgemeine Konfiguration (/etc/samba/smb.conf
):
workgroup = HOMEGROUP
# log file = /var/log/samba/log.%m
security = user
Beispiel für die Konfiguration eines neuen NAS-Netzlaufwerks (/etc/samba/smb.conf
):
[HDD]
comment = HDD
path = /mnt/hdd
valid users = @users
force group = users
create mask = 0660
directory mask = 0771
read only = no
Benutzer einrichten:
# useradd nas -m -G users
# passwd nas
# smbpasswd -a nas
# chown nas:nas -R /mnt/hdd
Samba-Dienst starten:
# systemctl start smb.service
# systemctl enable smb.service
# systemctl start nmb.service
# systemctl enable nmb.service
Last change: Wed, 28 Nov 2018 10:47:47 +0000
Commit-Message bearbeiten (Not pushed + most recent commit)
$ git commit --amend
Commit-Message bearbeiten (Already pushed + most recent commit)
$ git commit --amend
$ git push origin master --force
ACHTUNG: Dies wird andere Benutzer daran hindern sich mit dem Repo zu synchronisieren, wenn sie bereits eine Kopie gezogen haben!
Commit-Message bearbeiten (Not pushed + old commit)
$ git rebase -i HEAD~X
$ git commit --amend
$ git rebase --continue
Commit-Message bearbeiten (Already pushed + old commit)
$ git rebase -i HEAD~X
$ git commit --amend
$ git rebase --continue
$ git push origin master --force
$ git checkout <branch>
$ git merge -s ours master
$ git checkout master
$ git merge <branch>
-s ours
ist die Abk. für --strategy=ours
$ git branch -d <branch>
$ git push origin :<branch>
# pacman -S git
Ein entferntes Repository erstellen (gewöhnlicherweise auf einem Linux-Server).
$ mkdir <path/to/repo>
$ cd <path/to/repo>
$ git --bare init
Das enternte Repository lässt sich nun von einem Client-Rechner (mit installiertem Git) wie folgt klonen.
$ git clone ssh://username@host/path/to/remoteRepo
Nun könnte noch nach einem Schlüssel gefragt werden. Bei Tortoise-Git unter Windows muss dann die "raspi.ppk"-Datei angegeben werden. Unter Linux muss die "raspi.ppk"-Datei wie folgt umgewandelt werden:
$ mkdir -p ~/.ssh
$ puttygen ~/raspi.ppk -o ~/.ssh/id_rsa -O private-openssh
$ git add
$ git rm
Der Status kann jederzeit durch folgenden Befehl überprüft werden:
$ git status
$ git commit
Danach öffnet sich ein Editor, in dem die Commit-Nachricht eingegeben werden muss. Beachte: Der zu verwendende Editor kann wie folgt geändert werden:
$ git config --global core.editor notepad.exe
$ git push origin
Die Standard-Branch heißt "master".
$ git pull
Dadurch werden die letzten Updates aus dem entfernten Repository geholt.
Die Standard-Branch heißt "master". Für einen Entwicklungsschritt solltest du aber eine eigene Branch erstellen und in diese Branch wechseln:
$ git branch
$ git checkout
Sobald der Entwicklungsschritt abgeschlossen ist, sollte man in den "master"-Branch wechseln und die Änderungen aus den "Entwicklungs"-Branch dort hinein-mergen:
$ git checkout master
$ git merge
Dadurch können Konflikte auftreten, die du durch manuelles Edititeren beheben musst. Nach erfolgreichen mergen sollte die Branch auch wieder gelöscht werden:
$ git branch -d
Beachte: Eine Branch ist im entfernten Repository nicht verfügbar, bis du sie im entfernten Repository hochlädst:
$ git push origin
Es wird empfohlen für jeden abgeschlossenen Meilensteilen (z.B. ein Release) ein neues Tag anzulegen:
$ git tag
Für ein Backups auf dem enternten Repository auf dem Server kann folgendes Skript (backupGit.sh) genutzt werden:
#!/bin/bash
TIMESTAMP=`date +%Y%m%d-%H%M%S`
SRCDIR=/path/to/GitRepo.git
DESDIR=/path/to/backup
tar -cpzf $DESDIR/GitRepo.git_$TIMESTAMP.tar.gz $SRCDIR
sync
Anschließend wird mit
# export VISUAL=nano; crontab -e
ein Cron-Job eingerichtet, um das Backup-Skript zu wiederkehrenden Zeitpunkten automatisch auszuführen.
Um das Backup-Skript bspw. jeden Sonnabend um 2:00 Uhr auszuführen ist folgender Eintrag für den Cron-Job erforderlich:
0 2 * * * backupGit.sh
Last change: Wed, 22 Aug 2018 16:25:49 +0000
Nachfolgend wird das Erstellen eines Yocto-Images für den Raspberry Pi (als Target) beispielhaft gezeigt.
$ cd
$ mkdir -p yocto/source
$ cd yocto/source
$ git clone -b warrior git://git.yoctoproject.org/poky.git poky
$ git clone -b warrior git://git.openembedded.org/meta-openembedded
$ git clone -b warrior https://github.com/meta-qt5/meta-qt5
$ git clone -b warrior git://git.yoctoproject.org/meta-security
$ git clone -b warrior git://git.yoctoproject.org/meta-raspberrypi
$ git clone -b warrior git://github.com/jumpnow/meta-rpi
Mit dem source
-Befehl werden nun Befehle aus der Datei oe-init-build-env
direkt auf dieser Konsole ausgeführt.
$ source poky/oe-init-build-env ../build
Die Yocto-Build-Tools sollten nun bekannt und das Arbeitsverzeichnis der build
-Ordner sein.
Build-Konfiguration aus meta-rpi
übernehmen:
$ cp ../source/meta-rpi/conf/local.conf.sample conf/local.conf
$ cp ../source/meta-rpi/conf/bblayers.conf.sample conf/bblayers.conf
Image bauen:
$ bitbake qt5-image
Wenn das Bauen wegen eines Moduls fehlschlägt, dann kann folgendes helfen:
$ bitbake -c cleansstate <module_name>
Nachfolgend wird davon ausgegangen, dass die SD-Karte als /dev/sdb eingehangen ist.
SD-Karte mit 2 Partitionen formatieren:
$ sudo ./mk2parts.sh sdb
Umgebungsvariablen für die nachfolgenden Skripte setzen:
$ export OETMP=~/rpi/build/tmp
$ export MACHINE=raspberrypi3
Es kann sein, dass die Partitionen der SD-Karte automatisch gemountet werden. Damit die nachfolgenden Skripte erfolgreich arbeiten müssen diese ausgehangen werden.
$ umount /dev/sdb1
$ umount /dev/sdb2
Boot-Partition schreiben:
$ ./copy_boot.sh sdb
System-Partition schreiben:
$ ./copy_rootfs.sh sdb qt5 rpi3
Nachdem nach ein Yocto-Image für das Target-Gerät gebaut hat, möchte man i.d.R. unter einem Host für das Target Software cross-kompilieren, deployen und debuggen können. Dazu muss das Sysroot mit den Target-Header und die entsprechenden Cross-Compiler auf dem Host verfügbar sein. Diese lassen sich auch über das Yocto-Buildsystem für den Host wie folgen bauen.
$ source poky-rocko/oe-init-build-env ~/rpi/build
$ bitbake qt5-image -c populate_sdk
Generiert wurde nun ein Shell-Skript unter ${TMPDIR}/deploy/sdk. Die Installation erfolgt durch deren Ausführung:
$ sudo poky-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-vfpv4-toolchain-2.1.1.sh
Last change: Mon, 19 Aug 2019 14:44:24 +0000
Alle Packages die über Pacman installiert werden, werden in /var/cache/pacman/pkg
heruntergeladen. Dort findet man also alle Packages die bisher installiert wurden (sofern der Cache nicht gelöscht wird).
Falls ein installiertes Package Probleme bereitet, kann man einfach auf eine ältere Version des Package aus dem Cache wie folgt downgraden:
$ cd /var/cache/pacman/pkg
# pacman -U package-version.pkg.tar.xz
Im Falle dass man den Kernel downgraden möchte sollte man neben dem Package linux
auch linux-headers
und Kernelmodule wie z.B. virtualbox-host-modules-arch
downgraden.
Last change: Wed, 17 Jan 2018 10:49:57 +0000
# pacman -S noto-fonts noto-fonts-extra noto-fonts-cjk noto-fonts-emoji
Global Shortcuts:
WIN+D -> Show Desktop
WIN+E -> Open Explorer
WIN+L -> Lock Screen
WIN+X -> Open Settings
CTRL+ALT+Left -> Go to left Desktop
CTRL+ALT+Right -> Go to right Desktop
Last change: Fri, 15 Mar 2024 18:59:07 +0000
Keyboard Layout setzen:
# loadkeys de-latin1-nodeadkeys
Keyring updaten:
# pacman -Sy archlinux-keyring
Arch Linux interaktiv installieren:
# archinstall
Last change: Fri, 15 Mar 2024 18:59:07 +0000
This is bold and this is strong. This is italic and this is emphasized.
This is superscript text and this is subscript text.
This is underlined and this is code: for (;;) { ... }
. Finally, this is a link.
Fringilla nisl. Donec accumsan interdum nisi, quis tincidunt felis sagittis eget tempus euismod. Vestibulum ante ipsum primis in faucibus vestibulum. Blandit adipiscing eu felis iaculis volutpat ac adipiscing accumsan faucibus. Vestibulum ante ipsum primis in faucibus lorem ipsum dolor sit amet nullam adipiscing eu felis.
i = 0;
while (!deck.isInOrder()) {
print 'Iteration ' + i;
deck.shuffle();
i++;
}
print 'It took ' + i + ' iterations to sort the deck.';
Name | Description | Price |
---|---|---|
Item One | Ante turpis integer aliquet porttitor. | 29.99 |
Item Two | Vis ac commodo adipiscing arcu aliquet. | 19.99 |
Item Three | Morbi faucibus arcu accumsan lorem. | 29.99 |
Item Four | Vitae integer tempus condimentum. | 19.99 |
Item Five | Ante turpis integer aliquet porttitor. | 29.99 |
100.00 |
Name | Description | Price |
---|---|---|
Item One | Ante turpis integer aliquet porttitor. | 29.99 |
Item Two | Vis ac commodo adipiscing arcu aliquet. | 19.99 |
Item Three | Morbi faucibus arcu accumsan lorem. | 29.99 |
Item Four | Vitae integer tempus condimentum. | 19.99 |
Item Five | Ante turpis integer aliquet porttitor. | 29.99 |
100.00 |
This Website is based on a template from HTML5 UP.
Die Inhalte dieser Website wurden mit größter Sorgfalt erstellt. Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte kann ich jedoch keine Gewähr übernehmen. Als Diensteanbieter bin ich gemäß § 7 Abs. 1 TMG für eigene Inhalte auf dieser Website nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG bin ich als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werde ich diese Inhalte umgehend entfernen.
Meine Website enthält Links zu externen Webseiten Dritter, auf deren Inhalte ich keinen Einfluss habe. Deshalb kann ich für fremde Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Webseiten ist stets der jeweilige Anbieter oder Betreiber verantwortlich. Die verlinkten Websites wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
Die durch den Seitenbetreiber erstellten Inhalte und Werke auf dieser Website unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Website sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Website nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitte ich um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werde ich derartige Inhalte umgehend entfernen.
Die Nutzung dieser Website ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf dieser Website personenbezogene Daten (beispielsweise Name, Anschrift oder Email-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben.
Ich weise darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per Email) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Der Betreiber dieser Website behält sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.