forked from axiom-team/g1-stats
Cleaning code, ready to publish
This commit is contained in:
parent
82ae843307
commit
50c41e54b3
|
@ -0,0 +1,24 @@
|
||||||
|
# Extraction de quelques chiffres liés à la ḡ1
|
||||||
|
### Visible sur: [https://g1-stats.axiom-team.fr/](https://g1-stats.axiom-team.fr/)
|
||||||
|
|
||||||
|
*Ce code n'a pas été testé dans un autre environement que le miens, il est publié par simple soucis de transparence et d'audit*
|
||||||
|
|
||||||
|
Utilise l'API BMA pour l'extraction des clés publiques ḡ1 membres et non membres, ainsi que l'API ElasticSearch de Cesium+ pour la récupération des soldes par soucis d'optimisation.
|
||||||
|
Les variables d'environnements se trouvent simplement en début de script. Il est nécessaire de les modifier avant l'execution.
|
||||||
|
|
||||||
|
A exécuter dans un environnement Bash Debian/Ubuntu.
|
||||||
|
|
||||||
|
## Exécution
|
||||||
|
|
||||||
|
`./g1-stats.sh`
|
||||||
|
|
||||||
|
Pour générer la page web static:
|
||||||
|
|
||||||
|
`./g1-stats.sh web`
|
||||||
|
|
||||||
|
## Automatisation
|
||||||
|
|
||||||
|
Vous pouvez décider d'exécuter ce script régulièrement grâce à une tache cron.
|
||||||
|
Par exemple pour l'exécuter toutes les 3 heures:
|
||||||
|
|
||||||
|
`echo "0 */3 * * * /path/to/script/g1-stats.sh web >> /var/log/g1-stats.log 2>&1" >> /var/spool/cron/crontabs/$USER`
|
|
@ -0,0 +1,5 @@
|
||||||
|
<br>
|
||||||
|
<a href="/">Revenir à l'accueil</a>
|
||||||
|
</center>
|
||||||
|
</div>
|
||||||
|
</html>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<title>Historique des stats Ḡ1</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="stylesheet" href="../css/style.css" type="text/css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="statsHistory">
|
||||||
|
|
||||||
|
<center>
|
|
@ -0,0 +1,93 @@
|
||||||
|
body {
|
||||||
|
background-color: #c4a787;
|
||||||
|
margin: 30px;
|
||||||
|
font-family: "Gill Sans", sans-serif;
|
||||||
|
min-width: 1100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: "Gill Sans", sans-serif;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainbloc, #statsHistory {
|
||||||
|
margin-top: 60px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 300px;
|
||||||
|
margin-right: 300px;
|
||||||
|
padding: 20px;
|
||||||
|
min-width: 300px;
|
||||||
|
background-color: #DFCFBE;
|
||||||
|
border-radius: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.columnTitle {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previous, .next {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
color: black;
|
||||||
|
opacity: 0.3;
|
||||||
|
width: 50px;
|
||||||
|
height: 60px;
|
||||||
|
font-size: 3em;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 30%;
|
||||||
|
top: 45%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next {
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1100px) {
|
||||||
|
body {
|
||||||
|
margin: 15px;
|
||||||
|
margin-top: 30px;
|
||||||
|
min-width: 0px;
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
#mainbloc {
|
||||||
|
margin: 5px;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
font-size: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previous, .next {
|
||||||
|
font-size: 2em;
|
||||||
|
top: 5%;
|
||||||
|
width: 15px;
|
||||||
|
height: 55px;
|
||||||
|
border-radius: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.previous {
|
||||||
|
left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.next {
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,20 +1,20 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
startTime=$(date +'%H:%M')
|
|
||||||
day=$(date +'%d-%m-%y')
|
|
||||||
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
|
|
||||||
de=$(cat /dev/urandom | tr -dc '0-9' | fold -w 1 | head -n 1)
|
|
||||||
### Variable ###
|
### Variable ###
|
||||||
|
|
||||||
DUNITER="http://192.168.9.54:45000"
|
DUNITER="http://192.168.9.54:45000"
|
||||||
DUNITER2="https://g1.duniter.org"
|
DUNITER2="https://g1.duniter.org"
|
||||||
DUNITER3="https://duniter.g1.1000i100.fr"
|
DUNITER3="https://duniter.g1.1000i100.fr"
|
||||||
|
ESNODE="http://g1.data.duniter.fr"
|
||||||
indexhtml="/var/www/g1-stats/index.html"
|
webLocation="/var/www/g1-stats"
|
||||||
|
scriptLocation="/opt/g1-stats"
|
||||||
###
|
###
|
||||||
|
|
||||||
echo "######"
|
### Initialisation des données ###
|
||||||
echo "$day à $startTime"
|
startTime=$(date +'%H:%M')
|
||||||
|
day=$(date +'%d-%m-%y')
|
||||||
|
id=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
|
||||||
|
indexhtml="$webLocation/index.html"
|
||||||
|
echo -e "\n############# $day à $startTime #############\n"
|
||||||
[[ -z $(which jq) || -z $(which bc) ]] && apt update && apt install jq bc
|
[[ -z $(which jq) || -z $(which bc) ]] && apt update && apt install jq bc
|
||||||
echo "Initialisation ..."
|
echo "Initialisation ..."
|
||||||
outFile="/tmp/g1-stats-$day-$startTime_$id"
|
outFile="/tmp/g1-stats-$day-$startTime_$id"
|
||||||
|
@ -28,14 +28,15 @@ nbrMembers=${#MEMBERS[@]}
|
||||||
lastBloc=${TXBLOCKS[-1]}
|
lastBloc=${TXBLOCKS[-1]}
|
||||||
isWeb=$1
|
isWeb=$1
|
||||||
|
|
||||||
echo "Heure de début: $startTime"
|
### Extraction des adresses Ḡ1 actives ###
|
||||||
|
|
||||||
loopWalletUp() {
|
loopWalletUp() {
|
||||||
for i in ${TXBLOCKS[*]}; do
|
for i in ${TXBLOCKS[*]}; do
|
||||||
[[ -z ${TXBLOCKS[$i]} ]] && break
|
[[ -z ${TXBLOCKS[$i]} ]] && break
|
||||||
sleep 0.1
|
sleep 0.1
|
||||||
WALLETS0=$(curl -s ${DUNITER}/blockchain/block/${TXBLOCKS[$i]})
|
WALLETS0=$(curl -s ${DUNITER}/blockchain/block/${TXBLOCKS[$i]})
|
||||||
until WALLETS=$(echo $WALLETS0 | jq '.transactions[].outputs[]'); do
|
until WALLETS=$(echo $WALLETS0 | jq '.transactions[].outputs[]' 2>/dev/null); do
|
||||||
echo -e "iter $iter \n$WALLETS0"
|
[[ $isWeb != "web" ]] && echo -e "iter $iter \n$WALLETS0"
|
||||||
sleep 2
|
sleep 2
|
||||||
WALLETS0=$(curl -s ${DUNITER}/blockchain/block/${TXBLOCKS[$i]})
|
WALLETS0=$(curl -s ${DUNITER}/blockchain/block/${TXBLOCKS[$i]})
|
||||||
done
|
done
|
||||||
|
@ -60,8 +61,11 @@ loopWalletUp() {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
loopWalletUp
|
loopWalletUp
|
||||||
|
|
||||||
|
### Ecriture des adresses actives dans un fichier tampon ###
|
||||||
echo -e "$(echo -e "$wallets" | sort -u)" > $outFile
|
echo -e "$(echo -e "$wallets" | sort -u)" > $outFile
|
||||||
|
|
||||||
|
### Ajout des membres sans transaction au fichier tampon ###
|
||||||
loopMembers() {
|
loopMembers() {
|
||||||
iter=0
|
iter=0
|
||||||
for i in ${MEMBERS[*]}; do
|
for i in ${MEMBERS[*]}; do
|
||||||
|
@ -87,20 +91,34 @@ done
|
||||||
}
|
}
|
||||||
loopMembers
|
loopMembers
|
||||||
|
|
||||||
|
### Calcul du nombre de wallets ###
|
||||||
nbrTotalWallets=$(cat $outFile | wc -l)
|
nbrTotalWallets=$(cat $outFile | wc -l)
|
||||||
nbrSimpleWallets=$(echo "$nbrTotalWallets-$nbrMembers" | bc)
|
nbrSimpleWallets=$(echo "$nbrTotalWallets-$nbrMembers" | bc)
|
||||||
pourcentMbrs=$(echo "scale=1; $nbrMembers*100/$nbrTotalWallets/1" | bc)
|
pourcentMbrs=$(echo "scale=1; $nbrMembers*100/$nbrTotalWallets/1" | bc)
|
||||||
pourcentWallets=$(echo "scale=1; $nbrSimpleWallets*100/$nbrTotalWallets/1" | bc)
|
pourcentWallets=$(echo "scale=1; $nbrSimpleWallets*100/$nbrTotalWallets/1" | bc)
|
||||||
|
|
||||||
|
### Renseignement de l'index web et indexation de l'historique ###
|
||||||
web() {
|
web() {
|
||||||
cp /opt/g1-stats/stats.html $indexhtml
|
|
||||||
|
[ ! -d $webLocation/history/ ] && mkdir -p $webLocation/history/
|
||||||
|
[ ! -d $webLocation/css ] && cp -r $scriptLocation/css $webLocation/
|
||||||
|
cp $scriptLocation/index-stats.html $indexhtml
|
||||||
|
|
||||||
|
datePrevious=$(echo $day | awk -F '-' '{ print $3 "-" $2 "-" $1 }')
|
||||||
|
datePrevious=$(date +'%y-%m-%d' -d "$datePrevious -1 day")
|
||||||
|
datePrevious=$(echo $datePrevious | awk -F '-' '{ print $3 "-" $2 "-" $1 }')
|
||||||
|
[[ -z $(ls -l $webLocation/history/ | grep $datePrevious) && -z $(grep '"display:none;" class="previous"' $indexhtml) ]] && sed -i "s/class=\"previous\"/style=\"display:none;\" class=\"previous\"/g" $indexhtml
|
||||||
|
dateNext=$(echo $day | awk -F '-' '{ print $3 "-" $2 "-" $1 }')
|
||||||
|
dateNext=$(date +'%y-%m-%d' -d "$dateNext +1 day")
|
||||||
|
dateNext=$(echo $dateNext | awk -F '-' '{ print $3 "-" $2 "-" $1 }')
|
||||||
|
[[ -z $(ls -l $webLocation/history/ | grep $dateNext) && -z $(grep '"display:none;" class="next"' $indexhtml) ]] && sed -i "s/class=\"next\"/style=\"display:none;\" class=\"next\"/g" $indexhtml
|
||||||
|
|
||||||
sed -i "s/_nbrTotalWallets/$nbrTotalWallets/g" $indexhtml
|
sed -i "s/_nbrTotalWallets/$nbrTotalWallets/g" $indexhtml
|
||||||
sed -i "s/_nbrSimpleWallets/$nbrSimpleWallets/g" $indexhtml
|
sed -i "s/_nbrSimpleWallets/$nbrSimpleWallets/g" $indexhtml
|
||||||
sed -i "s/_nbrMembers/$nbrMembers/g" $indexhtml
|
sed -i "s/_nbrMembers/$nbrMembers/g" $indexhtml
|
||||||
sed -i "s/_pourcentMbrs/$pourcentMbrs/g" $indexhtml
|
sed -i "s/_pourcentMbrs/$pourcentMbrs/g" $indexhtml
|
||||||
sed -i "s/_pourcentWallets/$pourcentWallets/g" $indexhtml
|
sed -i "s/_pourcentWallets/$pourcentWallets/g" $indexhtml
|
||||||
# sed -i "s/_node/$DUNITER/g" $indexhtml
|
# sed -i "s/_node/$DUNITER/g" $indexhtml
|
||||||
sed -i "s/_heure/$startTime/g" $indexhtml
|
sed -i "s/_heure/$startTime/g" $indexhtml
|
||||||
sed -i "s/_day/$day/g" $indexhtml
|
sed -i "s/_day/$day/g" $indexhtml
|
||||||
sed -i "s/_txInSimple/$txInSimple/g" $indexhtml
|
sed -i "s/_txInSimple/$txInSimple/g" $indexhtml
|
||||||
|
@ -112,41 +130,40 @@ web() {
|
||||||
sed -i "s/_pourcentSimpleWallet/$pourcentSimpleWallet/g" $indexhtml
|
sed -i "s/_pourcentSimpleWallet/$pourcentSimpleWallet/g" $indexhtml
|
||||||
sed -i "s/_nonConsumedUDT/$nonConsumedUDT/g" $indexhtml
|
sed -i "s/_nonConsumedUDT/$nonConsumedUDT/g" $indexhtml
|
||||||
sed -i "s/_monetaryMass/$monetaryMass/g" $indexhtml
|
sed -i "s/_monetaryMass/$monetaryMass/g" $indexhtml
|
||||||
chown www-data:www-data $indexhtml 2>/dev/null
|
[[ -z $(grep '"display:none;" class="previous"' $indexhtml) ]] && sed -i "s/_datePrevious/$datePrevious/g" $indexhtml
|
||||||
|
[[ -z $(grep '"display:none;" class="next"' $indexhtml) ]] && sed -i "s/_dateNext/$dateNext/g" $indexhtml
|
||||||
|
|
||||||
cat "$outFile" | grep . > /var/www/g1-stats/wallets-g1.txt
|
cat "$outFile" | grep . > $webLocation/wallets-g1.txt
|
||||||
echo -e "${MEMBERS[@]}" | sed 's/ /\n/g' > /var/www/g1-stats/wallets-g1-membres.txt
|
echo -e "${MEMBERS[@]}" | sed 's/ /\n/g' > $webLocation/wallets-g1-membres.txt
|
||||||
echo -e "$simpleWallets" > /var/www/g1-stats/wallets-g1-simple.txt
|
echo -e "$simpleWallets" > $webLocation/wallets-g1-simple.txt
|
||||||
|
|
||||||
if [[ "$startTime" == "00:00" ]]; then
|
if [[ "$startTime" == "00:00" ]]; then
|
||||||
cp $indexhtml /var/www/g1-stats/history/index_$day.html
|
cp $indexhtml $webLocation/history/index_$day.html
|
||||||
sed -i "s/style.css/..\/style.css/g" /var/www/g1-stats/history/index_$day.html
|
sed -i "s/css\/style.css/..\/css\/style.css/g" $webLocation/history/index_$day.html
|
||||||
chown -R www-data:www-data /var/www/g1-stats
|
sed -i "s/_dateNext/$day/g" $webLocation/history/index_$datePrevious.html
|
||||||
|
sed -i "s/style=\"display:none;\" class=\"next\"/class=\"next\"/g" $webLocation/history/index_$datePrevious.html
|
||||||
fi
|
fi
|
||||||
|
chown -R www-data:www-data $webLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### Affichage du nombre de wallets ###
|
||||||
echo -e "\n ---\n"
|
echo -e "\n ---\n"
|
||||||
echo "Noeud: $DUNITER"
|
echo "Noeud: $DUNITER"
|
||||||
echo "Nombre total de wallet: $nbrTotalWallets"
|
echo "Nombre total de wallet: $nbrTotalWallets"
|
||||||
echo "Nombre de membres: $nbrMembers (${pourcentMbrs}%)"
|
echo "Nombre de membres: $nbrMembers (${pourcentMbrs}%)"
|
||||||
echo "Nombre de simple portefeuille: $nbrSimpleWallets (${pourcentWallets}%)"
|
echo "Nombre de simple portefeuille: $nbrSimpleWallets (${pourcentWallets}%)"
|
||||||
echo -e "\n ---\n"
|
echo -e "\n ---\n"
|
||||||
|
|
||||||
echo "Extraction wallets membres / Simples portefeuille"
|
echo "Extraction wallets membres / Simples portefeuille"
|
||||||
|
echo -e "\n ---\n"
|
||||||
|
|
||||||
|
### Isolation des simples portefeuilles ###
|
||||||
simpleWallets=$(cat $outFile)
|
simpleWallets=$(cat $outFile)
|
||||||
|
|
||||||
echo "Isolation des simples portefeuilles..."
|
echo "Isolation des simples portefeuilles..."
|
||||||
for i in ${MEMBERS[@]}; do
|
for i in ${MEMBERS[@]}; do
|
||||||
simpleWallets=$(echo "$simpleWallets" | grep -v "$i")
|
simpleWallets=$(echo "$simpleWallets" | grep -v "$i")
|
||||||
done
|
done
|
||||||
|
|
||||||
#cat "$outFile" | grep . > /var/www/g1-stats/wallets-g1.txt
|
### Boucle d'obtention des soldes ###
|
||||||
#echo -e "${MEMBERS[@]}" | sed 's/ /\n/g' > /var/www/g1-stats/wallets-g1-membres.txt
|
|
||||||
#echo -e "$simpleWallets" > /var/www/g1-stats/wallets-g1-simple.txt
|
|
||||||
|
|
||||||
echo -e "\n ---\n"
|
|
||||||
|
|
||||||
getSolde(){
|
getSolde(){
|
||||||
solde=0
|
solde=0
|
||||||
txInT=0
|
txInT=0
|
||||||
|
@ -154,11 +171,11 @@ txOutT=0
|
||||||
nonConsumedUDT=0
|
nonConsumedUDT=0
|
||||||
nonConsumedUD=0
|
nonConsumedUD=0
|
||||||
for i in $pubkeys; do
|
for i in $pubkeys; do
|
||||||
until txInL=$(curl -s "http://g1.data.duniter.fr/g1/movement/_search?filter_path=hits.hits._source&size=10000&q=recipient:$i&pretty"); do
|
until txInL=$(curl -s "$ESNODE/g1/movement/_search?filter_path=hits.hits._source&size=10000&q=recipient:$i&pretty"); do
|
||||||
echo "Erreur: $i"
|
echo "Erreur: $i"
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
until txOutL=$(curl -s "http://g1.data.duniter.fr/g1/movement/_search?filter_path=hits.hits._source&size=10000&q=issuer:$i&pretty"); do
|
until txOutL=$(curl -s "$ESNODE/g1/movement/_search?filter_path=hits.hits._source&size=10000&q=issuer:$i&pretty"); do
|
||||||
echo "Erreur: $i"
|
echo "Erreur: $i"
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
@ -191,9 +208,7 @@ soldeSimple=$(echo $soldeSimpleBrut | tr . , | sed ':a;s/\B[0-9]\{3\}\>/.&/;ta')
|
||||||
echo -e "Reçus simples wallets:\t $txInSimple"
|
echo -e "Reçus simples wallets:\t $txInSimple"
|
||||||
echo -e "Envoyé simples wallets:\t $txOutSimple"
|
echo -e "Envoyé simples wallets:\t $txOutSimple"
|
||||||
echo -e "Soldes simples wallets:\t $soldeSimple"
|
echo -e "Soldes simples wallets:\t $soldeSimple"
|
||||||
|
|
||||||
echo -e "\n ---\n"
|
echo -e "\n ---\n"
|
||||||
|
|
||||||
echo "Récupération du solde des membres..."
|
echo "Récupération du solde des membres..."
|
||||||
|
|
||||||
pubkeys=${MEMBERS[@]}
|
pubkeys=${MEMBERS[@]}
|
||||||
|
@ -207,6 +222,7 @@ echo -e "Envoyé membres:\t $txOutMembers"
|
||||||
echo -e "Soldes membres:\t $soldeMembers"
|
echo -e "Soldes membres:\t $soldeMembers"
|
||||||
echo -e "Total DU non consumés:\t $nonConsumedUDT"
|
echo -e "Total DU non consumés:\t $nonConsumedUDT"
|
||||||
|
|
||||||
|
### Calcul de la masse monétaire et du pourcentage de Ḡ1 sur les simples portefeuilles ###
|
||||||
monetaryMass=$(curl -s ${DUNITER}/blockchain/current | jq .monetaryMass)
|
monetaryMass=$(curl -s ${DUNITER}/blockchain/current | jq .monetaryMass)
|
||||||
monetaryMassBrut=$(echo -e "scale=2; ($monetaryMass/100)/1" | bc)
|
monetaryMassBrut=$(echo -e "scale=2; ($monetaryMass/100)/1" | bc)
|
||||||
monetaryMass=$(echo "$monetaryMassBrut" | tr . , | sed ':a;s/\B[0-9]\{3\}\>/.&/;ta')
|
monetaryMass=$(echo "$monetaryMassBrut" | tr . , | sed ':a;s/\B[0-9]\{3\}\>/.&/;ta')
|
||||||
|
@ -219,6 +235,7 @@ echo -e "Masse Monétaire:\t $monetaryMass Ḡ1"
|
||||||
|
|
||||||
[[ $isWeb == "web" ]] && web
|
[[ $isWeb == "web" ]] && web
|
||||||
|
|
||||||
|
### Fin de programme ###
|
||||||
rm $outFile
|
rm $outFile
|
||||||
day=$(date +'%d-%m-%y')
|
day=$(date +'%d-%m-%y')
|
||||||
echo "$day - Heure de fin: $(date +'%H:%M')"
|
echo "$day - Heure de fin: $(date +'%H:%M')"
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="css/style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -39,6 +39,9 @@ Ces données sont mises à jours toutes les 3 heures.<br>
|
||||||
<a href="/history/">Consulter l'historique</a>
|
<a href="/history/">Consulter l'historique</a>
|
||||||
</center>
|
</center>
|
||||||
|
|
||||||
|
<a href="/history/index__datePrevious.html" class="previous">‹</a>
|
||||||
|
<a href="/history/index__dateNext.html" class="next">›</a>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue