Posted on

The Noble 8-fold path of development

…. or maybe not so noble,
but more a tactical assault on the problem.

  1. Slap some stuff together
  2. Understand what you did, what it does, and what it should do.
    If you don’t or it doesn’t, revert to 1…
  3. Fix the remains so it does what it was supposed to do,
    in a passable fashion.
  4. Run it by some innocent victim (aka guinea pig or co-worker),
    and see about their reaction.

    If bad, revert to step 3.
  5. Prettify, if required…(trust me, it is.)
  6. Do a QA / code review with your peers (guinea pigs),
    and when the number of Whiskey Tango Foxtrots/minute
    goes below 1, you are generally safe to proceed.
  7. Release the product.
  8. Duck/Hide under the table, wait for the client fallout and bugs to be reported.
Posted on

Nasa Software Catalogue 2023/2024

I just thought i would share this little gem with you all!

I if you are into engineering, research, development, this may be of interest to you as well – the open catalogue of software in a wide range of areas.

“The 2023-2024 Software Catalog is Here!
Each year, NASA scientists, engineers, and developers create software packages to manage space missions, test spacecraft, and analyze the petabytes of data produced by agency research satellites. As the agency innovates for the benefit of humanity, many of these programs are now downloadable and free of charge through NASA’s Software Catalog.”

https://software.nasa.gov/

Enjoy!

Posted on

When things go untested…

This shows the importance of fundamental testing of code in Dev and Staging, BEFORE pushing to prod,
no matter the urgency, unless you are absolutely sure it will work and it is an emergency, or, of course,
you are out of options and ready to take the risk of burning down the house…

What could possibly go wrong, right?

 

Posted on

Tinypng script

Using the service from https://tinypng.com makes it easy to mass-shrink your PNG images to more palatable sizes, and it comes with a neat 500 free use transcodes per month, and it’s quite cheap after that.

Here’s a little script to help you with the work a bit.

Prerequisites:
bash, jq and curl.

Save the file as “tinify” and do a chmod 755 tinify

Flags:
-k <key> = API key for tinypng.com – can be omitted if specified in the environment variable by export TINIFY_API ="<api_key>"
-f <file> = Filename to compress
-r = Replace the original file with the compressed file. If not specified, the output file will be named tiny-<filename>
-v = verbose output
-s = Show compression statistics (1 line per file)

#!/bin/env bash
# (C) EmberLabs / Chris Sprucefield 2023.
# License: CC BY.

key=''
file=''
r_flag=false
v_flag=false
s_flag=false
s_arg="-s"

if [ "${TINIFY_API}" != "" ]
then
    if [ "${v_flag}" == true ] ; then echo "Using API key from env." ; fi
    key="${TINIFY_API}"
fi

while getopts 'rk:f:vsh?' flag; do
case "${flag}" in
    r) r_flag=true ;;
    k) key="${OPTARG}" ;;
    f) file="${OPTARG}" ;;
    v) v_flag=true
       s_arg="" ;;
    s) s_flag=true ;;
    *)
        echo "<cmd> -? | -h This help text"
        echo " -r Replace the original file with tinified file."
        echo " -k <apikey> The API key for tinify (or from \$TINIFY_API environment variable if set)"
        echo " -f <filename> The filename to encode (and replace if -r is specified)"
        echo " -v Verbose output"
        echo " -s Show compression statistics"
        exit 1
        ;;
    esac
done

if [ "${v_flag}" == true ] ; then echo "Processing ${file}" ; fi
JSON="$(curl ${s_arg} --user "api:${key}" --data-binary "@${file}" -i https://api.tinify.com/shrink | tail -1)"
URL="$(echo "${JSON}" | jq '.output.url' | sed 's/\"//g')"
ISIZE="$(echo "${JSON}" | jq '.input.size')"
OSIZE="$(echo "${JSON}" | jq '.output.size')"
RATIO="$(echo "${JSON}" | jq '.output.ratio')"
W="$(echo "${JSON}" | jq '.output.width')"
H="$(echo "${JSON}" | jq '.output.height')"

if [ "${ISIZE}" == "${OSIZE}" ]
then
    if [ "${v_flag}" == true ] ; then echo "No compression on ${file} - skipped." ; fi
    exit 0
fi

if [ "${URL}" != "null" ]
then
    if [ "${v_flag}" == true ] ; then echo "Fetching ${URL}" ; fi
    curl ${s_arg} "${URL}" -o "tiny-${file}"

    if [ "${r_flag}" == true ]
    then
        if [ "${v_flag}" == true ] ; then echo "Replacing original file" ; fi
        mv -f "tiny-${file}" "${file}"
    fi
    if [ "${s_flag}" == true ]
    then
        printf "%-40s %5d x %-5d In: %8d Out: %8d Ratio: %2.5f\n" "${file}" "${W}" "${H}" "${ISIZE}" "${OSIZE}" "${RATIO}"
    fi
else
    echo "Invalid response. (incorrect API key?)"
    exit 1
fi

 

Posted on

Easily mirror a BitBucket workspace?

So, you have a large pile of Bitbucket repos that you want to check out, mirror or even back up?

Here’s a shellscript for you that does the trick.

Prerequisites:

  • jq, bash and git installed on the machine.
  • You have an APP password on the bitbucket (create in personal settings)
  • You have an SSH key on the bitbucket and you can checkout via ssh.

Store the script as something like “bb” and issue “chmod 755 bb”

There are 3 commands:
“bb  get” will fetch the lists of the repos.
“bb update” will mass check out the repos if it doesn’t exist locally, or update them.
“bb backup” will check out the repos in mirror format, and make a tgz file of it all.

The checkouts will be done under the path ./<org>/<project>/<repo>

Enjoy!

#!/bin/env bash
# ###########################################################################
# (C) EmberLabs / Chris Sprucefield. 
# Licensed under CC BY | https://creativecommons.org/licenses/by/4.0/
# Basics
ORG=""  # Fill in your org name here. This is the workspace name. 
USER="" # Fill in your username here.
PASS="" # Fill in your BB APP password here.

function getRepoLists() {
    AUTH="Basic $(echo -ne "${USER}:${PASS}" | base64)"
    PAGE="1"

    echo "--------------------------------------------------------------------"
    echo "Getting the ${ORG} repository lists from BitBucket"
    BURL="https://api.bitbucket.org/2.0/repositories/${ORG}?pagelen=100"
    GO="1"
    rm -f repolist-*.json
    echo -n "Getting page "
    while [ "$GO" != "0" ]
    do
      echo -n "${PAGE} "
      curl -s -H "Accept: application/json" -H "Authorization: ${AUTH}" "${BURL}&page=${PAGE}" -o "repolist-${PAGE}.json"

      if [ "$(grep "\"next\":" repolist-${PAGE}.json)" == "" ]
      then
        GO="0"
      fi

      let PAGE=$PAGE+1

    done
    echo ""
}

function cloneRefreshRepos() {
    CWD="$(pwd)"

    for list in $(ls repolist-*.json)
    do
      echo "Processing list $list"
      O="0"
      CONT="1"
      while [ "${CONT}" == "1" ]
      do
        cd "${CWD}"
        OBJECT="$(jq ".values[${O}]" "${CWD}/$list")"

        if [ "${OBJECT}" != "null" ]
        then
          PROJECT="$(echo "$OBJECT" | jq -r '.project.name')"
          NAME="$(echo "$OBJECT" | jq -r '.name')"
          SLUG="$(echo "$OBJECT" | jq -r '.slug')"
          CLONE="$(echo "$OBJECT" | jq -r '.links.clone[1].href')"

          if [ "$1" == "mirror" ]
          then
            mkdir -p "${ORG}-Mirror/${PROJECT}"
            cd "${ORG}-Mirror/${PROJECT}"
            if [ ! -e "${SLUG}" ]
            then
              echo "----------------------------------------------------------"
              git clone --mirror "${CLONE}"
              echo ""
            fi
          else
            mkdir -p "${ORG}/${PROJECT}"
            cd "${ORG}/${PROJECT}"
            if [ ! -e "${SLUG}" ]
            then
              echo "----------------------------------------------------------"
              echo "Cloning ${NAME}"
              git clone "${CLONE}"
              echo ""
            else
              cd "${SLUG}"
              echo "----------------------------------------------------------"
              echo "Updating ${NAME}"
              git fetch --all
              git pull
              echo ""
            fi
          fi

        else
          CONT="0"
        fi

        let O=$O+1
      done
    done
    cs ${CWD}
}


case $1 in
  get)
    # ########################################################################
    # Get the repo lists
    getRepoLists
    ;;

  update)
    # ########################################################################
    # Process the lists.
    cloneRefreshRepos
    ;;

  backup)
    # ########################################################################
    # Process the lists.
    cloneRefreshRepos mirror
    tar -zcf "${ORG}-Mirror-$(date -I).tgz" "${ORG}-Mirror"
    rm -fr "${ORG}-Mirror"
    ;;

  *)
    echo "Usage: "
    echo "<cmd>> get            Get the repo lists"
    echo "<cmd>> update         Update / checkout repos from BB"
    echo "<cmd>> backup         Create a mirror mackup of BB"
esac

Posted on

Confluence Led Calculator User Macro

Another little snippet – Feel free to use.
A nice little led resistor calculator for use in Confluence.

 

Settings: 
No macro body

Template code:

## @noparams
<table borderwidth=0 style=’border-collapse: true;’>
<tr>
<td colspan=3 style=’text-align: center;’>
<font style=’weight: bold; font-size: 24px;’>Formula</font>
<svg align=right height=”50px” width=”300px” version=”1.1″ viewBox=”-0.239051 -0.228099 76.1064 31.3739″ xmlns=”http://www.w3.org/2000/svg” xmlns:xlink=”http://www.w3.org/1999/xlink”>
<defs>
<path d=”M2.30336 -3.1721H2.99676C3.13225 -3.1721 3.23587 -3.1721 3.23587 -3.32354C3.23587 -3.43512 3.12428 -3.43512 3.00473 -3.43512H2.35118C2.47073 -4.06476 2.44682 -4.001 2.58232 -4.62267C2.66202 -5.00523 2.74172 -5.3878 3.03661 -5.3878C3.06052 -5.3878 3.2279 -5.3878 3.34745 -5.28418C3.21993 -5.23636 3.07646 -5.10087 3.07646 -4.90959C3.07646 -4.67846 3.26775 -4.63861 3.35542 -4.63861C3.58655 -4.63861 3.76189 -4.82989 3.76189 -5.07696C3.76189 -5.42765 3.40324 -5.61096 3.04458 -5.61096C2.20772 -5.61096 2.01644 -4.60672 1.96065 -4.30386L1.79328 -3.43512H1.23537C1.09988 -3.43512 1.00423 -3.43512 1.00423 -3.28369C1.00423 -3.1721 1.10785 -3.1721 1.2274 -3.1721H1.74545L1.20349 -0.294894C1.10785 0.215193 1.09191 0.294894 0.956413 0.773101C0.908593 0.956413 0.789041 1.40274 0.510087 1.40274C0.334745 1.40274 0.215193 1.3071 0.215193 1.3071C0.366625 1.24334 0.486177 1.09988 0.486177 0.924533C0.486177 0.6934 0.294894 0.653549 0.207223 0.653549C-0.0239103 0.653549 -0.199253 0.844832 -0.199253 1.09191C-0.199253 1.45853 0.183313 1.6259 0.494147 1.6259C1.33101 1.6259 1.65778 0.247073 1.83313 -0.68543L2.30336 -3.1721Z” id=”g0-102″></path>
<path d=”M3.19601 -2.95691C2.91706 -2.88518 2.91706 -2.64608 2.91706 -2.63014C2.91706 -2.48667 3.02864 -2.39103 3.16413 -2.39103C3.19601 -2.39103 3.51482 -2.39103 3.51482 -2.82939C3.51482 -3.29963 3.04458 -3.51482 2.59029 -3.51482C1.51432 -3.51482 1.25928 -2.64608 1.25928 -2.34321C1.25928 -2.13599 1.34695 -1.91283 1.51432 -1.77733C1.68966 -1.6259 1.77733 -1.60996 2.24757 -1.50635C2.42291 -1.47447 2.84533 -1.3868 2.84533 -0.980324C2.84533 -0.74122 2.63811 -0.143462 1.76139 -0.143462C1.59402 -0.143462 1.12379 -0.167372 0.956413 -0.533998C1.31507 -0.597758 1.31507 -0.900623 1.31507 -0.924533C1.31507 -1.07597 1.20349 -1.18755 1.03611 -1.18755C0.820922 -1.18755 0.621669 -1.02814 0.621669 -0.6934C0.621669 -0.247073 1.06002 0.0797011 1.76139 0.0797011C3.0127 0.0797011 3.33948 -0.860772 3.33948 -1.24334C3.33948 -1.95268 2.63811 -2.09614 2.37509 -2.15193C2.02441 -2.22366 1.75342 -2.27945 1.75342 -2.60623C1.75342 -2.82939 1.95268 -3.29166 2.57435 -3.29166C2.82939 -3.29166 3.10037 -3.20399 3.19601 -2.95691Z” id=”g0-115″></path>
<path d=”M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z” id=”g3-61″></path>
<path d=”M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z” id=”g2-0″></path>
<path d=”M4.51905 -7.32852C4.61469 -7.73499 4.73425 -7.81868 5.45156 -7.81868C5.70262 -7.81868 5.79826 -7.81868 5.79826 -8.04583C5.79826 -8.16538 5.6787 -8.16538 5.63088 -8.16538C5.18854 -8.16538 4.72229 -8.14147 4.27995 -8.14147C3.82565 -8.14147 3.3594 -8.16538 2.91706 -8.16538C2.82142 -8.16538 2.68991 -8.16538 2.68991 -7.95019C2.68991 -7.81868 2.7736 -7.81868 2.97684 -7.81868C3.68219 -7.81868 3.68219 -7.73499 3.68219 -7.60349C3.68219 -7.57958 3.68219 -7.50785 3.63437 -7.31656L2.02042 -0.860772C1.91283 -0.430386 1.8411 -0.3467 1.02814 -0.3467C0.860772 -0.3467 0.74122 -0.3467 0.74122 -0.119552C0.74122 0 0.860772 0 0.908593 0C1.33898 0 1.80523 -0.0239103 2.24757 -0.0239103C2.70187 -0.0239103 3.18007 0 3.62242 0C3.71806 0 3.84956 0 3.84956 -0.227148C3.84956 -0.3467 3.76588 -0.3467 3.53873 -0.3467C3.20399 -0.3467 2.85729 -0.3467 2.85729 -0.549938C2.85729 -0.621669 2.85729 -0.645579 2.8812 -0.753176L4.51905 -7.32852Z” id=”g1-73″></path>
<path d=”M5.92976 -4.06476C7.4122 -4.41146 8.41644 -5.40374 8.41644 -6.40797C8.41644 -7.36438 7.53176 -8.16538 6.07323 -8.16538H3.07248C2.85729 -8.16538 2.74969 -8.16538 2.74969 -7.93823C2.74969 -7.81868 2.83337 -7.81868 3.06052 -7.81868C3.3594 -7.81868 3.69415 -7.81868 3.69415 -7.6274C3.69415 -7.55567 3.69415 -7.5198 3.67024 -7.44807L2.03238 -0.860772C1.92478 -0.442341 1.85305 -0.3467 1.12379 -0.3467C0.908593 -0.3467 0.800996 -0.3467 0.800996 -0.119552C0.800996 0 0.920548 0 0.968369 0C1.37484 0 1.82914 -0.0239103 2.24757 -0.0239103C2.67796 -0.0239103 3.13225 0 3.55068 0C3.64633 0 3.77783 0 3.77783 -0.227148C3.77783 -0.3467 3.68219 -0.3467 3.50286 -0.3467C2.83337 -0.3467 2.83337 -0.442341 2.83337 -0.549938L2.85729 -0.729265L3.67024 -3.96912H4.96139C5.90585 -3.96912 6.10909 -3.33549 6.10909 -2.89315C6.10909 -2.70187 6.01345 -2.29539 5.92976 -1.99651C5.84608 -1.66177 5.73848 -1.21943 5.73848 -0.980324C5.73848 -0.0478207 6.49166 0.251059 7.13724 0.251059C8.09365 0.251059 8.4523 -0.992279 8.4523 -1.09988C8.4523 -1.21943 8.33275 -1.21943 8.28493 -1.21943C8.15342 -1.21943 8.14147 -1.19552 8.09365 -1.02814C7.90237 -0.406476 7.56762 0.0119552 7.1731 0.0119552C6.79054 0.0119552 6.76663 -0.334745 6.76663 -0.669489C6.76663 -1.02814 6.85031 -1.66177 6.89813 -2.03238C6.89813 -2.05629 6.95791 -2.49863 6.95791 -2.666C6.95791 -3.43113 6.46775 -3.84956 5.92976 -4.06476ZM4.94944 -4.20822H3.73001L4.51905 -7.36438C4.61469 -7.74695 4.69838 -7.78281 4.80598 -7.79477C4.88966 -7.81868 5.24832 -7.81868 5.47547 -7.81868C6.21669 -7.81868 7.43611 -7.81868 7.43611 -6.67098C7.43611 -6.45579 7.37634 -4.20822 4.94944 -4.20822Z” id=”g1-82″></path>
<path d=”M8.69141 -6.8264C9.03811 -7.40025 9.32503 -7.74695 9.98257 -7.81868C10.1021 -7.83064 10.1978 -7.84259 10.1978 -8.04583C10.1978 -8.16538 10.0782 -8.16538 10.0543 -8.16538C9.79128 -8.16538 9.46849 -8.14147 9.19352 -8.14147C8.87073 -8.14147 8.52403 -8.16538 8.2132 -8.16538C8.14147 -8.16538 8.00996 -8.16538 8.00996 -7.93823C8.00996 -7.83064 8.1056 -7.81868 8.16538 -7.81868C8.23711 -7.80672 8.60772 -7.78281 8.60772 -7.43611C8.60772 -7.29265 8.51208 -7.12528 8.47621 -7.0655L4.88966 -1.05205L4.268 -7.26874C4.24408 -7.48394 4.22017 -7.80672 4.94944 -7.81868C5.12877 -7.81868 5.23636 -7.81868 5.23636 -8.03387C5.23636 -8.16538 5.12877 -8.16538 5.06899 -8.16538C4.67447 -8.16538 4.25604 -8.14147 3.84956 -8.14147C3.467 -8.14147 3.06052 -8.16538 2.68991 -8.16538C2.61818 -8.16538 2.48667 -8.16538 2.48667 -7.93823C2.48667 -7.81868 2.59427 -7.81868 2.71382 -7.81868C3.28767 -7.81868 3.32354 -7.73499 3.3594 -7.38829L4.07671 -0.0119552C4.10062 0.203238 4.12453 0.251059 4.27995 0.251059S4.45928 0.215193 4.55492 0.0597758L8.69141 -6.8264Z” id=”g1-86″></path>
</defs>
<g id=”page1″ transform=”matrix(1.13 0 0 1.13 -63.986 -61.0546)”>
<use x=”56.4133″ xlink:href=”#g1-82″ y=”70.0554″></use>
<use x=”68.7171″ xlink:href=”#g3-61″ y=”70.0554″></use>
<use x=”82.3041″ xlink:href=”#g1-86″ y=”61.9676″></use>
<use x=”90.9613″ xlink:href=”#g0-115″ y=”63.7609″></use>
<use x=”98.2534″ xlink:href=”#g2-0″ y=”61.9676″></use>
<use x=”110.174″ xlink:href=”#g1-86″ y=”61.9676″></use>
<use x=”118.831″ xlink:href=”#g0-102″ y=”63.7609″></use>
<rect height=”0.478187″ width=”41.46″ x=”82.3041″ y=”66.8275″></rect>
<use x=”98.3647″ xlink:href=”#g1-73″ y=”78.256″></use>
<use x=”102.853″ xlink:href=”#g0-102″ y=”80.0493″></use>
</g>
</svg>
<br>
<br>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>V<sub>s</sub> <input placeholder=”Supply V” onchange=”ledCalc()” style=’width: 90px;’ name=”Vs” id=”Vs” type=”number”> –
V<sub>f</sub> <input placeholder=”Forward V” onchange=”ledCalc()” style=’width: 90px;’ name=”Vf” id=”Vf” type=”number”><br></td>
</tr>
<tr>
<td>R <input name=”R” id=”R” style=’width: 90px;’ type=”number” disabled=true> Ohm</td>
<td>=</td>
<td><hr></td>
</tr>
<tr>
<td>P <input name=”R” id=”P” style=’width: 90px;’ type=”number” disabled=true> W</td>
<td></td>
<td style=’text-align: center;’>I <input placeholder=”Max I” onchange=”ledCalc()” style=’width: 90px;’ name=”I” id=”I” type=”number”><br></td>
</tr>
</table>
<script>
function ledCalc() {
let vs = document.getElementById(‘Vs’).value ;
let vf = document.getElementById(‘Vf’).value ;
let I = document.getElementById(‘I’).value ;
let ro = (vs – vf) / I ;
let po = (vs – vf) * I ;
document.getElementById(‘P’).value = po.toFixed(3) ;
document.getElementById(‘R’).value = ro.toFixed(0) ;
}
</script>