Overig / Notes
- Leerplein
- ROCvA
- Bookstack
- Youtube Videos
- Lesplanning - Max
- CamStudio
- Langs de Kromme Mijdrecht
- Scrum
- GIT - cheat sheet
- CheckList
- Ontkalken
- KT3 Upload website
- examen.ovh
- Backup DB
- Garmin
- Ostrogorski Paradox
- Running Numbers
- Mail alias in Google
- Nutriscore
- Slide Show Pictures (HTML/CSS en JS)
- python email merge
- Max-Quiz
- Wix
- PHP en GMAIL
- Brand-Brothers Forms
- SSH Checklist
- Books
- Grid View - Max MVC
Leerplein
Doel Leerplein
- leert zelfstandig te plannen en te werken volgens een planning;
- leert zelfstandig dingen uitzoeken (met behulp van informatie van het internet);
- leert samenwerken en elkaar helpen;
- huiswerk (af)maken.
Regels Leerplein
- Leerplein is verplicht.
- Leerplein is in de eerste plaats om je huiswerk te maken voor je AO/Software Development vakken.
- Als je de leerpleinuren anders wilt besteden dan is daar ruimte voor maar dat moet wel in overleg met de docenten en het dient in je planning (volgend punt) te worden opgenomen.
- Tijdens de leerpleinuren maak je een planning in Excel, zie bijlage.
In de planning plan je werk voor de komende drie uur.
Aan het eind van de drie uur bepaal je in hoeverre je je planning hebt gehaald. Dat vul je weer in.
Je planning lever je na elk leerplein-les in via Teams 'Leerplein'. Je planning en werkhouding tijdens de les wordt beoordeeld! - Tijdens leerplein werk je zelfstandig; als je er niet uit komt dan ga je zefl op onderzoek uit, daarna vraag je je klasgenoot en pas in de laatste plaats vraag je hulp aan één van de docenten.
- Als je al het AO huiswerk af hebt dan mag je: ander huiswerk maken, aan andere IT projecten werken of de AO docenten hebben extra plus werk.
--
ROCvA
Rooster koppelen aan Agenda
Hoe koppel ik mijn Rooster aan mijn ROCvA agenda?
- Ga naar EduArte Classic
- Onder Home, ga naar instellingen - Agenda
- Kopieer link (eventueel eerst key/sleutel genereren)
- Ga naar de online versie van Outlook
- Ga naar kalander
- Kies import kalender - Kies from Web
- Vul de gekopieerde link in en Geef de nieuwe kalender een naam.
Sync Issues
Als de koppeling niet werkt kan dat komen door een corrupte OST file.
Repareer dit door de mail en/of calendar folder in Outlook (lokaal) te repareren.
- Right-click the folder, and then click Properties.
- Click Clear Offline Items > OK.
- On the Outlook ribbon, click the Send/Receive tab.
- Click Update Folder.
--
Bookstack
Bookstack
roc.och dev omgeving: http://vps232189.ovh.net/bookstack/public
Bookstack commands
# Create a new admin user
php artisan bookstack:create-admin
# Delete all activity history from the system
php artisan bookstack:clear-activity
# Delete all page revisions from the system
php artisan bookstack:clear-revisions
# Delete all page revisions from the system including update drafts
php artisan bookstack:clear-revisions -a
# Delete all page views from the system
php artisan bookstack:clear-views
# Search and remove images that are not used in page content
php artisan bookstack:cleanup-images
# Generate SQL commands that will upgrade the database to UTF8mb4
# See https://www.bookstackapp.com/docs/admin/ut8mb4-support/
php artisan bookstack:db-utf8mb4
# Rebuild the search index
# Useful if manually inserting pages into the system
php artisan bookstack:regenerate-search
# Regenerate access permissions - Used mostly in development
php artisan bookstack:regenerate-permissions
# Delete all users from the system that are not "admin" or system users
php artisan bookstack:delete-users
# Copy the permission settings of a specified, or all, shelf to their child books
php artisan bookstack:copy-shelf-permissions --all
php artisan bookstack:copy-shelf-permissions --slug=my_shelf_slug
Set rechten op directories (Centos)
chown -R apache:max ./public/uploads/images/
chown -R apache:max ./storage/uploads/files/
chmod -R 775 ./public/uploads/images/
chmod -R 775 ./storage/uploads/files/
Set rechten op directories (Ubuntu)
chown -R www-data:max ./public/uploads/images/
chown -R www-data:max ./storage/uploads/files/
chmod -R 775 ./public/uploads/images/
chmod -R 775 ./storage/uploads/files/
x
Youtube Videos
Alle video's ter ondersteuning van onderwijs ROC
Alles
https://www.youtube.com/playlist?list=PLBU_XXNTKkBoD2pUPw8GR8VF51mc0z67U
Alleen Linux
https://www.youtube.com/playlist?list=PLBU_XXNTKkBrehj5Tcax4itW85cY5xMSr
Alleen SQL
https://www.youtube.com/playlist?list=PLBU_XXNTKkBordjKWRgH5XqF7I9Z26Cn8
Alleen PHP
https://www.youtube.com/playlist?list=PLBU_XXNTKkBrJ2kDna9tAAEJPbJBFQlZ-
Lesplanning - Max
Laatste week Periode 3
ma 20-4
8A - PHP | Examens uitleggen - voorschot nemen naar nieuw rooster Cijfers Opdr 1: Code aanpassen -> Corona opdracht Opdr 2: Na de vakantie -> OOP, PDO CRUD |
9a - PHP | cijfers - Eindcijfer (overgang): huiswerk - mondeling - portfolio nieuw rooster uitleggen Opdracht Portfolio (uitleg site/Les) en Bankrekening (deadline) |
9B - PHP | |
9C - PHP |
di 21-4
9A IB - SQL | Socrative (extra) test Les Joins afmaken |
9B IB - SQL |
wo 22-4
8A - PHP | Huiswerk maken |
9a - PHP | Huiswerk maken |
9B - PHP | |
9C - PHP |
-- online lessen --
ma 12-3
9A - PHP | Bespreken huiswerk functies en inleiden nieuwe praktijkopdracht simulatie. Bespreken HW LInux 3.2 - opdracht 2f en opdracht 3 |
9B - PHP | Toets PHP 1.1 |
9A - PHP | Toets PHP 1.1 |
IB9A - SQL | 3 nieuwe leerlingen HW verplicht!: Ali, Ayoub en Kamel Toets |
- week 7 -
vr 12-3
8A - Linux |
Uitleg HW PHP En Linux, komende week concentreren op PHP: 2 opdrachten Hoofdstedenspel en dobbelstenen (of indien gewenst bankrekeningnummer) |
9C Linux | uitval ivm Corona - Werken aan les install Apache en Virtual Server |
8A - Linux | uitval ivm Corona - zelfstandig werken en individuele hulp |
8A - PHP | uitval ivm Corona - zelfstandig werken en individuele hulp |
9C - PHP | uitval ivm Corona - Toets PHP 1.1 |
-- Nieuwe richtlijnen Covid-19 --
do 12-3
8A - PHP |
Functions 2a/b - unset array - "samen programmeren" via pseude code
|
9B - PHP |
6.4 Functions en Linux 4.1/4.2 |
9C - PHP |
Huiswerk nabespreken - demo - discipline Voorbespreken PHP Toets volgende week maandag
(PHP) 6.4 Functions (Linux) 4.1 en 4.2 - uitleg |
9ABC |
Leerplein |
wo 11-03
9B Linux |
Voorbespreken PHP Toets volgende week maandag
Huiswerk 3.1 opgave 3 bespreken Huiswerk 3.2 Opgave 2f en 3 en maar 7! Ingeleverd? Waarom?
4.1 Deze week 4.2 Volgende week - wordt afgetekend veel werk |
8B Mentorles | |
IB9B SQL |
Toets bespreken Nieuwe leerlingen? -> HW? |
HW PHP 9C nakijken en voorbereiden voor morgen |
(searchtag planningmax roostermax rmax)
CamStudio
Voor het afnemen van toetsen is het nodig om een schermopname van de toets te laten zien.
Dit kan op verschillende manieren, hier wordt uitgelegd hoe dat kan met CamStudio.
CamStudio
Download and Install
Download de portabel versie: https://portableapps.com/downloading/?a=CamStudioPortable&n=CamStudio%20Portable&s=s&p=&d=pa&f=CamStudioPortable_2.7.2_English.paf.exe
"Installeer" de software, feitelijk wordt de software nu alleen uitgepakt.
Start de software op en configureer een paar zaken. Omdat de software niet is geïnstalleerd moet je via de verkenner/explorer zelf naar de juiste folder CamStudioPortable toe gaan en de CamStudioPortable.exe opstarten.
Configuratie
1. Zet de region op Full Screen.
4. Kies Options - Program Options - Name of Avi File - Automatic file naming
Opname maken
Druk op de rode record button om de opname te starten.
Druk op de blauwe stop button (rechts naast de record button) om de opname te stoppen.
--
Langs de Kromme Mijdrecht
Via Ouderkerk aan de Amstel of via de Ouderkerkerplas ga je naar Abcoude, bij Abcoude langs het spoor en uiteindelijk de weg langs het Amsterdam Rijnkanaal op richting het zuiden, Breukelen en Utrech).
Breukelen onder he spoor en A2
Bij Breukelen naar rechtsen dan de A2 onderdoor
Ventweg langs N401
Weg volgen tot aan rotonde
Vlak na de rotonde her dorpje Portengensebrug
Eerste links
Verlaten weg
Deze weg volgens en je komt dan langs een gemaal/sluisje (?) en dan op een weg langs een 'riviertje, de Geer. De Geer is links van je. Deze weg volgen. Ergens moet je nog een keer de N212 oversteken, rechtdoor en je volgt het water gewoon. Tot aan een de T-splitsing bij de witte brug aan de linkerkant, deze brug gaat over de Geer.
Witte brug de Geer over
Woerdense Verlaat, Amstelkade rechts
Nadat je rechts bent gegaan, de Amstelkade in Woerdense Verlaat
Scrum
Scrum Begrippenlijst
Het Scrumteam kent 3 rollen die elkaar complementeren in verantwoordelijkheden zodat er een optimale samenwerking kan worden bewerkstelligd.
Ontwikkelteam
Een zelf organiserend, multidisciplinair team, bestaande uit vijf tot negen leden, dat alle items op de product backlog ontwikkelt tot werkende (deel)producten.
Product Owner
Vertaalt alle klantwensen naar wat er geleverd moet worden. Hiervoor gebruikt de product owner de product backlog waarin zij bepaalt wat de hoogste prioriteit heeft.
Scrum Master
Faciliteert de product owner en het ontwikkelteam gedurende het proces. Zij zorgt ervoor dat iedereen begrijpt hoe scrum werkt en dat alle impediments (hobbels op de weg) die het proces vertragen en/of hinderen worden weggenomen.
Sprint meetings
Al het werk dat gedaan moet worden is georganiseerd in 4 herhalende sprints van ieder 2 weken per sprint.
Tijdens elke sprint vinden er 4 sprint meetings (ceremonies) plaats, die de mogelijkheid bieden om het proces voortdurend aan te passen aan de omstandigheden.
Sprintplanning
Elke sprint begint met een sprintplanning waarin de product owner de opdracht voor de sprint geeft en het ontwikkelteam het werk voor de sprint plant.
Daily Scrum
Een korte dagelijkse bijeenkomst van hooguit 15 minuten waarin het ontwikkelteam de voortgang en de obstakels bespreken.
Sprint Review
Aan het eind van de sprint presenteert het ontwikkelteam de resultaten en krijgt het feedback van betrokkenen, zoals klanten, managers en collega’s.
Sprint Retrospective
Ter afronding van de sprint wordt het proces geëvalueerd met als doel het proces te verbeteren met het oog op de volgende sprint.
Termen en Overzichten
Product backlog
een lijst van al het werk dat gedaan moet worden om een product te creëren en onderhouden. De product owner beheert en prioriteert de product backlog.
Sprint backlog
een overzicht van het geselecteerde werk uit de product backlog dat het ontwikkelteam wilt realiseren gedurende de aankomende sprint.
Definition of done
een lijst met vereisten waaraan een item van de sprint backlog moet voldoen om als voltooid te worden aangemerkt.
Scrumbord
een bord met 3 kolommen (soms 4): (‘Backlog’),‘to do’, ‘doing’ en ‘done’. Hierop worden de taken die op de sprint backlog staan (vaak in de vorm van post-its) weergegeven die door teamleden zijn opgepakt.
Sprint Burndown Chart
een grafiek met de voorraad werk per dag. Als het goed is, zie je een dalende lijn die aan het eidn van de sprint op 0 moet uitkomen.
User Story
Een user story is een korte beschrijving van een onderdeel van een product, beschreven vanuit het oogpunt van de eindgebruiker. Het heeft de structuur: Als (wie?), wil ik (wat?), zodat ik (waarom?).
GIT - cheat sheet
Install (Windows)
https://git-scm.com/
https://desktop.github.com/
set up new repo
(create git repo in web gui first)
git init
git add .gitignore
touch README.md
git add README.md
git remote add myOrigin git@github.com:maxbis/examengesprekken
git push -u origin master
ssh key
add ~/.ssh/id_rsa.pub in git hub web gui
add file
git add <file name>
update repo
git commit -a -m "comment"
git push
Get updated files
git pull
Overwrite local changes
git reset --hard
git pull
New clone - install new
git clone https://github.com/maxbis/examengesprekken
// for Ubuntu server
sudo chgrp -R www-data examengesprekken
Go to older version
git reset --hard 0ad5a7a6.....
Git clear cache (if ignore file is changed)
git rm --cached config
List all tracked files
git ls-tree -r HEAD --name-only
Git issues with .ignore
git rm -r --cached .
git add .
git commit -m "Stop tracking files that are now ignored"
Init new repo
cd path/to/class-cloud
git init
git add .
git commit -m "Initial commit"
<create new repo on githib>
git remote add origin https://github.com/maxbis/class-cloud.git
git push -u origin master
<on Linux>
git clone https://github.com/maxbis/class-cloud.git
CheckList
Yii
1. XAMPP is recent - jun 2019 of nieuwer
2. PHP is maar één keer geïnstalleerd.
- check path variabele (cmd box 'path')
Er mag maar een verwijzing zijn naar een php directory.
Meer details zijn te vinden op: https://www.roc.ovh/books/yii/page/trouble-shooting-yii-installatie
3. Yii2 Model generator werkt
De model generator werk, http://localhost:8080/gii/model
Vereisten: (1) Yii is geïnstalleerd, (2) XAMPP is up-to-date, (3) PHP van XAMPP wordt gebruikt (zie trouble shoot page), (4) database draait en (5) database is in Yii geconfigureerd en geïmporteerd (zie les 1)
ERD
1. Iedereen heeft een login op Lucichart
Student mag andere tool gebruiken, dan graag noteren welke.
Functioneel Ontwerp
1. Wireframe
( Licence key voor desktop versie op verzoek via Teams verkrijgbaar )
2. Tool overzicht
Alles studenten dienen dit helder te hebben en wij moeten de voorbeelden afvinken.
Wat | Hoe - Tool | Voorbeeld gezien |
ERD voor TO | ||
Wireframe voor FO (dat is grove schets v/d lay-out) | ||
Uivoerontwerp; proto-type output scherm | ||
Formulierontwerp; proto-type form (invoerscherm) | ||
Navigatie structuur - flow diagram |
Zie instructie in les welke tool je kan gebruiken.
De keuze van tools is verder vrij, mits er wordt aangetoond dat de student in staat is de gevraagde diagrammen te maken.
--
Ontkalken
- filter verwijderen
- 100 ml (level A) onkalkingsmiddel + 1 liter water (level B)
- Stoompijpje en koffieruitloop onder grote bak
- Toets "druppels" onder stoomknop 5 sec indrukken
- Stoomlampje knippert -> stoomkraan open zetten
- ong. 25 m. wachten
- Lampjes (stoom en kannetje) knipperen - stoomkraantje uit - vers water - stoomkraantje weer aan
- Zelfde als stap 7 maar nu met filter
KT3 Upload website
Maak lijst met kandidaten in Excel, met alle studenten nummers en verzin/generate wachtwoorden.
Maak een text input file met userid's en passwords (gescheiden door spatie).
Scipts ran on Ubuntu Server VPS
SFTP restriction
in /etc/ssh/sshd_config (aan eind toevoegen).
Match Group sftp
ForceCommand internal-sftp
ChrootDirectory %h
AllowTCPForwarding no
PermitTunnel no
X11Forwarding no
Werkt niet goed - uiteindelijk opgelost met standaard rechten:
drwxr-xr-x 14 root root 4096 Jul 26 2020 var/
drwxrwxr-x 9 root www-data 4096 Nov 30 10:28 www/
drwxr-x--x 78 max root 4096 Feb 4 21:12 softwaredeveloper/
drwxr-x--x 4 u515 sftp 4096 Feb 5 16:15 u515/
(group root werkt ook)
-rw-rw-r-- 1 u515 sftp 38 Feb 3 19:42 index.php
(group root werkt ook)
Note group sftp only needed if ssh restriction are aplied
Readme
input file consists out of line with
<userid> <password>
add users
run addUser.sh <file>
run creatDBUsers.sql file; sudo mysql < createDB Users.sql
remove
run removeUser.sf <file>
go to php myadmin and delete dabases and users (no script but easy with gui)
Script add users
#!/bin/bash
# Script to add a user to Linux system
# Params <user> <passw> or <file>
DB_FILE=createDBUsers.sql
addThisUser() {
if [ $(id -u) -eq 0 ]; then
echo "" >> $DB_FILE
if [ "$1" == "" ]; then
read -p "Enter username : " username
else
username=$1
fi
if [ "$2" == "" ]; then
read -s -p "Enter password : " password
else
password=$2
fi
egrep "^$username" /etc/passwd >/dev/null
if [ $? -eq 0 ]; then
echo "$username exists!"
exit 1
else
U_HOME=/var/www/softwaredeveloper/$username
U_GROUP=sftp
U_SHELL=/bin/bash
pass=$(perl -e 'print crypt($ARGV[0], "password")' $password)
useradd -d $U_HOME -g $U_GROUP -m -s $U_SHELL -p $pass $username
[ $? -eq 0 ] && echo "User $username has been added to system!" || echo "Failed to add a user!"
chown $username $U_HOME
echo "<?php echo \"welkom $username\"; ?>" > $U_HOME/index.php
chown $username $U_HOME/index.php
echo "" >> $DB_FILE
echo "CREATE USER \`$username\`@\`%\` IDENTIFIED BY '$password';" >> $DB_FILE
echo "ALTER USER \`$username\`@\`%\` REQUIRE NONE;" >> $DB_FILE
echo "CREATE DATABASE IF NOT EXISTS \`$username\`;" >> $DB_FILE
echo "GRANT ALL PRIVILEGES ON \`$username\`.* TO \`$username\`@\`%\`;" >> $DB_FILE
fi
else
echo "Only root may add a user to the system"
exit 2
fi
}
# is parameter is file then read input from file <user> Mpassword>
# else read two command line params
if test -f "$1"; then
while IFS= read -r line
do
addThisUser $line
done < $1
else
addThisUser $1 $2
fi
script del users
#!/bin/bash
# remove user, params <user> or <file>
removeThisUser() {
if [ $(id -u) -ne 0 ]; then
echo "Only root may add a user to the system"
exit 2
fi
if [ "$1" == "" ]; then
read -p "Enter username : " username
else
username=$1
fi
if [ $? -eq 0 ]; then
userdel -r $username
getent group $username || groupadd $username
U_HOME=/var/www/softwaredeveloper/$username
echo "Remove $U_HOME"
fi
}
# is parameter is file then read input from file <user>
# else read command line params
if test -f "$1"; then
while IFS= read -r line
do
removeThisUser $line
done < $1
else
removeThisUser $1 $2
fi
examen.ovh
Verwijderen resultaten uit examanresultaat
Dit doe je als er een kandidaat is beoordeeld die niet heeft meegedaan. Kandidaat moet volledig uit de uitslagenlijst.
DELETE FROM `results`
WHERE studentid in (48, 59, 52, 51, 55, 39, 34, 68,1)
AND formid=18
AND examenid=4
In dit voorbeeld worden alle resultaten van de studenten met id's 48, 59,.... en het formulier id 18 verwijderd. Als je regel 3 weglaat dan worden alle uitslagen van alle formulieren van de student van het examen (in dit voorbeeld id-4) weggehaald.
Beoordelaar1/2 in batch wijzigen
De beoordeling wordt pas naar de beoordeling tabel gekopieerd als die is ge-saved. Op dat moment wordt het commentaar vanuit de forms ook in de beoordeling gekopieerd. Als je de beoordelaars van de gesaved-de beoordelingen wil wijzigen.
update uitslag u
inner join student s on s.id = u.studentid
set beoordeelaar2id = 16
where examenid= 4
and s.klas='8C'
and werkproces = 'B1-K3-W1'
Backup DB
Backup
- 5x per dag wordt een dump van de database op de server gemaakt. -> cron job
- Oude back-up worden verwijderd, de 23:10 back up wordt 400 dagen bewaard,
de andere worden eerder verwijderd. - Elk dag wordt via rsync en ssh (via public/privat keys) de hele document root plus alle database dumps gekopieerd. Script wordt geïnitieerd door NAS.
- Een controle script - nog niet geïmplementeerd.
NAS
Cron job draait om 11:10, 14:10, 17:10, 20:10 en 23:10. Er worden dus 5 DB dumps per dag gemaakt.
# create backup of Bookstack Database
10 23,20,17,14,11 * * * /home/max/mysql/backupDB.sh > /home/max/mysql/backupDB.log 2>&1
Backup Script plus clean up
Script backupDB.sh voor backup
#!/bin/bash
export PATH=/bin:/usr/bin:/usr/local/bin
TODAY=`date +"%d%b%Y"`
TODAY=`date +"%m%d-%H00"`
################################################################
################## Update below values ########################
DB_BACKUP_PATH='/home/max/mysql/Backup-DB'
MYSQL_HOST='localhost'
MYSQL_PORT='3306'
MYSQL_USER='user'
MYSQL_PASSWORD='secret'
DATABASE_NAME='sb_name'
BACKUP_RETAIN_DAYS=180 ## Number of days to keep local backup copy
#################################################################
echo "Backup started for database - ${DATABASE_NAME}"
mkdir -p ${DB_BACKUP_PATH}
mysqldump -h ${MYSQL_HOST} \
-P ${MYSQL_PORT} \
-u ${MYSQL_USER} \
-p${MYSQL_PASSWORD} \
${DATABASE_NAME} | gzip > ${DB_BACKUP_PATH}/${DATABASE_NAME}-${TODAY}.sql.gz
if [ $? -eq 0 ]; then
# remove all files older than 400 days
find ${DB_BACKUP_PATH} -type f -not -name '*.sql.gz' -mtime +400 -exec rm {} \;
# remove all files older than 90 days excpet those made on the 1ste of the month
find ${DB_BACKUP_PATH} -type f -not -name '*01-????.sql.gz' -mtime +90 -exec rm {} \;
# remove all files not created ar 23:00 and older than 10 days
find ${DB_BACKUP_PATH} -type f -not -name '*300.sql.gz' -mtime +10 -exec rm {} \;
echo "Database backup successfully completed"
else
echo "Error found during backup"
exit 1
fi
##### Remove backups older than {BACKUP_RETAIN_DAYS} days #####
find ${DB_BACKUP_PATH}/* -mtime +${BACKUP_RETAIN_DAYS} -exec rm {} \;
NAS Script
(let op dat niet-standaard poorten worden gebruikt ivm security)
TARGET=/volume1/archives/1/
mkdir -p $TARGET/server/var/www
mkdir -p $TARGET/server/home/abc
nohup rsync -av -e 'ssh -p 9999' servername.domain.net:/var/www/* $TARGET/server/var/www &
nohup rsync -av -e 'ssh -p 9999' servername.domain.net:/home/abc/ $TARGET/server/home/abc &
Garmin
Hard reset:
https://www.youtube.com/watch?v=-8vWGDOrn_Q
Ostrogorski Paradox
Ik laat aan de hand van een voorbeeld zien dat als er in een democratie wordt gekozen op een partij en daarmee op een compleet partij-programma, er een verkeerd beeld kan ontstaan van de "wil van de kiezer". Deze verstoring zou niet bestaan als de kiezer per onderwerp zou stemmen.
Deze verstoring heeft niets te maken met coalitievorming. Ik werk een voorbeeld uit waarin twee partijen met de verkiezingen meedoen.
Stel je hebt twee partijen de PP = Progressieve Partij en de CP = Conservatieven Partij.
Stel er zijn drie belangrijke onderwerpen, economie (ec), milieu (env) en Europese samenwerking (eur). Stel voor het gemak dat alle onderwerpen even zwaar wegen.
Dit is wat de partijen willen:
Onderwerp | PP, Progressieve partij | CP, Conservatieve partij |
Economie | hervormen (1) | zo houden als het is (0) |
milieu | hervormen (1) | huidig beleid voortzetten (0) |
Europese Samenwerking | meer politieke integratie (1) | houden zoals het is (0) |
De keuzes hervormen of niet worden in het kort weergegeven door 1 of 0.
Er zijn 5 kiezers en die hebben de volgende voorkeuren:
Economie | Milieu | Europese Samenwerking | Stemt (dus)op | |
Kiezer 1 | 0 | 1 | 0 | CP |
Kiezer 2 | 0 | 1 | 0 | CP |
Kiezer 3 | 1 | 0 | 0 | CP |
Kiezer 4 | 1 | 1 | 1 | PP |
Kiezer 5 | 1 | 1 | 0 | PP |
Uitslag | CP wint |
Alleen kiezer 4 en 5 stemmen op de PP omdat zij beiden voor de meerderheid van de onderwerpen het beste passen bij de PP. Bijvoorbeeld kiezer 5 vind voor twee van zijn idealen aansluiting bij de PP en voor maar één bij de CP. Let wel alle onderwerpen tellen even zwaar.
Voor kiezer 1,2 en 3 geldt andersom dat zij de meeste aansluiting vinden bij de CP.
Kiezer 1 | CP | overeenstemming 2/3 punten |
Kiezer 2 | CP | overeenstemming 2/3 punten |
Kiezer 3 | CP | overeenstemming 2/3 punten |
Kiezer 4 | PP | overeenstemming 3/3 punten |
Kiezer 5 | PP | overeenstemming 2/3 punten |
Dus de meeste keizers zullen als zij volledig rationeel kiezen, kiezen voor de CP. De CP wint met 3 tegen 2 stemmen.
"Case closed" of niet?
Laten we per onderwerp eens gaan bekijken hoe de stand is:
Economie | Milieu | Europese Samenwerking | ||
Kiezer 1 | 0 | 1 | 0 | |
Kiezer 2 | 0 | 1 | 0 | |
Kiezer 3 | 1 | 0 | 0 | |
Kiezer 4 | 1 | 1 | 1 | |
Kiezer 5 | 1 | 1 | 0 | |
Uitslag - voorkeur |
PP | PP | CP | PP wint |
- De meerderheid (kiezer 3, 4, en 5) wil de economie hervormen (3 tegen 2). Zij zouden op dit punt kiezen voor de PP.
- Een ruime meerderheid (kiezer 1, 2, 4 en 5) wil het milieu hervormen (4 tegen 1). Zij zouden op dit punt kiezen voor de PP.
- De meerderheid wil de Europese samenwerking niet hervormen (4 tegen 1). Zij zouden op dit punt kiezen voor de CP.
Voor 2 van 3 punten wil de meerderheid dus het beleid van de PP. Het zou dus in het belang van iedereen zijn als de PP zou winnen in de verkiezingen omdat dan de meeste wensen van de kiezers dan worden uitgevoerd. De meerderheid is het immers op 2 van de 3 onderwerpen eens met de PP. Als iedereen rationeel stemt dan wint echter de CP.
Dus in deze denkbeeldige vereenvoudigde situatie waarin iedereen rationeel zou handelen, zou de partij winnen die opgeteld per onderwerp niet de meerderheid zou vertegenwoordigwoordigen.
Dit is slechts een vereenvoudigd voorbeeld met 3 issues en 2 partijen, maar ook in een complexere situatie geldt hetzelfde. Als de kiezers stemmen op de partij die het meest bij hun past, dan kan er als je alle issues zou optellen en eventueel zou wegen een verkiezingsuitslag komen die niet optimaal is voor de gemiddelde kiezer.
Dus deze paradox laat zien dat er een vervorming van de "wil van de kiezer" kan ontstaan als er gekozen wordt op een compleet partij-programma in plaats van dat er op aparte onderwerpen zou worden gekozen.
of in het Engels (quote van second.wiki):
The paradox shows that there can be strong distortions of the “will of the electorate” in elections and votes when votes are taken on entire party programs and not (separately) on individual issues.
Bronnen
www.pigozzi.org/Episteme_Pigozzi.pdf
https://second.wiki/wiki/ostrogorski-paradox
--
Running Numbers
Gewicht
Op de 10KM scheelt elke kilo meer gewich iets meer dan 30 seconden.
Weight | Estimated Time | Time Difference |
---|---|---|
67kg | 42:23 | - 02:37 |
68kg | 42:55 | - 02:05 |
69kg | 43:26 | - 01:34 |
70kg | 43:58 | - 01:02 |
71kg | 44:29 | - 00:31 |
72kg | 45:00 | - |
73kg | 45:31 | + 00:31 |
74kg | 46:02 | + 01:02 |
75kg | 46:33 | + 01:33 |
76kg | 47:04 | + 02:04 |
77kg | 47:35 | + 02:35 |
Gewicht schoenen
Elke 100 gram scheelt iets minder dan 1% snelheid.
Caloriegebruik
Aantal kilometer X gewicht ~ calorie gebruik.
Calculators: https://runbundle.com/tools/
Mail alias in Google
Het werkt als volgt.
Ga naar ‘tandwieltje’/settings
Account and Import
Add another email address (waar we ook zaten)
Vul in:
smtp.google.com
jouw email, dus laura.bisschop@gmail.com
wachtwoord (alleen als je geen 2FA aan hebt staan, anders lees verder hieronder)
dan wachtwoord als je GEEN 2FA aan hebt staan (2FA is twee factor authenticatie).
Heb je wel 2FA aan staan dan wordt het lastiger:
In een ander window click op google-account (op je fotootje).
Manage your google account
(links) Security (4de optie?)
Dan onder signing in to Google, App password
(opnieuw aanloggen)
select een app en een device (beiden zijn puur een label, dus verzin wat).
Dan druk je op generate en je krijgt een wachtwoord:
Dat ziet er zo uit:
Dat wachtwoord in dat gele vlak kun je dan copy/past en dat is jouw wachtwoord voor in dat andere window.
Bewaar dit wachtwoord even, want het gaat soms mis (de smtp server is vaak druk).
Probeer het dus opnieuw als het niet lukt.
Uiteindelijk lukte het, dan krijg je een window voor een verificatie-code. Die krijg je in 1 a 2 minuten via mail.
Success!
Niet vergeten.....
O ja en als alles werkt dan kun je dat (tijdelijke) wachtwoord weer beter weghalen. Het is niet meer nodig. Het was alleen nodig voor de verificatie email.
Wachtwoord kun je weghalen op dezelfde plaats als waar jehet hebt aangemaakt. Spreekt voor zich: gewoon op het prullenmandje clicken.
Nutriscore
De berekening van de Nutriscore
Er zijn op landniveau verschillen voor bepaalde productgroepen zoals kazen, olijfolie, ....
Stap 1, negatieve- en positieve punten
Bron: https://blog.has.nl/voedselkeuzelogo-2-het-nutri-score-algoritme/
Stap 2, punten omzetten in score
Bron: https://www.colruytgroup.com/en/conscious-consuming/nutri-score
Slide Show Pictures (HTML/CSS en JS)
Hoe maak je een slide show?
Opacity
Je hebt 4 images en via de CSS heeft elke img een opacity van 0 en is daarmee doorzichtig.
Class Active
Het enige plaatje dat je ziet, is het plaatsje dat via de class active een opacity van 1 heeft gekregen.
Javascript
Het JavaScript zorgt ervoor dat het plaatje de class active wordt weggehaald (remove) en dat het volgende plaatje de class active krijgt.
Via de transition in de CSS wordt de overgang van het ene naar het andere plaatje op 0.5 seconden gezet. Het JS loopt oneindig door en ververst elke 3000 ms (=3 seconden) het plaatje.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rotating Images</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="slideshow">
<img src="image1.jpg" alt="Image 1" class="active">
<img src="image2.jpg" alt="Image 2">
<img src="image3.jpg" alt="Image 3">
<img src="image4.jpg" alt="Image 4">
</div>
<script src="script.js"></script>
</body>
</html>
CSS
.slideshow {
position: relative;
width: 300px; /* Adjust based on your image's width */
height: 200px; /* Adjust based on your image's height */
overflow: hidden;
}
.slideshow img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s;
}
.slideshow img.active {
opacity: 1;
}
JavaScript
let currentImageIndex = 0;
const images = document.querySelectorAll('.slideshow img');
const totalImages = images.length;
setInterval(() => {
// Hide the current image
images[currentImageIndex].classList.remove('active');
// Move to the next image or loop back to the first one
currentImageIndex = (currentImageIndex + 1) % totalImages;
// Show the new current image
images[currentImageIndex].classList.add('active');
}, 3000); // Change the images every 3 seconds
python email merge
What it does
- Reads data from a CSV file.
- Uses the column named "email" from teh CSV file as the to: address.
- Replaces placeholders in the email text and subject line with corresponding data from the CSV file.
- Sends each customized email through Microsoft Outlook.
How it works
Replace 'your_file.csv'
, standard_email_text
, and standard_subject
with your actual file path and text. The script reads the CSV file, replaces placeholders in the email text and subject line with the corresponding data, and sends the emails.
What you need
- You need to have Microsoft Outlook installed on your system.
- This script assumes the CSV file is well-formed and the headers match the placeholders.
- Python's
win32com.client
library is used for interacting with Outlook, which is Windows-specific. - @Line 28 the standard Excel delimiter is specified, this is depending on local settings and is either , or ;
Example
If the body text contains _index_, _name_, _ leeg_ or _URL_ these are replaced with the values in the corresponding lines. The search and replace is case-sensitive!
Set Outlook to work offline and check the email in the outbox before going back online!
Python Script
import csv
import win32com.client as win32
import sys
# Define your standard email text and subject line here
standard_email_text = """Beste _name_,
Hierbij de persoonlijke link waarmee u de voortgang van _name_ kan volgen:\n_URL_.
Voor het afronden van de studie binnen drie jaar, moeten dit schooljaar 8 blokken worden afgerond.
Groet, ...............
(deze email is automatisch gegenereerd)
"""
standard_subject = "voortgangsmonitor _name_"
# Function to send email via Outlook
def send_email(recipient, subject, body):
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.Body = body
mail.Send()
# Reading CSV and sending emails
with open('ouderemailC23 .csv', newline='', encoding='utf-8-sig') as csvfile:
reader = csv.DictReader(csvfile, delimiter=';')
for row in reader:
if ( row['email'] == "" ): # no email, skip
continue
email_body = standard_email_text
email_subject = standard_subject
email_to = row['email']
# Replace placeholders in the email text and subject
for key in row:
email_body = email_body.replace(f'_{key}_', row[key])
email_subject = email_subject.replace(f'_{key}_', row[key])
print(f"To: {email_to}")
print(f"Subject: {email_subject}")
print(f"{email_body}\n")
print("-----------------------------------------\n")
# Send the email
send_email(row['email'], email_subject, email_body)
Max-Quiz
Use Case
In a classroom, as a teacher, I want to execute a formative assessment. I want to be able to start a quiz, minimize the change that students help each other and I want to be able to change quizzes, create new ones without much hassle.
Furthermore, I want to monitor the quiz once it is running and I want to be able to spot irregularities during the quiz session.
The commercial product Socrative matches this use case pretty well, but I kept on running into limitations. So I made my own quiz app.
Installation
Clone the repo
git clone https://github.com/maxbis/max-quiz
Update with composer
composer update
Database
Install the MySQL database by importing the file max-quiz-database-plus example_data.sql, note that this files also creates the database for you. If you want to name the database different, please edit the SLQ file.
Create and/or set rights to some directories
Depending on the system you are running on, you might need to create a few directories, since empty directories are not copied with GitHub. Maybe you need to set the file/directory rights, but this depends on your system and your Web server settings.
The framework Yii will give pretty clear hints for this.
The Yii app can be opened by navigating to the web directory, all routes mentioned in this document are relative to this directory.
Students view
The app starts by navigation to the web directory.
If you are not logged in you get a screen to start a quiz, this is the student's view.
A student need to provide his name, class and a password to start the quiz.
Student session
Once a student is started. He will always get the next unanswered questions. You can refresh the page, or do whatever. The sessions kept in a cookie that is valid for 2 hours. This is also the maximum time a student can work on a quiz.
When for what reason the student looses his session (he switched from device a to device b), you can provide the student a link to continue to finish the quiz.
Admin
Go to the login, by navigating to /admin.
The standard database has one admin account, called admin with the password admin.
The management of the users is all standard Yii: navigate to /tbl-user to manage this.
For now only username and password are used.
Quiz Screen
In the quiz screen you can manage the quizzes. Only active quizzes can be started.
Once a quiz is started, it can only be forced to be stopped on a student level.
Progress Screen
Here you can monitor the progress of the quiz. The questions are mixed per student.
By pressing on the progress column ("Progr."), you can edit the submission. You can change the name, class, correct the score, and force the quiz to be finished.
The code in shown in the left column helps to identify a user, since the code is printed in the header of the students working on the quiz.
One all students are finished, you can export the results to Excel.
Questions Screen
In this screen you get a grid with all question. Here you can link/unlink questions to a quiz.
Use the search bars (question and label) to select questions and add these to the quiz.
View complete quiz
On the questions screen, the first part shows the quiz data. The green dot means the quiz is active.
Import/export Questions
From this screen you can go to import and export where you can import/export questions.
The format used is shown in the import screen and can also be seen when exporting a series of questions. Note that only the linked question of the quiz will be exported.
When the optional ID is provided in an import, you can update questions via import/export. Of course, you can also use the GUI.
--
Wix
Een veld op een form op "hidden" zetten.
Als je in de form editor op een veld klikt dan kan je aan de rechterkant de checkbox hidden aan klikken:
Op het form dat de gebruiker ziet, is dit veld dan niet meer zichtbaar.
Via script kan je het veld een waarde geven. In developer mode zie je onderaan een script.
Dit script is standaard 'leeg' en bevat alleen het begin en eind (hetgeen in het voorbeeld hieronder op regel 1 en 4 staat). Een regel die begint met // is een commentaarregel. In het voorbeeld hieronder zijn de commentaarregels verwijderd.
w.onReady(function () {
$w("#input5").value = "Hidden informatie";
$w("#hidden02").value = "Dit is een test";
});
Bovenstaande code zet de waarde van twee velden. Het veld dat hierboven op hidden is gezet heeft een ID #input5 en de waarde wordt "Hidden informatie" (regel 2 van de code). Een ander veld met het ID #hidden02 krijgt ook een waarde op regel 3. Op deze manier kan je elk veld een waarde geven.
--
PHP en GMAIL
In (any) project directory:
composer require phpmailer/phpmailer
Create app password in Google
google account - security 0 2-Step Verification - App passwords
emailer
PHP code (this will accept a posted form and email all form fields).
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
// Your Gmail credentials
$gmailUsername = 'user-name@gmail.com';
$gmailPassword = '16-char-app-password'; // under 2 FA in google account settings
// Recipient email address
$recipientEmail = 'to-user@server.com';
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$emailContent = "Form Submission:\n\n";
foreach ($_POST as $key => $value) {
$emailContent .= "$key: $value\n";
}
$mail = new PHPMailer(true);
try {
// Server settings
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com';
$mail->SMTPAuth = true;
$mail->Username = $gmailUsername;
$mail->Password = $gmailPassword;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
// Recipients
$mail->setFrom($gmailUsername, 'Form Submission');
$mail->addAddress($recipientEmail);
// Content
$mail->isHTML(false);
$mail->Subject = 'New Form Submission';
$mail->Body = $emailContent;
$mail->send();
echo 'Message has been sent';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
}
?>
Form example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Submission</title>
</head>
<body>
<form action="process_form.php" method="post">
<label for="name">Name:</label>
<input type="text" id="name" name="name"><br><br>
<label for="email">Email:</label>
<input type="email" id="email" name="email"><br><br>
<label for="message">Message:</label>
<textarea id="message" name="message"></textarea><br><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
Brand-Brothers Forms
Nieuwe locatie
https://www.roc.ovh/books/brand-brothers
Handleiding
Deze handleiding beschrijft de verschillende parameters die je kunt gebruiken bij het configureren van een bier selectie formulier.
Het form wordt aangeroepen door middel van een URL en alle parameters worden in de URL meegegeven.
Voorbeeld:
https://....../.../brand-brothers/forms/?eigenaar=naam&merk=Texels&set=Texels-vuurtorenbar&minbeers=3&beerfilter=amstel&options=1,2,3,4,25,26&t=1&maxbeers=3
Spaties in URL
In de gehele URL moeten spaties worden gecodeerd als %20
.
Parameters
De parameters zoals in het voorbeeld getoond, worden hieronder beschreven. Elke parameter is rood gemarkeerd.
minbeers
- Beschrijving: Het minimaal aantal bieren dat geselecteerd moet worden.
- Werking: Als er minder bieren zijn geselecteerd dan het minimum, krijg je een waarschuwing wanneer je probeert het formulier te versturen.
maxbeers
- Beschrijving: Het maximaal aantal bieren dat geselecteerd kan worden.
- Werking: Als je meer bieren selecteert dan het maximum, verschijnt er onmiddellijk een waarschuwing.
Verborgen Velden
- Beschrijving: De volgende velden zijn verborgen en kunnen via de URL worden meegegeven. De verborgen velden worden dor het formulier meegestuurd en verschijnen in de email.
- eigenaar: De eigenaar van het biermerk.
- merk: De naam van het biermerk.
- set: De naam van de set die in de titel van het formulier verschijnt.
t (Testmodus)
- Beschrijving: Hiermee kun je de testmodus van het formulier instellen. aan t kunnen de volgende waarden worden gegeven:
- 0: Normale werking (dezelfde als geen waarde opgegeven).
- 1: Alle verplichte velden zijn niet meer verplicht en het formulier wordt niet per e-mail verzonden.
- 2: Alle verplichte velden zijn niet meer verplicht en het formulier wordt wel per e-mail verzonden
options
- Beschrijving: Een lijst van opties die als een komma-gescheiden lijst moeten worden opgegeven. Deze opties worden getoond op het formulier.
beerfilter
- Beschrijving: Een filter om bieren op naam te selecteren.
- Werking: Als de waarde 'none' is, wordt de gehele bierselectie niet getoond. Je kunt meerdere filters specificeren, bijvoorbeeld:
beerfilter=amstel,brand
.
Options aanpassen
Om options aan te passen kan deze URL worden gebruikt:
https://....../.../brand-brothers/forms/options
of nieuwe interface
https://....../.../brand-brothers/forms/options/index2.php
Optienummer
Elke optie heeft een nummer. Aan de hand van dit nummer wordt de optie op het formulieer geplaatst. De nummers hoeven niet uniek te zijn. Wanneer meerdere opties hetzelfde nummer hebben, worden alle opties op het fomrulier getoond wanneer deze optie wordt gekozen.
Optienaam
De naam van de optie is de naam die op de aanvraag verschijnt (email).
Optielabel
Het label is de de naam zoals die op het formulier verschijnt.
Extra naam
De extra naam is de (open) vraag die wordt gesteld indien de optie wordt geslecteerd. De naam is de naam zoals die op het aanvraag (email) verschijnt.
Extra label
Het extra label is de (open) vraag die wordt gesteld indien de optie wordt geslecteerd. Het label is de naam zoals die op het formulier verschijnt.
URL naar options (back-up)
De 'database' waarin de options worden opgeslagen kun je via de volgende URLs controleren:
https://.../.../brand-brothers/forms/options/options.js
https://.../.../brand-brothers/forms/options/options.json
Deze bestanden zou je ook als (extra) back-up kunnen gebruiken.
De twee bestanden bevatten dezelfde informatie, maar zijn om technische redenen op een andere wijze vormgegeven.
Options kunnen niet worden aangepast?
Als de opties niet kunnen worden aangepast, controleer dan de twee bestanden. Zijn de wijzigingen in deze bestanden wel aangepast dan zorgt de cache van de browser ervoor dat de wijzigingen niet (direct) worden getoond. Laadt de pagina dan opnieuw en leeg de browser cache (dit werkt op elke browser anders).
Beers aanpassen
(dit is nog nooit in productie getest)
https://............/brand-brothers/forms/beers
of nieuwe interface
https://............/brand-brothers/forms/beers/index2.php
Een beer heeft een ID en een naam zoals dat op het form te zien is. Zorg ervoor dat de ID's uniek blijven.
Equipmentlist
(in ontwikkeling)
https://..../brand-brothers/equipment-list/folders.php
--
SSH Checklist
SSH Key Setup Checklist
-
Generate SSH Key Pair
- Ensure that you have generated an SSH key pair on the client machine (
system a
).- Run the following command and check for the existence of
~/.ssh/id_rsa
(private key) and~/.ssh/id_rsa.pub
(public key):ls -l ~/.ssh/id_rsa ~/.ssh/id_rsa.pub
- Run the following command and check for the existence of
- If the keys do not exist, generate them using:
ssh-keygen -t rsa -b 4096
- Ensure the keys have appropriate permissions (600 for private and 644 for public keys):
chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub
- Ensure that you have generated an SSH key pair on the client machine (
-
Copy Public Key to Remote Server
- Ensure that the public key has been copied to
system b
and appended to the~/.ssh/authorized_keys
file.- Use the
ssh-copy-id
command to copy the key:ssh-copy-id username@system_b
- Alternatively, you can manually copy the contents of
~/.ssh/id_rsa.pub
to~/.ssh/authorized_keys
onsystem b
.
- Use the
- Verify that the
authorized_keys
file has the correct permissions:chmod 600 ~/.ssh/authorized_keys
- Make sure the
.ssh
directory has the correct permissions:chmod 700 ~/.ssh
- Ensure that the public key has been copied to
-
Check SSH Daemon Configuration on Remote Server
- Ensure the SSH daemon is configured to allow key-based authentication. Check
/etc/ssh/sshd_config
onsystem b
for the following settings:PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
(optional, for enforcing key-based auth only)
- Restart the SSH daemon to apply changes:
sudo systemctl restart sshd
- Ensure the SSH daemon is configured to allow key-based authentication. Check
-
Verify Ownership and Permissions
- Check ownership and permissions of the user's home directory on
system b
:- Ensure that the home directory and
.ssh
directory are owned by the user and have appropriate permissions:chown -R username:username /home/username chmod 700 /home/username/.ssh
- Ensure that the home directory and
- Check ownership and permissions of the user's home directory on
-
Ensure Correct SSH Command Usage
- Use the correct username and hostname when attempting to SSH into
system b
:ssh username@system_b
- If using a non-standard SSH port, specify it using the
-p
option:ssh -p <port_number> username@system_b
- Use the correct username and hostname when attempting to SSH into
-
Check SSH Agent (Optional)
- Ensure that the SSH agent is running and the key is added to it, especially if using
ssh-agent
for key management:eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
- Verify the keys added to the agent:
ssh-add -l
- Ensure that the SSH agent is running and the key is added to it, especially if using
-
Review SSH Debugging Output
- Use the
-v
option with the SSH command to enable verbose mode, which can provide detailed debugging information:bashssh -v username@system_b
- Look for lines indicating whether the key is being offered and any errors that may indicate why the key is being rejected.
- Use the
-
Network Issues
- Ensure there are no network issues preventing the connection. Check that
system b
is reachable via the network. - Verify that the firewall on
system b
is allowing incoming SSH connections on the specified port.
- Ensure there are no network issues preventing the connection. Check that
-
SELinux and AppArmor (Linux Specific)
- If
system b
uses SELinux, ensure it is not blocking SSH connections:sudo setenforce 0 # Temporarily disable for testing
- If using AppArmor, check that it allows SSHD to read the authorized_keys file.
- If
-
Check for Multiple Keys (Optional)
- If multiple keys are present, specify the exact key to use:
ssh -i ~/.ssh/id_rsa username@system_b
- If multiple keys are present, specify the exact key to use:
By following this checklist, you should be able to identify and resolve most issues preventing SSH key-based authentication. If problems persist, examining the verbose output from the SSH command can provide further clues.
Books
-
Black Heart (2018) - read
The first book introduces Detective Dan Riley as he investigates the brutal murder of a woman found dead in a luxury hotel suite. As the investigation unfolds, dark secrets emerge, leading to a web of lies, obsession, and revenge. A thrilling police procedural with psychological elements. -
The Couple on Cedar Close (2019) - read
This novel centers around a seemingly perfect couple, until the wife is found dead and the husband becomes the prime suspect. Detective Riley must dig deeper into their lives to uncover shocking truths that no one saw coming. -
The Stranger's Wife (2020) - read
In this book, two women from vastly different lives find themselves linked by a series of tragic events. Riley works to solve a complex case involving abuse, betrayal, and a violent crime, with plenty of twists and turns along the way. -
The Woman Inside (2021) - read
After surviving a near-fatal attack, Daisey Garrett wakes up in the hospital with no memory of what happened. With the help of Detective Riley, she attempts to piece together the events of that night, while her troubled personal life adds further complications. -
The Night of the Party (2022)
This novel explores the secrets of an elite social circle after a shocking murder at a glamorous party. As Detective Riley investigates, he uncovers hidden grudges and a complex tapestry of deceit. -
The Lie in Our Marriage (2023) - now
The sixth book focuses on a couple celebrating their 25th wedding anniversary, but beneath the surface, their relationship is falling apart. A series of dark secrets and lies unravel, leading to a gripping conclusion as Detective Riley is called to solve yet another mystery. - The Housewife’s Secret (2024) - read
Grid View - Max MVC
Below is sample documentation that explains how to configure each column in your grid. You can include this in your project’s documentation (for example, as a README or developer guide).
Grid Column Data Structure
Each column in the grid is defined as an associative array. The following keys are available:
Required Keys
-
name
Type: string
Description:
The header text shown at the top of the column.
Example:'name' => 'Order ID'
-
data
Type: string
Description:
Specifies how to obtain the value for each cell in this column.- If the value is a plain key (e.g.,
"order_id"
), the cell displays the corresponding value from each record in your data array. - If the value contains tokens enclosed in curly braces (e.g.
"{price} * {quantity}"
), it is treated as a formula. Each token is replaced by the value from the corresponding key in the data record, and the resulting expression is evaluated. Examples:
// Plain data field (must exist in each $data record) 'data' => 'order_id' // Calculated field using tokens 'data' => '{price} * {quantity}'
- If the value is a plain key (e.g.,
Optional Keys
-
width
Type: string
Description:
The width of the column as a CSS value (e.g.,"60px"
or"10%"
).
Example:'width' => '80px'
-
align
Type: string
Description:
Sets the text alignment for the column. Valid values are:"left"
(default)"right"
"center"
Example:
'align' => 'right'
-
formatter
Type: string
Description:
A PHP expression used to format the cell’s value. The expression is evaluated usingeval()
. You can use the variable$item
(or$value
for computed columns) to reference the current cell data.
Example:'formatter' => 'number_format($item["price"], 2, ".", ",")'
When using formulas for the
data
key, the computed value can be formatted by referencing$value
:'formatter' => 'number_format($value, 2, ".", ",")'
-
aggregate
Type: string
Description:
Specifies how to compute an aggregate value for this column (displayed in the footer). Accepted values:"sum"
– calculates the total."average"
– calculates the average.- A formula string (e.g.,
"({YTD_PL} / {VALUE_EUR}) * 100"
) that uses tokens to reference computed aggregate values from other columns. Example:
// Standard aggregate (sum) 'aggregate' => 'sum', // Aggregate based on a formula 'aggregate' => '({YTD_PL} / {VALUE_EUR}) * 100'
-
aggregateToken
Type: string
Description:
Used when the computed aggregate value of this column needs to be referenced in another aggregate formula. When provided, the calculated value is stored in a global object (or passed to JavaScript) under this token name.
Example:'aggregateToken' => 'YTD_PL'
-
sortable
Type: boolean (or integer with values 0/1)
Description:
Indicates whether the column is sortable by clicking on the header.
Example:'sortable' => true
-
filter
Type: string
Description:
Specifies the type of filtering available for the column. Valid values are:"none"
– no filter input."select"
– a dropdown list of unique values."text"
– a text input for filtering. Example:
'filter' => 'text'
-
hide
Type: boolean
Description:
Determines whether the column is visible in the rendered grid. If set totrue
, the column is hidden from the user view via CSS (display: none
), but it remains in the DOM so that its data is still available for calculations (such as aggregates or formulas).
Example:'hide' => true
Example of a Complete Column Configuration
Below is a sample array of columns that demonstrates how to configure different aspects:
$columns = [
[
'name' => 'Order ID',
'data' => 'order_id',
'width' => '80px',
'align' => 'left',
'sortable' => true,
'filter' => 'text',
],
[
'name' => 'Customer',
'data' => 'customer_name',
'width' => '150px',
'align' => 'left',
'sortable' => true,
'filter' => 'select',
],
[
'name' => 'Price',
'data' => 'price',
'width' => '80px',
'align' => 'right',
'formatter' => 'number_format($item["price"], 2, ".", ",")',
'aggregate' => 'sum',
'sortable' => true,
'filter' => 'none',
],
[
'name' => 'Quantity',
'data' => 'quantity',
'width' => '60px',
'align' => 'right',
'aggregate' => 'sum',
'sortable' => true,
'filter' => 'none',
],
[
'name' => 'Total',
'data' => '{price} * {quantity}', // Calculated column using tokens
'width' => '100px',
'align' => 'right',
'formatter' => 'number_format($value, 2, ".", ",")', // $value refers to the computed total
'aggregate' => 'sum',
'sortable' => false,
'filter' => 'none',
],
[
'name' => 'Secret Code',
'data' => 'secret_code',
'hide' => true, // Hidden from the view but used for calculations or references
'sortable' => false,
'filter' => 'none',
],
];
Notes
-
Formulas in
data
oraggregate
:
When using a formula, ensure that tokens (e.g.,{price}
or{quantity}
) exactly match the keys in your data records. If a token is missing, you may get unexpected results or errors. -
DOM and Calculations:
Even if a column is hidden (hide
is set totrue
), it is still rendered in the DOM (using a CSS class such ashidden-col
withdisplay: none
). This is important so that JavaScript functions that perform calculations (such as aggregate totals) can still access the values. -
Formatter Security:
Sinceformatter
is evaluated usingeval()
, make sure that any code provided is trusted and controlled. Do not use untrusted input in these expressions.
This documentation provides an overview of how to set up and customize the grid’s column definitions. Adjust the examples to match your application’s needs, and feel free to extend the configuration with additional keys or logic as required.