G1Voeu makes & publish FRIENDS Ŋ1 JSON's

This commit is contained in:
fred 2022-12-28 17:21:50 +01:00
parent 68a0c3c563
commit 15b7378d5d
4 changed files with 60 additions and 105 deletions

View File

@ -528,10 +528,20 @@ echo "" > ~/.zen/tmp/.ipfsgw.bad.twt # TODO move in 20h12.sh
# PAY : /?player=PLAYER&pay=1&dest=G1PUB
##############################################
if [[ $APPNAME == "pay" ]]; then
echo "${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey pay -a ${WHAT} -p ${VAL} -c 'Bro' -m"
echo "$HTTPCORS" > ~/.zen/tmp/pay.log
${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey pay -a ${WHAT} -p ${VAL} -c 'Bro' -m 2>&1 >> ~/.zen/tmp/pay.log
cat ~/.zen/tmp/pay.log | nc -l -p ${PORT} -q 1 > /dev/null 2>&1 &
echo "$HTTPCORS" > ~/.zen/tmp/$PLAYER.pay.$VAL.http
if [[ $VAL =~ [0-9] ]]; then
echo "${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey pay -a ${WHAT} -p ${VAL} -c 'Bro' -m"
${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey pay -a ${WHAT} -p ${VAL} -c 'Bro' -m 2>&1 >> ~/.zen/tmp/$PLAYER.pay.$VAL.http
elif [[ $VAL == "balance" || $VAL == "history" || $VAL == "get" ]]; then
echo "${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey $VAL"
${MY_PATH}/tools/jaklis/jaklis.py -k ~/.zen/game/players/${PLAYER}/secret.dunikey $VAL 2>&1 >> ~/.zen/tmp/$PLAYER.pay.$VAL.http
fi
cat ~/.zen/tmp/$PLAYER.pay.$VAL.http | nc -l -p ${PORT} -q 1 > /dev/null 2>&1 &
end=`date +%s`
echo "(G_G ) PAYING Execution time was "`expr $end - $start` seconds.
continue

View File

@ -7,6 +7,9 @@
MY_PATH="`dirname \"$0\"`" # relative
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
ME="${0##*/}"
. "${MY_PATH}/tools/my.sh"
################################################################################
# Create G1VOEU TW for PLAYER
# Mon Titre => G1MonTitre => PEPPER
@ -22,7 +25,8 @@ PSEUDO=$(cat ~/.zen/game/players/$PLAYER/.pseudo 2>/dev/null)
[[ $G1PUB == "" ]] && G1PUB=$(cat ~/.zen/game/players/$PLAYER/.g1pub 2>/dev/null)
[[ $G1PUB == "" ]] && echo "Troisième paramètre G1PUB manquant" && exit 1
[[ ! $INDEX ]] && echo "MISSING ASTRONAUTE TW index.html - EXIT -" && exit 1
[[ ! $INDEX ]] && INDEX="$HOME/.zen/game/players/$PLAYER/ipfs/moa/index.html"
[[ ! -s $INDEX ]] && echo "TW $PLAYER manquant" && exit 1
echo "Working on $INDEX"
@ -41,7 +45,7 @@ echo
SALT=$(${MY_PATH}/../tools/diceware.sh 3 | xargs)
echo "$SALT"
echo "## TITRE POUR CE VOEU ? "
echo "## TITRE DE VOTRE VOEU ? CapitalGluedWords"
[[ ! $TITRE ]] && read TITRE
PEPPER=$(echo "$TITRE" | sed -r 's/\<./\U&/g' | sed 's/ //g') # CapitalGluedWords
echo "$PEPPER" && [[ ! $PEPPER ]] && echo "EMPTY PEPPER - ERROR" && exit 1
@ -59,15 +63,8 @@ echo
echo "/ipns/$VOEUNS"
## TEST IPFS
ipfs --timeout=6s cat /ipns/$VOEUNS > ~/.zen/tmp/$VOEUNS.html
[[ -s ~/.zen/tmp/$VOEUNS.html ]] && echo "HEY !!! UN TW EXISTE POUR CE VOEU ! ~/.zen/tmp/$VOEUNS.html - EXIT -" && exit 1
# CRYPTO BUG. TODO use natools to protect and share key with Ŋ1 only ;)
myIP=$(hostname -I | awk '{print $1}' | head -n 1)
isLAN=$(route -n |awk '$1 == "0.0.0.0" {print $2}' | grep -E "/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/")
[[ ! $myIP || $isLAN ]] && myIP="ipfs.localhost"
echo " Passerelle : $myIP"
ipfs --timeout=30s cat /ipns/$VOEUNS > ~/.zen/tmp/$VOEUNS.json
[[ -s ~/.zen/tmp/$VOEUNS.json ]] && echo "HEY !!! UN CHANNEL EXISTE DEJA POUR CE VOEU ! ~/.zen/tmp/$VOEUNS.json - EXIT -" && exit 1
echo "# UPGRADING WORLD WHISHKEY DATABASE"
MOATS=$(date -u +"%Y%m%d%H%M%S%4N")
@ -76,48 +73,6 @@ isLAN=$(route -n |awk '$1 == "0.0.0.0" {print $2}' | grep -E "/(^127\.)|(^192\.1
## A la fois Titre du tag et Pepper construction de clef
echo $PEPPER > ~/.zen/game/world/$WISHKEY/.pepper
echo "# INIT WISH TW"
##########################################################################################
##########################################################################################
cp ~/.zen/Astroport.ONE/templates/twdefault.html ~/.zen/game/world/$WISHKEY/index.html
# TODO : CREATE ONE TEMPLATE / REMOVE USELESS TID
# PERSONNALISATION "MadeInZion"
sed -i "s~_BIRTHDATE_~${MOATS}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_PSEUDO_~${PSEUDO}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_PLAYER_~${PLAYER}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_G1PUB_~${G1PUB}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_WISHKEY_~${WISHKEY}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_NUMBER_~${SALT}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_SECRET_~${PEPPER}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_ASTROPORT_~/ipns/${ASTRONAUTENS}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~_QRSEC_~${myIP}~g" ~/.zen/game/world/$WISHKEY/index.html
# IPNS KEY is WISHKEY / VOEUNS
sed -i "s~_MEDIAKEY_~${WISHKEY}~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~k2k4r8kxfnknsdf7tpyc46ks2jb3s9uvd3lqtcv9xlq9rsoem7jajd75~${VOEUNS}~g" ~/.zen/game/world/$WISHKEY/index.html
# ASTROPORT LOCAL IP RELAY == Smartphone doesn't resolve LAN DNS. So using Astroport Station IP
sed -i "s~ipfs.infura.io~tube.copylaradio.com~g" ~/.zen/game/world/$WISHKEY/index.html
sed -i "s~127.0.0.1~$myIP~g" ~/.zen/game/world/$WISHKEY/index.html
# ADD API GW TIDDLERS for IPFS SAVE
##########################################################################################
# [{"title":"$:/ipfs/saver/api/http/local/5001","tags":"$:/ipfs/core $:/ipfs/saver/api","text":"http://127.0.0.1:5001"}]
# [{"title":"$:/ipfs/saver/gateway/local/myip","tags":"$:/ipfs/core $:/ipfs/saver/gateway","text":"http://127.0.0.1:8080"}]
##########################################################################################
tiddlywiki --load ~/.zen/game/world/$WISHKEY/index.html \
--import ~/.zen/Astroport.ONE/templates/data/local.api.json "application/json" \
--import ~/.zen/Astroport.ONE/templates/data/local.gw.json "application/json" \
--deletetiddlers '"Dessin de _PLAYER_"' \
--deletetiddlers '"BunkerBOX"' \
--deletetiddlers '"CopierYoutube"' \
--deletetiddlers '"Bienvenue"' \
--output ~/.zen/tmp --render "$:/core/save/all" "newindex.html" "text/plain"
[[ -s ~/.zen/tmp/newindex.html ]] && cp ~/.zen/tmp/newindex.html ~/.zen/game/world/$WISHKEY/index.html
[[ ! -s ~/.zen/tmp/newindex.html ]] && echo "ERROR ~/.zen/tmp/newindex.html MISSING" && exit 1
echo "# CREATION QR CODE"
LIBRA=$(head -n 2 ~/.zen/Astroport.ONE/A_boostrap_nodes.txt | tail -n 1 | cut -d ' ' -f 2)
@ -128,12 +83,6 @@ isLAN=$(route -n |awk '$1 == "0.0.0.0" {print $2}' | grep -E "/(^127\.)|(^192\.1
qrencode -s 12 -o "$HOME/.zen/game/world/$WISHKEY/QR.G1WISH.png" "$WISHKEY"
qrencode -s 12 -o "$HOME/.zen/game/world/$WISHKEY/QR.IPNS.png" "/ipns/$VOEUNS"
# Bricolage avec node tiddlywiki (TODO add tiddler with command line)
# A suivre .... https://talk.tiddlywiki.org/t/how-to-add-extract-modify-tiddlers-from-command-line-to-do-ipfs-media-transfer/4345/4
# cd ~/.zen/game/world/$WISHKEY
# tiddlywiki $WISHKEY --load ~/.zen/game/world/$WISHKEY/index.html --savewikifolder ./tw/
# cd -
#################################
# PREMIER TYPE ~/.zen/tmp/player.png
convert $HOME/.zen/game/world/$WISHKEY/QR.WISHLINK.png -resize 300 ~/.zen/tmp/QRWISHLINK.png
@ -160,10 +109,7 @@ convert -gravity northwest -pointsize 50 -fill black -draw "text 30,300 \"$PEPPE
# IMAGE DANS IPFS
IVOEUPLAY=$(ipfs add -Hq ~/.zen/tmp/player.png | tail -n 1)
IVOEU=$(ipfs add -Hq ~/.zen/tmp/voeu.png | tail -n 1)
## Replace Template G1Voeu image
sed -i "s~bafybeidhghlcx3zdzdah2pzddhoicywmydintj4mosgtygr6f2dlfwmg7a~${IVOEU}~g" ~/.zen/game/world/$WISHKEY/index.html
# TEXT="<a target='_blank' href='"/ipns/${VOEUNS}"'><img src='"/ipfs/${IVOEUPLAY}"'></a><br><br><a target='_blank' href='"/ipns/${VOEUNS}"'>"${PEPPER}"</a>"
#:[tag[G1CopierYoutube]] [tag[pdf]]
@ -174,7 +120,7 @@ convert -gravity northwest -pointsize 50 -fill black -draw "text 30,300 \"$PEPPE
<\$list filter='[tag[G1"${PEPPER}"]]'>
<\$action-navigate \$to=<<currentTiddler>> \$scroll=no/>
</\$list>
Afficher tous les G1"${PEPPER}"
Afficher tous vos G1"${PEPPER}"
</\$button>"
# NEW IVEU TIDDLER
@ -184,11 +130,13 @@ convert -gravity northwest -pointsize 50 -fill black -draw "text 30,300 \"$PEPPE
"created": "'${MOATS}'",
"title": "'${PEPPER}'",
"type": "'text/vnd.tiddlywiki'",
"astronautens": "'/ipns/$ASTRONAUTENS'",
"wishns": "'/ipns/$VOEUNS'",
"astronautens": "'/ipns/${ASTRONAUTENS}'",
"wishns": "'/ipns/${VOEUNS}'",
"qrcode": "'/ipfs/${IVOEUPLAY}'",
"wish": "'$WISHKEY'",
"text": "'$TEXT'",
"decode": "'/ipfs/${IVOEU}'",
"wish": "'${WISHKEY}'",
"g1pub": "'${G1PUB}'",
"text": "'${TEXT}'",
"tags": "'G1Voeu G1${PEPPER} ${PLAYER}'"
}
]
@ -198,7 +146,7 @@ convert -gravity northwest -pointsize 50 -fill black -draw "text 30,300 \"$PEPPE
rm -f ~/.zen/tmp/newindex.html
echo "Nouveau Qr$PEPPER dans MOA $PSEUDO : http://127.0.0.1:8080/ipns/$ASTRONAUTENS"
echo "Nouveau Voeu $PEPPER dans MOA $PSEUDO : http://127.0.0.1:8080/ipns/$ASTRONAUTENS"
tiddlywiki --verbose --load $INDEX \
--deletetiddlers '[tag[voeu]]' \
--import ~/.zen/game/world/$WISHKEY/${PEPPER}.voeu.json "application/json" \
@ -227,26 +175,24 @@ convert -gravity northwest -pointsize 50 -fill black -draw "text 30,300 \"$PEPPE
# COPY QR CODE TO PLAYER ZONE
cp ~/.zen/tmp/player.png ~/.zen/tmp/voeu.png ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/
echo "$PEPPER" > ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/.title
echo "http://$myIP:8080/ipns/$VOEUNS" > ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/.link
echo "$LIBRA/ipns/$VOEUNS" > ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/.link
cp ~/.zen/game/world/$WISHKEY/QR.WISHLINK.png ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/
# PUBLISHING
echo "## ${PLAYER} RECORDING YOU WISH INTO IPFS"
echo "ipfs add -Hq ~/.zen/game/world/$WISHKEY/index.html
ipfs name publish --key=${WISHKEY} /ipfs/\$IPUSH"
IPUSH=$(ipfs add -Hq ~/.zen/game/world/$WISHKEY/index.html | tail -n 1)
banner="## ${PLAYER} YOUR WISH IS READY TO MAKE Ŋ1 TW FLUX for G1$PEPPER"
echo "ipfs name publish --key=${WISHKEY} $banner"
IPUSH=$(echo "$banner" | ipfs add -q)
ipfs name publish --key=${WISHKEY} /ipfs/$IPUSH 2>/dev/null
echo $IPUSH > ~/.zen/game/world/$WISHKEY/.chain
echo $MOATS > ~/.zen/game/world/$WISHKEY/.moats
echo $IPUSH > ~/.zen/game/players/$PLAYER/voeux/$WISHKEY/.$MOATS.chain
echo
echo "Astronaute TW : http://$myIP:8080/ipns/$ASTRONAUTENS"
echo "Astronaute TW : $LIBRA/ipns/$ASTRONAUTENS"
echo "Nouveau G1Voeu : $PEPPER (document de contrôle de copie Ŋ1)"
echo "TW $PEPPER : http://$myIP:8080/ipns/$VOEUNS"
echo "TW $PEPPER : $LIBRA/ipns/$VOEUNS"
echo "## TO RECEIVE G1RONDS Creating Cesium+ Profil #### timeout long ... patience ...."
$MY_PATH/../tools/jaklis/jaklis.py -k ~/.zen/tmp/qrtw.dunikey -n "https://g1.data.presles.fr" set --name "G1Voeu $PEPPER" --avatar "/home/$USER/.zen/Astroport.ONE/images/logojune.jpg" --site "https://astroport.com/ipns/$VOEUNS" #CESIUM+
$MY_PATH/../tools/jaklis/jaklis.py -k ~/.zen/tmp/qrtw.dunikey -n "https://g1.data.presles.fr" set --name "G1Voeu $PEPPER" --avatar "/home/$USER/.zen/Astroport.ONE/images/logojune.jpg" --site "$LIBRA/ipns/$VOEUNS" #CESIUM+
[[ ! $? == 0 ]] && echo "CESIUM PROFILE CREATION FAILED !!!!"
echo "************************************************************"

View File

@ -7,13 +7,12 @@
MY_PATH="`dirname \"$0\"`" # relative
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
ME="${0##*/}"
. "${MY_PATH}/tools/my.sh"
################################################################################
## Publish All PLAYER TW,
# Run TAG subprocess: tube, voeu
############################################
echo "## RUNNING PLAYER.refresh"
# IPFSNODEID=$(ipfs id -f='<id>\n')
IPFSNODEID=$(cat ~/.ipfs/config | jq -r .Identity.PeerID)
PLAYERONE="$1"
[[ ! $PLAYERONE ]] && PLAYERONE=($(ls -t ~/.zen/game/players/))
@ -21,6 +20,7 @@ PLAYERONE="$1"
## RUNING FOR ALL LOCAL PLAYERS
for PLAYER in ${PLAYERONE[@]}; do
[[ ! -d ~/.zen/game/players/$PLAYER ]] && echo "BAD $PLAYERONE" && continue
MOATS=$(date -u +"%Y%m%d%H%M%S%4N")
[[ ! $(echo "$PLAYER" | grep '@') ]] && continue
mkdir -p ~/.zen/tmp/${MOATS}

View File

@ -43,7 +43,7 @@ echo "Exporting $PLAYER TW [tag[G1Voeu]]"
rm -f ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1voeu.json
tiddlywiki --load ${INDEX} --output ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu --render '.' "${PLAYER}.g1voeu.json" 'text/plain' '$:/core/templates/exporters/JsonFile' 'exportFilter' '[tag[G1Voeu]]'
[[ ! -s ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1voeu.json ]] && echo "AUCUN G1VOEU - EXIT -" && exit 1
[[ ! -s ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1voeu.json ]] && echo "AUCUN G1VOEU - EXIT -" && exit 0
cat ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1voeu.json | jq -r '.[].wish' > ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1wishes.txt
echo "VOEUX : ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1wishes.txt "$(cat ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1wishes.txt | wc -l)
@ -99,34 +99,33 @@ do
rm -f ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json
echo "TRY EXPORT [tag[G1${WISHNAME}]] FROM $FRIENDTW"
tiddlywiki --load $FRIENDTW \
--output ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME} --render '.' ${APLAYER}'.tiddlers.json' 'text/plain' '$:/core/templates/exporters/JsonFile' 'exportFilter' '[days:created[-1]tag[G1'${WISHNAME}']!tag[G1Voeu]]'
--output ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME} --render '.' ${APLAYER}'.tiddlers.json' 'text/plain' '$:/core/templates/exporters/JsonFile' 'exportFilter' '[tag[G1'${WISHNAME}']!tag[G1Voeu]]'
[[ ! -s ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json ]] && echo "NO ${WISHNAME} - CONTINUE -" && continue
[[ $(cat ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json) == "[]" ]] && echo "EMPTY ${WISHNAME} - CONTINUE -" && continue
echo "## NEW TIDDLERS FOUND ;) MIAM >>> (◕‿‿◕) <<<"
######################################
## TODO ADD EXTRA TAG ?
# Remove G1${WISHNAME} with WISHNAME Initial TIDDLER
# Reduce importation with extra filters days:created[-1]
# Apply Extra filters... TODO LEARN https://talk.tiddlywiki.org/t/how-to-filter-and-delete-multiple-tiddlers/4950/2?u=papiche
echo ">>> Importing ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json"
tiddlywiki --load $INDEX \
--import "$HOME/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json" "application/json" \
--output ~/.zen/tmp --render "$:/core/save/all" "${ASTRONAUTENS}.newindex.html" "text/plain"
if [[ -s ~/.zen/tmp/${ASTRONAUTENS}.newindex.html ]]; then
echo "$$$ Mise à jour $INDEX"
cp ~/.zen/tmp/${ASTRONAUTENS}.newindex.html $INDEX
else
echo "Problem with tiddlywiki command. Missing ~/.zen/tmp/${ASTRONAUTENS}.newindex.html"
echo "XXXXXXXXXXXXXXXXXXXXXXX"
fi
echo "## TIDDLERS FOUND ;) MIAM >>> (◕‿‿◕) <<<"
echo ">>> YEAH § ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${APLAYER}.tiddlers.json"
done
echo ">>> MOA § ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/${PLAYER}.tiddlers.json"
tiddlywiki --load $INDEX \
--output ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME} \
--render '.' ${PLAYER}'.tiddlers.json' 'text/plain' '$:/core/templates/exporters/JsonFile' 'exportFilter' '[tag[G1'${WISHNAME}']!tag[G1Voeu]]'
### ADD TO IPFS
echo "++++ ipfs add -qHwr ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/*"
JSONIPFS=$(ipfs add -qHwr ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME}/* | tail -n 1) # ADDING JSONS TO IPFS
ipfs name publish -k $VOEUKEY /ipfs/$JSONIPFS # PUBLISH $VOEUKEY
## MOVE INTO PLAYER AREA
echo "MOVING INTO ~/.zen/game/players/$PLAYER/G1${WISHNAME}"
rm -Rf ~/.zen/game/players/$PLAYER/G1${WISHNAME}
mv ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${WISHNAME} ~/.zen/game/players/$PLAYER/G1${WISHNAME}
done < ~/.zen/tmp/${IPFSNODEID}/${PLAYER}/g1voeu/${PLAYER}.g1wishes.txt
~/.zen/game/players/$PLAYER/G1CopierYoutube
echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
echo "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"