update
This commit is contained in:
parent
a2b24cd586
commit
b892946c25
37
run.sh
37
run.sh
|
@ -1,37 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
WORKING_DIRECTORY=$(pwd)
|
|
||||||
TOOL_DIR="$(cd -- "$(dirname -- "$0")" && pwd)/tool"
|
|
||||||
cd "${WORKING_DIRECTORY}"
|
|
||||||
|
|
||||||
JQ=${JQ:-jq}
|
|
||||||
export JQ_FLAVOUR=${JQ_FLAVOUR:-"$(basename "${JQ}")"}
|
|
||||||
|
|
||||||
run() {
|
|
||||||
if [ -d "${TOOL_DIR}/lib/stubs/${JQ_FLAVOUR}" ]; then
|
|
||||||
STUBS_DIR="${TOOL_DIR}/lib/stubs/${JQ_FLAVOUR}"
|
|
||||||
else
|
|
||||||
STUBS_DIR="${TOOL_DIR}/lib/stubs/jq"
|
|
||||||
fi
|
|
||||||
|
|
||||||
FILES_ARGS=()
|
|
||||||
if [ "${EXPORT_FILE:-}" != "" ] && [ -f "${EXPORT_FILE}" ]; then
|
|
||||||
FILES_ARGS+=(--arg exportFileName "${EXPORT_FILE:-}")
|
|
||||||
if [ "${JQ_FLAVOUR}" != "gojq-extended" ]; then
|
|
||||||
FILES_ARGS+=(--slurpfile exportFile "${EXPORT_FILE}")
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
FILES_ARGS+=(--argjson exportFileName null)
|
|
||||||
FILES_ARGS+=(--argjson exportFile null)
|
|
||||||
fi
|
|
||||||
|
|
||||||
${JQ} -nr -L "$(realpath "${TOOL_DIR}")" -L "$(realpath "${TOOL_DIR}/lib")" -L "$(realpath "${STUBS_DIR}")" \
|
|
||||||
"${FILES_ARGS[@]}" \
|
|
||||||
'include "main"; main' \
|
|
||||||
--args -- "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
run "$@"
|
|
||||||
|
|
28
runTests.sh
28
runTests.sh
|
@ -1,28 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
|
|
||||||
cd "${SCRIPT_DIR}/tool" || return
|
|
||||||
|
|
||||||
JQ=${JQ:-jq}
|
|
||||||
export JQ_FLAVOUR=${JQ_FLAVOUR:-"$(basename "${JQ}")"}
|
|
||||||
export JQ_TYPECHECKING=1
|
|
||||||
|
|
||||||
if [ ! -d "./lib/stubs/${JQ_FLAVOUR}" ]; then
|
|
||||||
STUBS_DIR="./lib/stubs/${JQ_FLAVOUR}"
|
|
||||||
else
|
|
||||||
STUBS_DIR="./lib/stubs/jq"
|
|
||||||
fi
|
|
||||||
|
|
||||||
runTests() {
|
|
||||||
echo "Running Tests with JQ=${JQ}"
|
|
||||||
export JQ_FLAVOUR=${JQ_FLAVOUR:-"$(basename "${JQ}")"}
|
|
||||||
${JQ} -nr \
|
|
||||||
-L "$(realpath .)" -L "$(realpath ./lib)" -L "$(realpath "${STUBS_DIR}")" \
|
|
||||||
"include \"tests\"; testsMain"
|
|
||||||
}
|
|
||||||
|
|
||||||
runTests
|
|
||||||
|
|
||||||
if command -v gojq 2>/dev/null >/dev/null; then
|
|
||||||
JQ=gojq JQ_FLAVOUR=gojq runTests
|
|
||||||
fi
|
|
|
@ -1,70 +0,0 @@
|
||||||
import "lib/utilsLib" as utilsLib;
|
|
||||||
import "lib/stringLib" as stringLib;
|
|
||||||
import "lib/numberLib" as numberLib;
|
|
||||||
import "lib/journalLib" as journalLib;
|
|
||||||
|
|
||||||
def formatExperienceTitle:
|
|
||||||
. as $experience |
|
|
||||||
"\"\(.title)\": \(.creationDate / 1000 | strftime("%d-%m-%Y"))";
|
|
||||||
|
|
||||||
def formatDose($dose; $unit; $isEstimate; $standardDeviation):
|
|
||||||
if $dose == null then
|
|
||||||
"Unknown \($unit)"
|
|
||||||
else
|
|
||||||
(if $isEstimate then "~" else "" end) as $estimate |
|
|
||||||
(if $standardDeviation != null then "±\($standardDeviation)" else "" end) as $standardDeviation |
|
|
||||||
|
|
||||||
"\($estimate)\($dose | numberLib::round(2))\($standardDeviation) \($unit)"
|
|
||||||
end;
|
|
||||||
|
|
||||||
def formatIngestionDose($customUnits):
|
|
||||||
. as $ingestion |
|
|
||||||
(. | journalLib::ingestionDose($customUnits)) as $dose |
|
|
||||||
(. | journalLib::ingestionUnit($customUnits)) as $unit |
|
|
||||||
(. | journalLib::ingestionStandardDeviation($customUnits)) as $standardDeviation |
|
|
||||||
$customUnits | map(select(.id == $ingestion.customUnitId))[0] as $customUnit |
|
|
||||||
if $ingestion.dose == null then
|
|
||||||
"Unknown"
|
|
||||||
elif $customUnit == null then
|
|
||||||
formatDose($dose; $unit; $ingestion.isDoseAnEstimate; $standardDeviation)
|
|
||||||
else
|
|
||||||
formatDose($dose; $unit; $ingestion.isDoseAnEstimate; $standardDeviation) +
|
|
||||||
" (" +
|
|
||||||
formatDose($customUnit.dose; $unit; $customUnit.isEstimate; $customUnit.estimatedDoseStandardDeviation) +
|
|
||||||
" * " +
|
|
||||||
formatDose($ingestion.dose; $customUnit.unit; $ingestion.isDoseAnEstimate; $ingestion.estimatedDoseStandardDeviation) +
|
|
||||||
")"
|
|
||||||
end;
|
|
||||||
|
|
||||||
def formatIngestionTime:
|
|
||||||
. as $ingestion |
|
|
||||||
$ingestion.time / 1000 | strftime("%a %I:%M %p");
|
|
||||||
|
|
||||||
def formatIngestionROA($customUnits; $substitutions):
|
|
||||||
. as $ingestion |
|
|
||||||
$ingestion.administrationRoute as $roa |
|
|
||||||
|
|
||||||
(if
|
|
||||||
$substitutions | has($roa)
|
|
||||||
then
|
|
||||||
$substitutions | .[$roa]
|
|
||||||
else
|
|
||||||
$roa | stringLib::titleCase
|
|
||||||
end) as $roaText |
|
|
||||||
|
|
||||||
$ingestion.customUnitId as $customUnitId |
|
|
||||||
|
|
||||||
if
|
|
||||||
$customUnitId == null
|
|
||||||
then
|
|
||||||
$roaText
|
|
||||||
else
|
|
||||||
$customUnits | map(select(.id == $customUnitId))[0] as $customUnit |
|
|
||||||
"\($roaText) (\($customUnit.name))"
|
|
||||||
end;
|
|
||||||
|
|
||||||
def formatIngestionROA($customUnits): formatIngestionROA($customUnits; {});
|
|
||||||
|
|
||||||
def formatIngestionInfo:
|
|
||||||
. as $ingestionInfo |
|
|
||||||
formatDose(.dose; .unit; .isEstimate; .standardDeviation);
|
|
|
@ -1,2 +0,0 @@
|
||||||
def _readFile($filename): empty;
|
|
||||||
def _writeFileString($filename): empty;
|
|
|
@ -1,233 +0,0 @@
|
||||||
import "ansiLib" as ansiLib;
|
|
||||||
|
|
||||||
def isColourSupported:
|
|
||||||
$ENV["JQ_SUPPORTS_COLOUR"] == "1";
|
|
||||||
|
|
||||||
def colourEscapes:
|
|
||||||
def parseJQColours:
|
|
||||||
split(":") |
|
|
||||||
{
|
|
||||||
"null": (.[0] // "0"),
|
|
||||||
"false": (.[1] // "0"),
|
|
||||||
"true": (.[2] // "0"),
|
|
||||||
"number": (.[3] // "0"),
|
|
||||||
"string": (.[4] // "0"),
|
|
||||||
"array": (.[5] // "0"),
|
|
||||||
"object": (.[6] // "0"),
|
|
||||||
"objectKey": (.[7] // "0"),
|
|
||||||
};
|
|
||||||
|
|
||||||
def parseGOJQColours:
|
|
||||||
split(":") |
|
|
||||||
{
|
|
||||||
"null": (.[0] // "0"),
|
|
||||||
"false": (.[1] // "0"),
|
|
||||||
"true": (.[2] // "0"),
|
|
||||||
"number": (.[3] // "0"),
|
|
||||||
"string": (.[4] // "0"),
|
|
||||||
"objectKey": (.[5] // "0"),
|
|
||||||
"array": (.[6] // "0"),
|
|
||||||
"object": (.[7] // "0"),
|
|
||||||
};
|
|
||||||
def defaultColours:
|
|
||||||
if ($ENV["JQ_FLAVOUR"] | tostring | startswith("gojq")) then
|
|
||||||
"90:33:33:36:32:34;1" | parseGOJQColours
|
|
||||||
else
|
|
||||||
"0;90:0;39:0;39:0;39:0;32:1;39:1;39:1;34" | parseJQColours
|
|
||||||
end;
|
|
||||||
|
|
||||||
try (
|
|
||||||
if $ENV["JQ_COLORS"] != null then
|
|
||||||
$ENV["JQ_COLORS"] | parseJQColours
|
|
||||||
elif $ENV["GOJQ_COLORS"] != null then
|
|
||||||
$ENV["GOJQ_COLORS"] | parseGOJQColours
|
|
||||||
else
|
|
||||||
defaultColours
|
|
||||||
end
|
|
||||||
) catch (
|
|
||||||
defaultColours
|
|
||||||
);
|
|
||||||
|
|
||||||
def _encodeJSONValuePlainPretty($indent; $currentDepth):
|
|
||||||
([range($indent * $currentDepth) | " "] | join("")) as $currentIndentDepthIndent |
|
|
||||||
([range($indent * ($currentDepth + 1)) | " "] | join("")) as $nextDepthIndent |
|
|
||||||
"\n" as $currentIndentDepthNewline |
|
|
||||||
" " as $currentIndentDepthSpace |
|
|
||||||
|
|
||||||
. as $value |
|
|
||||||
(. | type) as $valueType |
|
|
||||||
if $valueType == "array" then
|
|
||||||
($value | length) as $numValues |
|
|
||||||
|
|
||||||
if $numValues > 0 then
|
|
||||||
"[" +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
([
|
|
||||||
$value[] |
|
|
||||||
$nextDepthIndent +
|
|
||||||
_encodeJSONValuePlainPretty($indent; $currentDepth + 1)
|
|
||||||
] | join("," + $currentIndentDepthNewline)) +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
$currentIndentDepthIndent +
|
|
||||||
"]"
|
|
||||||
else
|
|
||||||
"[]"
|
|
||||||
end
|
|
||||||
elif $valueType == "object" then
|
|
||||||
($value | keys | length) as $numKeys |
|
|
||||||
|
|
||||||
if $numKeys > 0 then
|
|
||||||
"{" +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
([
|
|
||||||
$value | keys | sort[] |
|
|
||||||
. as $objectKey |
|
|
||||||
$value[$objectKey] as $objectValue |
|
|
||||||
|
|
||||||
$nextDepthIndent +
|
|
||||||
($objectKey | tojson) +
|
|
||||||
":" +
|
|
||||||
$currentIndentDepthSpace +
|
|
||||||
($objectValue | _encodeJSONValuePlainPretty($indent; $currentDepth + 1))
|
|
||||||
] | join("," + $currentIndentDepthNewline)) +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
$currentIndentDepthIndent +
|
|
||||||
"}"
|
|
||||||
else
|
|
||||||
"{}"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tojson
|
|
||||||
end;
|
|
||||||
|
|
||||||
def _encodeJSONValueColourCompact:
|
|
||||||
colourEscapes as $escapes |
|
|
||||||
|
|
||||||
def colourText($text; $kind):
|
|
||||||
ansiLib::CSR + $escapes[$kind] + "m" + $text + ansiLib::CSR + "0m";
|
|
||||||
|
|
||||||
. as $value |
|
|
||||||
(. | type) as $valueType |
|
|
||||||
if $valueType == "null" then
|
|
||||||
colourText("null"; "null")
|
|
||||||
elif $valueType == "boolean" then
|
|
||||||
($value | tostring) as $boolStr |
|
|
||||||
colourText($boolStr; $boolStr)
|
|
||||||
elif $valueType == "number" then
|
|
||||||
colourText($value | tostring; "number")
|
|
||||||
elif $valueType == "string" then
|
|
||||||
colourText($value | tojson; "string")
|
|
||||||
elif $valueType == "array" then
|
|
||||||
($value | length) as $numValues |
|
|
||||||
|
|
||||||
if $numValues > 0 then
|
|
||||||
colourText("["; "array") +
|
|
||||||
([
|
|
||||||
$value[] |
|
|
||||||
_encodeJSONValueColourCompact
|
|
||||||
] | join(colourText(","; "array"))) +
|
|
||||||
colourText("]"; "array")
|
|
||||||
else
|
|
||||||
colourText("[]"; "array")
|
|
||||||
end
|
|
||||||
elif $valueType == "object" then
|
|
||||||
($value | keys | length) as $numKeys |
|
|
||||||
|
|
||||||
if $numKeys > 0 then
|
|
||||||
colourText("{"; "object") +
|
|
||||||
([
|
|
||||||
$value | keys | sort[] |
|
|
||||||
. as $objectKey |
|
|
||||||
$value[$objectKey] as $objectValue |
|
|
||||||
|
|
||||||
colourText($objectKey | tojson; "objectKey") +
|
|
||||||
colourText(":"; "object") +
|
|
||||||
($objectValue | _encodeJSONValueColourCompact)
|
|
||||||
] | join(colourText(","; "object"))) +
|
|
||||||
colourText("}"; "object")
|
|
||||||
else
|
|
||||||
colourText("{}"; "object")
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
def _encodeJSONValueColourPretty($indent; $currentDepth):
|
|
||||||
colourEscapes as $escapes |
|
|
||||||
|
|
||||||
def colourText($text; $kind):
|
|
||||||
ansiLib::CSR + $escapes[$kind] + "m" + $text + ansiLib::CSR + "0m";
|
|
||||||
|
|
||||||
([range($indent * $currentDepth) | " "] | join("")) as $currentIndentDepthIndent |
|
|
||||||
([range($indent * ($currentDepth + 1)) | " "] | join("")) as $nextDepthIndent |
|
|
||||||
"\n" as $currentIndentDepthNewline |
|
|
||||||
" " as $currentIndentDepthSpace |
|
|
||||||
|
|
||||||
. as $value |
|
|
||||||
(. | type) as $valueType |
|
|
||||||
if $valueType == "null" then
|
|
||||||
colourText("null"; "null")
|
|
||||||
elif $valueType == "boolean" then
|
|
||||||
($value | tostring) as $boolStr |
|
|
||||||
colourText($boolStr; $boolStr)
|
|
||||||
elif $valueType == "number" then
|
|
||||||
colourText($value | tostring; "number")
|
|
||||||
elif $valueType == "string" then
|
|
||||||
colourText($value | tojson; "string")
|
|
||||||
elif $valueType == "array" then
|
|
||||||
($value | length) as $numValues |
|
|
||||||
|
|
||||||
if $numValues > 0 then
|
|
||||||
colourText("["; "array") +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
([
|
|
||||||
$value[] |
|
|
||||||
$nextDepthIndent +
|
|
||||||
_encodeJSONValueColourPretty($indent; $currentDepth + 1)
|
|
||||||
] | join(colourText(","; "array") + $currentIndentDepthNewline)) +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
$currentIndentDepthIndent +
|
|
||||||
colourText("]"; "array")
|
|
||||||
else
|
|
||||||
colourText("[]"; "array")
|
|
||||||
end
|
|
||||||
elif $valueType == "object" then
|
|
||||||
($value | keys | length) as $numKeys |
|
|
||||||
|
|
||||||
if $numKeys > 0 then
|
|
||||||
colourText("{"; "object") +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
([
|
|
||||||
$value | keys | sort[] |
|
|
||||||
. as $objectKey |
|
|
||||||
$value[$objectKey] as $objectValue |
|
|
||||||
|
|
||||||
$nextDepthIndent +
|
|
||||||
colourText($objectKey | tojson; "objectKey") +
|
|
||||||
colourText(":"; "object") +
|
|
||||||
$currentIndentDepthSpace +
|
|
||||||
($objectValue | _encodeJSONValueColourPretty($indent; $currentDepth + 1))
|
|
||||||
] | join(colourText(","; "object") + $currentIndentDepthNewline)) +
|
|
||||||
$currentIndentDepthNewline +
|
|
||||||
$currentIndentDepthIndent +
|
|
||||||
colourText("}"; "object")
|
|
||||||
else
|
|
||||||
colourText("{}"; "object")
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
def encodeJSON($withColour; $indent):
|
|
||||||
if ($withColour == false) and ($indent == 0) then
|
|
||||||
tojson
|
|
||||||
else
|
|
||||||
if $withColour and isColourSupported then
|
|
||||||
if $indent > 0 then
|
|
||||||
_encodeJSONValueColourPretty($indent; 0)
|
|
||||||
else
|
|
||||||
_encodeJSONValueColourCompact
|
|
||||||
end
|
|
||||||
else
|
|
||||||
_encodeJSONValuePlainPretty($indent; 0)
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
def supportsColour:
|
|
||||||
$ENV["JQ_SUPPORTS_COLOR"] == "1" or $ENV["JQ_SUPPORTS_COLOUR"] == "1" ;
|
|
||||||
|
|
||||||
def CSR:
|
|
||||||
"\u001b[";
|
|
||||||
|
|
||||||
def resetColours:
|
|
||||||
CSR + "0m";
|
|
||||||
|
|
||||||
def colourText($colourCode):
|
|
||||||
. as $text |
|
|
||||||
if supportsColour | not then
|
|
||||||
$text
|
|
||||||
else
|
|
||||||
CSR + ($colourCode | tostring) + "m" + $text + resetColours
|
|
||||||
end;
|
|
||||||
|
|
||||||
def colourText($colourCode; $mode):
|
|
||||||
. as $text |
|
|
||||||
if supportsColour | not then
|
|
||||||
$text
|
|
||||||
else
|
|
||||||
CSR + ($mode | tostring) + ";" + ($colourCode | tostring) + "m" + $text + resetColours
|
|
||||||
end;
|
|
|
@ -1,45 +0,0 @@
|
||||||
def parseArgBool:
|
|
||||||
. as $value |
|
|
||||||
if ($value | type) == "boolean" then
|
|
||||||
$value
|
|
||||||
elif
|
|
||||||
$value == "true" or $value == "on" or $value == "yes"
|
|
||||||
then
|
|
||||||
true
|
|
||||||
elif
|
|
||||||
$value == "false" or $value == "off" or $value == "no"
|
|
||||||
then
|
|
||||||
false
|
|
||||||
else
|
|
||||||
error("invalid bool value")
|
|
||||||
end;
|
|
||||||
|
|
||||||
def parseArgs:
|
|
||||||
. as $args |
|
|
||||||
if
|
|
||||||
($args.named | has("argsJson"))
|
|
||||||
then $args.named.argsJson[0] else $args.positional end | . as $args |
|
|
||||||
|
|
||||||
reduce $args[] as $arg ({
|
|
||||||
shortArgs: [],
|
|
||||||
longArgs: {},
|
|
||||||
nonArgs: []
|
|
||||||
}; (
|
|
||||||
if ($arg | test("^-[\\-a-zA-Z]") | not) then
|
|
||||||
.nonArgs += [$arg]
|
|
||||||
else
|
|
||||||
if $arg | startswith("--") then
|
|
||||||
$arg[2:] as $arg |
|
|
||||||
($arg | contains("=")) as $containsValue |
|
|
||||||
if $containsValue then
|
|
||||||
($arg | split("=")) as $argSplit |
|
|
||||||
$argSplit[0] as $arg | $argSplit[1] as $value |
|
|
||||||
.longArgs[$arg] |= $value
|
|
||||||
else
|
|
||||||
.longArgs[$arg] |= null
|
|
||||||
end
|
|
||||||
else
|
|
||||||
.shortArgs += [$arg[1:]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
));
|
|
|
@ -1,7 +0,0 @@
|
||||||
include "stubs";
|
|
||||||
|
|
||||||
def checkSupported:
|
|
||||||
$ENV.JQ_FLAVOUR == "gojq-extended";
|
|
||||||
|
|
||||||
def readFile($filename): _readFile($filename);
|
|
||||||
def writeFileString($filename): _writeFileString($filename);
|
|
|
@ -1,309 +0,0 @@
|
||||||
import "utilsLib" as utilsLib;
|
|
||||||
import "numberLib" as numberLib;
|
|
||||||
import "journalTypes" as journalTypes;
|
|
||||||
|
|
||||||
def ingestionDose($customUnits):
|
|
||||||
. as $ingestion |
|
|
||||||
journalTypes::ensureIngestion |
|
|
||||||
|
|
||||||
if .customUnitId != null then
|
|
||||||
($customUnits | map(select(.id == $ingestion.customUnitId))[0]) as $customUnit |
|
|
||||||
.dose * $customUnit.dose | . as $dose |
|
|
||||||
$dose
|
|
||||||
else
|
|
||||||
.dose
|
|
||||||
end;
|
|
||||||
|
|
||||||
def addStandardDeviations($expectationX; $standardDeviationX; $expectationY; $standardDeviationY):
|
|
||||||
(pow($standardDeviationX; 2) + pow($expectationX; 2)) as $sumX |
|
|
||||||
(pow($standardDeviationY; 2) + pow($expectationY; 2)) as $sumY |
|
|
||||||
(pow($expectationX; 2) * pow($expectationY; 2)) as $expectations |
|
|
||||||
($sumX * $sumY - $expectations) as $productVariance |
|
|
||||||
if $productVariance > 0.0000001 then
|
|
||||||
$productVariance | sqrt | numberLib::round(2)
|
|
||||||
else
|
|
||||||
null
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ingestionStandardDeviation($customUnits):
|
|
||||||
. as $ingestion |
|
|
||||||
journalTypes::ensureIngestion |
|
|
||||||
|
|
||||||
if .customUnitId != null then
|
|
||||||
($customUnits | map(select(.id == $ingestion.customUnitId))[0]) as $customUnit |
|
|
||||||
|
|
||||||
($ingestion.dose // 0) as $expectationX |
|
|
||||||
($ingestion.estimatedDoseStandardDeviation // 0) as $standardDeviationX |
|
|
||||||
($customUnit.dose // 0) as $expectationY |
|
|
||||||
($customUnit.estimatedDoseStandardDeviation // 0) as $standardDeviationY |
|
|
||||||
|
|
||||||
addStandardDeviations($expectationX; $standardDeviationX; $expectationY; $standardDeviationY)
|
|
||||||
else
|
|
||||||
.estimatedDoseStandardDeviation
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ingestionUnit($customUnits):
|
|
||||||
. as $ingestion |
|
|
||||||
journalTypes::ensureIngestion |
|
|
||||||
if .customUnitId != null then
|
|
||||||
($customUnits | map(select(.id == $ingestion.customUnitId))[0]) as $customUnit |
|
|
||||||
$customUnit.originalUnit
|
|
||||||
else
|
|
||||||
.units
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ingestionConsumerName:
|
|
||||||
. as $ingestion |
|
|
||||||
journalTypes::ensureIngestion |
|
|
||||||
$ingestion.consumerName // "default";
|
|
||||||
|
|
||||||
def filterIngestions($substanceFilter; $consumerFilter):
|
|
||||||
. as $ingestions |
|
|
||||||
($substanceFilter // []) as $substanceFilter |
|
|
||||||
(($substanceFilter | length) > 0) as $shouldFilterBySubstance |
|
|
||||||
($consumerFilter // []) as $consumerFilter |
|
|
||||||
(($consumerFilter | length) > 0) as $shouldFilterByConsumer |
|
|
||||||
|
|
||||||
journalTypes::ensureIngestions |
|
|
||||||
|
|
||||||
if $shouldFilterBySubstance or $shouldFilterByConsumer then
|
|
||||||
[
|
|
||||||
$ingestions[] as $ingestion |
|
|
||||||
if
|
|
||||||
(if $shouldFilterBySubstance then ([$substanceFilter[] | . == $ingestion.substanceName] | any) else true end
|
|
||||||
and
|
|
||||||
if $shouldFilterByConsumer then ([$consumerFilter[] | . == ($ingestion | ingestionConsumerName)] | any) else true end)
|
|
||||||
then $ingestion
|
|
||||||
else null end
|
|
||||||
] | map(select(. != null))
|
|
||||||
else $ingestions end;
|
|
||||||
|
|
||||||
def ingestionsSubstanceNames:
|
|
||||||
. as $ingestions |
|
|
||||||
journalTypes::ensureIngestions |
|
|
||||||
[$ingestions[].substanceName] | utilsLib::orderedUnique;
|
|
||||||
|
|
||||||
def ingestionsConsumerNames:
|
|
||||||
. as $ingestions |
|
|
||||||
journalTypes::ensureIngestions |
|
|
||||||
[$ingestions[] | ingestionConsumerName] | utilsLib::orderedUnique;
|
|
||||||
|
|
||||||
def ingestionsByConsumer:
|
|
||||||
. as $ingestions |
|
|
||||||
journalTypes::ensureIngestions |
|
|
||||||
($ingestions | ingestionsConsumerNames) as $consumerNames |
|
|
||||||
[
|
|
||||||
$consumerNames[] as $consumerName |
|
|
||||||
{
|
|
||||||
key: $consumerName,
|
|
||||||
value: $ingestions | map(select((. | ingestionConsumerName) == $consumerName)),
|
|
||||||
}
|
|
||||||
] | from_entries;
|
|
||||||
|
|
||||||
def defaultIngestionInfo:
|
|
||||||
{
|
|
||||||
unit: "",
|
|
||||||
dose: null,
|
|
||||||
isUnknown: false,
|
|
||||||
isEstimate: false,
|
|
||||||
# TODO
|
|
||||||
standardDeviation: null
|
|
||||||
};
|
|
||||||
|
|
||||||
def ingestionInfo($customUnits):
|
|
||||||
. as $ingestion |
|
|
||||||
.substanceName as $name |
|
|
||||||
.administrationRoute as $administrationRoute |
|
|
||||||
. | ingestionStandardDeviation($customUnits) as $standardDeviation |
|
|
||||||
. | ingestionDose($customUnits) as $dose |
|
|
||||||
. | ingestionUnit($customUnits) as $unit |
|
|
||||||
. | ingestionConsumerName as $consumerName |
|
|
||||||
|
|
||||||
defaultIngestionInfo as $ingestionInfo |
|
|
||||||
$ingestionInfo |
|
|
||||||
|
|
||||||
if ($dose == null) then .isUnknown |= true end |
|
|
||||||
|
|
||||||
if ($standardDeviation != null) then
|
|
||||||
.isEstimate |= true
|
|
||||||
end |
|
|
||||||
|
|
||||||
.unit |= $unit |
|
|
||||||
.dose |= $dose |
|
|
||||||
.standardDeviation |= $standardDeviation;
|
|
||||||
|
|
||||||
def addIngestionInfo($rhs):
|
|
||||||
. as $lhs |
|
|
||||||
|
|
||||||
if (.unit != "" and $rhs.unit != "") then
|
|
||||||
utilsLib::assert(.unit == $rhs.unit; "units mismatch, todo add reasonable conversions")
|
|
||||||
else
|
|
||||||
.unit |= $rhs.unit
|
|
||||||
end |
|
|
||||||
|
|
||||||
|
|
||||||
if ($rhs.dose == null) then .isUnknown |= true end |
|
|
||||||
|
|
||||||
if ($rhs.standardDeviation != null) then
|
|
||||||
.isEstimate |= true
|
|
||||||
end |
|
|
||||||
|
|
||||||
.dose += $rhs.dose |
|
|
||||||
.standardDeviation += $rhs.standardDeviation;
|
|
||||||
|
|
||||||
def addIngestionInfos:
|
|
||||||
. as $ingestionInfos |
|
|
||||||
reduce $ingestionInfos[] as $ingestionInfo (defaultIngestionInfo;
|
|
||||||
. | addIngestionInfo($ingestionInfo)
|
|
||||||
);
|
|
||||||
|
|
||||||
def experienceStats($customUnits):
|
|
||||||
. as $experience |
|
|
||||||
journalTypes::ensureExperience |
|
|
||||||
$experience.ingestions as $ingestions |
|
|
||||||
(reduce $ingestions[] as $ingestion ({}; . as $stats |
|
|
||||||
$ingestion |
|
|
||||||
.substanceName as $name |
|
|
||||||
.administrationRoute as $administrationRoute |
|
|
||||||
(. | ingestionConsumerName) as $consumerName |
|
|
||||||
|
|
||||||
$stats |
|
|
||||||
.[$consumerName].[$ingestion.substanceName].[$administrationRoute] as $ingestionStats |
|
|
||||||
|
|
||||||
if $ingestionStats == null then
|
|
||||||
($ingestion | ingestionInfo($customUnits))
|
|
||||||
else
|
|
||||||
$ingestionStats | addIngestionInfo($ingestion | ingestionInfo($customUnits))
|
|
||||||
end | . as $ingestionStats |
|
|
||||||
|
|
||||||
$stats |
|
|
||||||
.[$consumerName].[$ingestion.substanceName].[$administrationRoute] |= $ingestionStats
|
|
||||||
));
|
|
||||||
|
|
||||||
def statsCalculateCombinedDose($substanceName; $consumerName):
|
|
||||||
. as $stats |
|
|
||||||
utilsLib::assert($stats | has($consumerName); "consumer not found in stats") |
|
|
||||||
utilsLib::assert($stats[$consumerName] | has($substanceName);
|
|
||||||
"substance for consumer not found in stats"
|
|
||||||
) |
|
|
||||||
|
|
||||||
.[$consumerName].[$substanceName] | values | addIngestionInfos;
|
|
||||||
|
|
||||||
def experiencesWithExtraData($customUnits):
|
|
||||||
. as $experiences |
|
|
||||||
journalTypes::ensureExperiences |
|
|
||||||
(reduce $experiences[] as $experience ([];
|
|
||||||
($experience | experienceStats($customUnits)) as $stats |
|
|
||||||
. += [{
|
|
||||||
$stats,
|
|
||||||
$experience
|
|
||||||
}]
|
|
||||||
));
|
|
||||||
|
|
||||||
def filterSortExperiences($customUnits; $substanceFilter; $consumerFilter; $sortMethod; $sortOptions):
|
|
||||||
. as $experiences |
|
|
||||||
journalTypes::ensureExperiences |
|
|
||||||
($consumerFilter // ["default"]) as $consumerFilter |
|
|
||||||
$sortOptions |
|
|
||||||
# If filtering results by substances but no sortOptions.substanceName is defined, use the first one as a default
|
|
||||||
(.substanceName |=
|
|
||||||
if
|
|
||||||
$sortOptions.substanceName == null
|
|
||||||
and
|
|
||||||
(($substanceFilter | length) >= 1)
|
|
||||||
then
|
|
||||||
$substanceFilter[0]
|
|
||||||
else
|
|
||||||
null
|
|
||||||
end
|
|
||||||
) | . as $sortOptions |
|
|
||||||
$sortOptions | (.ingestionMethod |= ($sortOptions.ingestionMethod // "ORAL")) | . as $sortOptions |
|
|
||||||
$sortOptions | (.consumerName |= ($sortOptions.consumerName // "default")) | . as $sortOptions |
|
|
||||||
|
|
||||||
def sortFilter:
|
|
||||||
def oldToNewSort: .experience.sortDate;
|
|
||||||
def highestCombinedDoseSort: .stats.[$sortOptions.consumerName].[$sortOptions.substanceName] | [to_entries[] | .value.dose] | add;
|
|
||||||
def highestMethodDoseSort: .stats.[$sortOptions.consumerName].[$sortOptions.substanceName].[$sortOptions.ingestionMethod // "ORAL"].dose;
|
|
||||||
|
|
||||||
def filterBySubstanceFilter:
|
|
||||||
. as $experiencesData |
|
|
||||||
[
|
|
||||||
$experiencesData[] as $experienceData |
|
|
||||||
($experienceData.experience.ingestions) as $ingestions |
|
|
||||||
if ($experienceData.experience.ingestions |
|
|
||||||
any(
|
|
||||||
. as $ingestion |
|
|
||||||
$substanceFilter |
|
|
||||||
any(index($ingestion.substanceName))
|
|
||||||
)
|
|
||||||
) then $experienceData else null end
|
|
||||||
] | map(select(. != null));
|
|
||||||
|
|
||||||
def filterByConsumerFilter:
|
|
||||||
. as $experiencesData |
|
|
||||||
(reduce $experiencesData[] as $experienceData ([];
|
|
||||||
($experienceData.experience.ingestions) as $ingestions |
|
|
||||||
. +=
|
|
||||||
if ($experienceData.experience.ingestions |
|
|
||||||
any(
|
|
||||||
(. | ingestionConsumerName) as $consumerName |
|
|
||||||
$consumerFilter |
|
|
||||||
any(index($consumerName))
|
|
||||||
)
|
|
||||||
) then [$experienceData] else [] end
|
|
||||||
));
|
|
||||||
|
|
||||||
def filterBySubstanceAndConsumer:
|
|
||||||
. as $experiencesData |
|
|
||||||
(reduce $experiencesData[] as $experienceData ([];
|
|
||||||
($experienceData.experience.ingestions) as $ingestions |
|
|
||||||
. +=
|
|
||||||
if
|
|
||||||
($experienceData.experience.ingestions |
|
|
||||||
any(
|
|
||||||
.substanceName == $sortOptions.substanceName
|
|
||||||
and
|
|
||||||
(. | ingestionConsumerName) == $sortOptions.consumerName
|
|
||||||
))
|
|
||||||
then [$experienceData] else [] end
|
|
||||||
));
|
|
||||||
|
|
||||||
def filterByIngestionMethodForSubstance:
|
|
||||||
. as $experiencesData | filterBySubstanceAndConsumer as $experiencesData |
|
|
||||||
(reduce $experiencesData[] as $experienceData ([];
|
|
||||||
($experienceData.experience.ingestions) as $ingestions |
|
|
||||||
. += if ($experienceData.experience.ingestions | any(.substanceName == $sortOptions.substanceName and .administrationRoute == $sortOptions.ingestionMethod))
|
|
||||||
then [$experienceData] else [] end
|
|
||||||
));
|
|
||||||
|
|
||||||
# speeds up by excluding everything not containing substances & consumers not in filters, wouldn't show any data anyway
|
|
||||||
if $substanceFilter != null then filterBySubstanceFilter end |
|
|
||||||
filterByConsumerFilter |
|
|
||||||
|
|
||||||
if
|
|
||||||
$sortMethod == "old-to-new" or $sortMethod == null
|
|
||||||
then
|
|
||||||
sort_by(oldToNewSort)
|
|
||||||
elif
|
|
||||||
$sortMethod == "highest-combined-dose"
|
|
||||||
then
|
|
||||||
utilsLib::assert($sortOptions.substanceName != null; "substanceName not provided as sortOption") |
|
|
||||||
filterBySubstanceAndConsumer |
|
|
||||||
sort_by(highestCombinedDoseSort, oldToNewSort) |
|
|
||||||
reverse
|
|
||||||
elif
|
|
||||||
$sortMethod == "highest-dose-for-method"
|
|
||||||
then
|
|
||||||
utilsLib::assert($sortOptions.substanceName != null; "substanceName not provided as sortOption") |
|
|
||||||
filterByIngestionMethodForSubstance |
|
|
||||||
sort_by(highestMethodDoseSort, oldToNewSort) |
|
|
||||||
reverse
|
|
||||||
end;
|
|
||||||
|
|
||||||
$experiences |
|
|
||||||
experiencesWithExtraData($customUnits) |
|
|
||||||
sortFilter;
|
|
||||||
|
|
||||||
def experienceByTitle($name):
|
|
||||||
utilsLib::assert((. | type) == "array"; "experienceByTitle takes a array of experiences as input") |
|
|
||||||
map(select(.title == $name))[0];
|
|
|
@ -1,22 +0,0 @@
|
||||||
import "testLib" as testLib;
|
|
||||||
import "journalLib" as journalLib;
|
|
||||||
|
|
||||||
import "testdata/tests_export" as $exportDataArray;
|
|
||||||
|
|
||||||
def journalLibTests:
|
|
||||||
testLib::expectPassed(testLib::runTest(
|
|
||||||
"invalid input to experienceByTitle";
|
|
||||||
(
|
|
||||||
null | journalLib::experienceByTitle("Test")
|
|
||||||
);
|
|
||||||
. == "experienceByTitle takes a array of experiences as input";
|
|
||||||
true
|
|
||||||
)) |
|
|
||||||
testLib::expectPassed(testLib::runTest(
|
|
||||||
"experience not found";
|
|
||||||
(
|
|
||||||
$exportDataArray[0].experiences | journalLib::experienceByTitle("Test")
|
|
||||||
);
|
|
||||||
. == null;
|
|
||||||
false
|
|
||||||
));
|
|
|
@ -1,117 +0,0 @@
|
||||||
import "typeLib" as typeLib;
|
|
||||||
|
|
||||||
def ensureAdministrationRoute:
|
|
||||||
. as $administrationRoute |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
if [
|
|
||||||
"ORAL",
|
|
||||||
"SUBLINGUAL",
|
|
||||||
"BUCCAL",
|
|
||||||
"INSUFFLATED",
|
|
||||||
"RECTAL",
|
|
||||||
"TRANSDERMAL",
|
|
||||||
"SUBCUTANEOUS",
|
|
||||||
"INTRAMUSCULAR",
|
|
||||||
"INTRAVENOUS",
|
|
||||||
"SMOKED",
|
|
||||||
"INHALED"
|
|
||||||
] | any(index($administrationRoute)) | not then
|
|
||||||
typeLib::typeErrorText("administrationRoute")
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ensureIngestion:
|
|
||||||
. as $ingestion |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
typeLib::ensureObject |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "substanceName") |
|
|
||||||
.substanceName | typeLib::ensureWrapError("experience:substanceName"; typeLib::ensureString) |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "time") |
|
|
||||||
.time | typeLib::ensureWrapError("experience:time"; typeLib::ensureNumber) |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "creationDate") |
|
|
||||||
.creationDate | typeLib::ensureWrapError("experience:creationDate"; typeLib::ensureNumber) |
|
|
||||||
|
|
||||||
# TODO: check routes
|
|
||||||
$ingestion |
|
|
||||||
typeLib::ensureKey("ingestion"; "administrationRoute") |
|
|
||||||
$ingestion.administrationRoute |
|
|
||||||
typeLib::ensureWrapError("experience:administrationRoute"; typeLib::ensureString) |
|
|
||||||
$ingestion.administrationRoute |
|
|
||||||
ensureAdministrationRoute |
|
|
||||||
|
|
||||||
typeLib::ensureWrapError(
|
|
||||||
"experience:dose";
|
|
||||||
$ingestion | typeLib::ensureIfKey("dose"; typeLib::ensureNullOr(typeLib::ensureNumber))
|
|
||||||
) |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "isDoseAnEstimate") |
|
|
||||||
.isDoseAnEstimate | typeLib::ensureWrapError("experience:isDoseAnEstimate"; typeLib::ensureBool) |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "units") |
|
|
||||||
.units | typeLib::ensureWrapError("experience:units"; typeLib::ensureString) |
|
|
||||||
|
|
||||||
$ingestion | typeLib::ensureKey("ingestion"; "notes") |
|
|
||||||
.notes | typeLib::ensureWrapError("experience:notes"; typeLib::ensureString) |
|
|
||||||
|
|
||||||
typeLib::ensureWrapError(
|
|
||||||
"experience:stomachFullness";
|
|
||||||
$ingestion | typeLib::ensureIfKey("stomachFullness"; typeLib::ensureNullOr(typeLib::ensureString))
|
|
||||||
) |
|
|
||||||
|
|
||||||
typeLib::ensureWrapError(
|
|
||||||
"experience:customUnitId";
|
|
||||||
$ingestion | typeLib::ensureIfKey("customUnitId"; typeLib::ensureNullOr(typeLib::ensureNumber))
|
|
||||||
) |
|
|
||||||
|
|
||||||
$ingestion
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ensureIngestions:
|
|
||||||
. as $ingestions |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
(reduce $ingestions[] as $ingestion (null; $ingestion | ensureIngestion))
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ensureExperience:
|
|
||||||
. as $experience |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
$experience | typeLib::ensureObject |
|
|
||||||
|
|
||||||
$experience | typeLib::ensureKey("experience"; "title") |
|
|
||||||
$experience.title | typeLib::ensureWrapError("experience:title"; typeLib::ensureString) |
|
|
||||||
|
|
||||||
$experience | typeLib::ensureKey("experience"; "text") |
|
|
||||||
$experience.text | typeLib::ensureWrapError("experience:text"; typeLib::ensureString) |
|
|
||||||
|
|
||||||
$experience | typeLib::ensureKey("experience"; "creationDate") |
|
|
||||||
$experience.creationDate | typeLib::ensureWrapError("experience:creationDate"; typeLib::ensureNumber) |
|
|
||||||
|
|
||||||
$experience | typeLib::ensureKey("experience"; "sortDate") |
|
|
||||||
$experience.sortDate | typeLib::ensureWrapError("experience:sortDate"; typeLib::ensureNumber) |
|
|
||||||
|
|
||||||
$experience | typeLib::ensureKey("experience"; "ingestions") |
|
|
||||||
$experience.ingestions | typeLib::ensureWrapError("experience:ingestions"; typeLib::ensureArray) |
|
|
||||||
$experience.ingestions | ensureIngestions |
|
|
||||||
|
|
||||||
$experience
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ensureExperiences:
|
|
||||||
. as $experiences |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
(reduce $experiences[] as $experience (null; $experience | ensureExperience))
|
|
||||||
end;
|
|
||||||
|
|
||||||
def ensureExportData:
|
|
||||||
. as $exportData |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
typeLib::ensureObject |
|
|
||||||
typeLib::ensureKey("exportData"; "customSubstances") |
|
|
||||||
typeLib::ensureKey("exportData"; "customUnits") |
|
|
||||||
typeLib::ensureKey("exportData"; "experiences") |
|
|
||||||
typeLib::ensureKey("exportData"; "substanceCompanions") |
|
|
||||||
.experiences | ensureExperiences
|
|
||||||
end;
|
|
|
@ -1,106 +0,0 @@
|
||||||
import "typeLib" as typeLib;
|
|
||||||
import "ansiLib" as ansiLib;
|
|
||||||
import "JSONLib" as JSONLib;
|
|
||||||
|
|
||||||
def logLevels:
|
|
||||||
[
|
|
||||||
"trace",
|
|
||||||
"debug",
|
|
||||||
"info",
|
|
||||||
"warn",
|
|
||||||
"error",
|
|
||||||
"fatal"
|
|
||||||
];
|
|
||||||
|
|
||||||
def isJSONTooComplex:
|
|
||||||
(.. | length) > 128;
|
|
||||||
|
|
||||||
def isValidLogLevel($logLevel):
|
|
||||||
logLevels | any(index($logLevel));
|
|
||||||
|
|
||||||
def ensureLogLevel:
|
|
||||||
. as $logLevel |
|
|
||||||
if typeLib::typecheckingEnabled then
|
|
||||||
if isValidLogLevel($logLevel) | not then typeLib::typeErrorText("logLevel") end
|
|
||||||
end;
|
|
||||||
|
|
||||||
def maxLogLevel:
|
|
||||||
($ENV["JQ_LOGLEVEL"] // "info") as $maxLogLevel |
|
|
||||||
if isValidLogLevel($maxLogLevel) | not then
|
|
||||||
"info"
|
|
||||||
else $maxLogLevel end;
|
|
||||||
|
|
||||||
def shouldLog($logLevel):
|
|
||||||
maxLogLevel as $maxLogLevel |
|
|
||||||
logLevels as $logLevels |
|
|
||||||
reduce range($logLevels | length) as $logLevelIndex ({};
|
|
||||||
.[$logLevels[$logLevelIndex]] = $logLevelIndex
|
|
||||||
) as $logLevelIndexes |
|
|
||||||
$logLevelIndexes[$maxLogLevel] <= $logLevelIndexes[$logLevel];
|
|
||||||
|
|
||||||
def ansiColourByName:
|
|
||||||
. as $name |
|
|
||||||
{
|
|
||||||
"red": "31",
|
|
||||||
"yellow": "33",
|
|
||||||
"blue": "36",
|
|
||||||
"gray": "37"
|
|
||||||
}[$name];
|
|
||||||
|
|
||||||
def levelColour:
|
|
||||||
. as $logLevel |
|
|
||||||
{
|
|
||||||
"trace": "yellow",
|
|
||||||
"debug": "gray",
|
|
||||||
"info": "blue",
|
|
||||||
"warn": "yellow",
|
|
||||||
"error": "red",
|
|
||||||
"fatal": "red"
|
|
||||||
}[$logLevel] | ansiColourByName;
|
|
||||||
|
|
||||||
def log($logLevel; $msg; $data):
|
|
||||||
. as $input |
|
|
||||||
($logLevel | ensureLogLevel) |
|
|
||||||
($msg | typeLib::ensureNullOr(typeLib::ensureString)) |
|
|
||||||
|
|
||||||
if shouldLog($logLevel) then
|
|
||||||
($logLevel | levelColour) as $logLevelColour |
|
|
||||||
($logLevel | ascii_upcase | ansiLib::colourText($logLevelColour)) as $logLevelText |
|
|
||||||
($msg | ansiLib::colourText("gray" | ansiColourByName)) as $msgText |
|
|
||||||
|
|
||||||
if $data != null then
|
|
||||||
if $data | isJSONTooComplex | not then
|
|
||||||
$data | JSONLib::encodeJSON(true; 2)
|
|
||||||
else
|
|
||||||
$data | tojson
|
|
||||||
end
|
|
||||||
else "" end | . as $dataText |
|
|
||||||
|
|
||||||
"\($logLevelText) \($msgText) \($dataText)\n" |
|
|
||||||
if $logLevel == "fatal" then halt_error(1) else stderr end
|
|
||||||
end |
|
|
||||||
|
|
||||||
$input;
|
|
||||||
|
|
||||||
def trace($msg; $data): log("trace"; $msg; $data);
|
|
||||||
def debug($msg; $data): log("debug"; $msg; $data);
|
|
||||||
def info($msg; $data): log("info"; $msg; $data);
|
|
||||||
def warn($msg; $data): log("warn"; $msg; $data);
|
|
||||||
def error($msg; $data): log("error"; $msg; $data);
|
|
||||||
def fatal($msg; $data): log("fatal"; $msg; $data);
|
|
||||||
|
|
||||||
def trace($msg): trace($msg; null);
|
|
||||||
def debug($msg): debug($msg; null);
|
|
||||||
def info($msg): info($msg; null);
|
|
||||||
def warn($msg): warn($msg; null);
|
|
||||||
def error($msg): error($msg; null);
|
|
||||||
def fatal($msg): fatal($msg; null);
|
|
||||||
|
|
||||||
def logTest:
|
|
||||||
([
|
|
||||||
"trace",
|
|
||||||
"debug",
|
|
||||||
"info",
|
|
||||||
"warn",
|
|
||||||
"error"
|
|
||||||
][] | log(.; "example text \(.)"; {})) | empty;
|
|
|
@ -1,2 +0,0 @@
|
||||||
def round(precision):
|
|
||||||
. * pow(10; precision) | round / pow(10; precision);
|
|
|
@ -1,10 +0,0 @@
|
||||||
def titleCase:
|
|
||||||
[splits("\\b") | select(length>0)]
|
|
||||||
| map((.[:1]|ascii_upcase) + (.[1:] |ascii_downcase))
|
|
||||||
| join("");
|
|
||||||
|
|
||||||
def lpad(string;len;fill):
|
|
||||||
if len == 0 then string else (fill * len)[0:len] + string end;
|
|
||||||
|
|
||||||
def rpad(string;len;fill):
|
|
||||||
if len == 0 then string else string + (fill * len)[0:len] end;
|
|
|
@ -1,2 +0,0 @@
|
||||||
def _readFile($filename): error("_readFile only supported in gojq-extended");
|
|
||||||
def _writeFileString($filename): error("_writeFileString only supported in gojq-extended");
|
|
|
@ -1,84 +0,0 @@
|
||||||
import "stringLib" as stringLib;
|
|
||||||
|
|
||||||
def printPrettyTable($title; $columnTitles; $rows):
|
|
||||||
if [$rows[] | length] | unique | length > 1 then error("non-even number of columns") end |
|
|
||||||
|
|
||||||
$title | if . == null then "" end | . as $title |
|
|
||||||
|
|
||||||
" | " as $numColumnseperator |
|
|
||||||
|
|
||||||
def padRow($numColumns; $maxColumnLengths):
|
|
||||||
. as $row |
|
|
||||||
[
|
|
||||||
range($numColumns) as $columnNumber |
|
|
||||||
$row[$columnNumber] as $content |
|
|
||||||
if $columnNumber == 0 then
|
|
||||||
stringLib::lpad($content; $maxColumnLengths[$columnNumber] - ($content | length) ; " ")
|
|
||||||
else
|
|
||||||
stringLib::rpad($content; $maxColumnLengths[$columnNumber] - ($content | length) ; " ")
|
|
||||||
end
|
|
||||||
];
|
|
||||||
|
|
||||||
([$rows[] | length] | unique[0]) as $numColumns |
|
|
||||||
([$columnTitles | length] | unique[0]) as $numColumnTitles |
|
|
||||||
if $numColumns != $numColumnTitles then error("unequal title rows and columns") end |
|
|
||||||
|
|
||||||
[$columnTitles[] | length] as $maxColumnLengths |
|
|
||||||
(reduce $rows[] as $column ($maxColumnLengths;
|
|
||||||
[
|
|
||||||
range($numColumns) as $columnNumber |
|
|
||||||
[
|
|
||||||
.[$columnNumber],
|
|
||||||
($column[$columnNumber] | length)
|
|
||||||
] | max
|
|
||||||
]
|
|
||||||
)) as $maxColumnLengths |
|
|
||||||
|
|
||||||
$columnTitles |
|
|
||||||
padRow($numColumns; $maxColumnLengths) |
|
|
||||||
join($numColumnseperator) as $columnTitleRow |
|
|
||||||
|
|
||||||
[$rows[] | padRow($numColumns; $maxColumnLengths)] as $rows |
|
|
||||||
|
|
||||||
$title | length as $titleLength |
|
|
||||||
|
|
||||||
((($numColumns - 1) * ($numColumnseperator | length)) + ($maxColumnLengths | add)) as $maxRowLength |
|
|
||||||
[
|
|
||||||
$maxRowLength,
|
|
||||||
$titleLength
|
|
||||||
] | max as $maxLength |
|
|
||||||
|
|
||||||
|
|
||||||
# Pad title to be centered to maximum row length
|
|
||||||
$title | if $titleLength < $maxRowLength then
|
|
||||||
stringLib::lpad($title; ($maxLength - $titleLength) / 2; " ")
|
|
||||||
end | . as $title |
|
|
||||||
|
|
||||||
# if title is longer than maximum row length, pad the first row the difference between them
|
|
||||||
if $titleLength > $maxRowLength then
|
|
||||||
[
|
|
||||||
$rows[] as $row |
|
|
||||||
[
|
|
||||||
stringLib::lpad($row[0]; $titleLength - $maxRowLength; " ")
|
|
||||||
] + $row[1:]
|
|
||||||
]
|
|
||||||
else $rows end | . as $rows |
|
|
||||||
|
|
||||||
($rows | map(join($numColumnseperator))) as $rows |
|
|
||||||
if $title != "" then
|
|
||||||
|
|
||||||
[
|
|
||||||
$title,
|
|
||||||
([range($maxLength) | "-"] | join("")),
|
|
||||||
|
|
||||||
$columnTitleRow,
|
|
||||||
([range($maxLength) | "-"] | join("")),
|
|
||||||
$rows
|
|
||||||
] | flatten | join("\n") + "\n"
|
|
||||||
else
|
|
||||||
|
|
||||||
[
|
|
||||||
$columnTitleRow,
|
|
||||||
$rows
|
|
||||||
] | flatten | join("\n") + "\n"
|
|
||||||
end;
|
|
|
@ -1,114 +0,0 @@
|
||||||
def printTestResult:
|
|
||||||
. as $result | $result |
|
|
||||||
if .passed then
|
|
||||||
"Test \"\(.name)\" Passed"
|
|
||||||
else
|
|
||||||
"Test \"\(.name)\" Failed\nReason: \(.reason)\nOutput: \(.output | tojson)"
|
|
||||||
end;
|
|
||||||
|
|
||||||
def runTest($name; testExpr; checkResult; $expectError):
|
|
||||||
try (
|
|
||||||
(null | testExpr) as $output |
|
|
||||||
if $expectError then
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: false,
|
|
||||||
reason: "Expected error but no error was raised",
|
|
||||||
$output
|
|
||||||
}
|
|
||||||
elif ($output | checkResult) then
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: true,
|
|
||||||
$output
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: false,
|
|
||||||
reason: "Result was different from expected",
|
|
||||||
$output
|
|
||||||
}
|
|
||||||
end
|
|
||||||
) catch (
|
|
||||||
. as $error |
|
|
||||||
if ($expectError | not) then
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: false,
|
|
||||||
reason: "Error caught when no error was expected",
|
|
||||||
output: $error
|
|
||||||
}
|
|
||||||
elif ($expectError and ($error | checkResult)) then
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: true,
|
|
||||||
output: $error
|
|
||||||
}
|
|
||||||
elif ($expectError and ($error | checkResult | not)) then
|
|
||||||
{
|
|
||||||
$name,
|
|
||||||
passed: false,
|
|
||||||
reason: "Expected error but received different error",
|
|
||||||
output: $error
|
|
||||||
}
|
|
||||||
else
|
|
||||||
error("unknown error")
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
def expectPassed:
|
|
||||||
if (.passed | not) then
|
|
||||||
error(. | printTestResult)
|
|
||||||
end;
|
|
||||||
def expectPassed($result): $result | expectPassed;
|
|
||||||
|
|
||||||
def expectFailed:
|
|
||||||
if (.passed) then
|
|
||||||
error(. | printTestResult)
|
|
||||||
end;
|
|
||||||
def expectFailed($result): $result | expectFailed;
|
|
||||||
|
|
||||||
def testTests:
|
|
||||||
expectPassed(runTest(
|
|
||||||
"passing test";
|
|
||||||
true;
|
|
||||||
. == true;
|
|
||||||
false
|
|
||||||
)) |
|
|
||||||
expectPassed(runTest(
|
|
||||||
"error expected and equal";
|
|
||||||
error("error");
|
|
||||||
. == "error";
|
|
||||||
true
|
|
||||||
)) |
|
|
||||||
expectFailed(runTest(
|
|
||||||
"failing test";
|
|
||||||
true;
|
|
||||||
. == false;
|
|
||||||
false
|
|
||||||
)) |
|
|
||||||
expectFailed(runTest(
|
|
||||||
"error expected but no error";
|
|
||||||
null;
|
|
||||||
. == null;
|
|
||||||
true
|
|
||||||
)) |
|
|
||||||
expectFailed(runTest(
|
|
||||||
"error not expected";
|
|
||||||
error("error");
|
|
||||||
. == null;
|
|
||||||
false
|
|
||||||
)) |
|
|
||||||
expectFailed(runTest(
|
|
||||||
"error different";
|
|
||||||
error("error");
|
|
||||||
. == "different error";
|
|
||||||
true
|
|
||||||
));
|
|
||||||
|
|
||||||
def testLibMain:
|
|
||||||
testTests |
|
|
||||||
"Tests Passed\n" |
|
|
||||||
halt_error(0);
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
import "testLib" as testLib;
|
|
||||||
|
|
||||||
def typecheckingEnabled:
|
|
||||||
if $ENV["JQ_TYPECHECKING"] != null then
|
|
||||||
["true", "1", "debug"] | any(index($ENV["JQ_TYPECHECKING"]))
|
|
||||||
else false end;
|
|
||||||
|
|
||||||
def typecheckingDebug:
|
|
||||||
if $ENV["JQ_TYPECHECKING"] == "debug" then
|
|
||||||
true
|
|
||||||
else false end;
|
|
||||||
|
|
||||||
def dumpType:
|
|
||||||
if (. | type) == "object" then
|
|
||||||
. | [to_entries | sort_by(.key)[] | {"\(.key)": (.value|dumpType)}] | add
|
|
||||||
elif (. | type) == "array" then
|
|
||||||
[.[] | dumpType] as $array |
|
|
||||||
if ($array | length > 0) then
|
|
||||||
if ($array | all(select(. == $array[0]))) then
|
|
||||||
[$array[0]]
|
|
||||||
else
|
|
||||||
$array
|
|
||||||
end
|
|
||||||
else
|
|
||||||
"array:empty/unknown"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
. | type
|
|
||||||
end;
|
|
||||||
|
|
||||||
def typeErrorText:
|
|
||||||
. as $type |
|
|
||||||
"Type Error Checking '\($type)'";
|
|
||||||
|
|
||||||
def typeErrorText($type): $type | typeErrorText;
|
|
||||||
|
|
||||||
def typeError($type):
|
|
||||||
if typecheckingDebug then debug({typeName: $type, value: ., valueType: . | dumpType}) end |
|
|
||||||
error($type | typeErrorText);
|
|
||||||
|
|
||||||
def ensureNull: if typecheckingEnabled and (. | type != "null") then typeError("null") end;
|
|
||||||
def ensureBool: if typecheckingEnabled and (. | type) != "boolean" then typeError("bool") end;
|
|
||||||
def ensureString: if typecheckingEnabled and (. | type) != "string" then typeError("string") end;
|
|
||||||
def ensureArray: if typecheckingEnabled and (. | type) != "array" then typeError("array") end;
|
|
||||||
def ensureObject: if typecheckingEnabled and (. | type) != "object" then typeError("object") end;
|
|
||||||
def ensureNumber: if typecheckingEnabled and (. | type) != "number" then typeError("number") end;
|
|
||||||
|
|
||||||
def ensureNull($value): $value | ensureNull;
|
|
||||||
def ensureBool($value): $value | ensureBool;
|
|
||||||
def ensureString($value): $value | ensureString;
|
|
||||||
def ensureArray($value): $value | ensureArray;
|
|
||||||
def ensureObject($value): $value | ensureObject;
|
|
||||||
def ensureNumber($value): $value | ensureNumber;
|
|
||||||
|
|
||||||
def ensureNullOr(ensureType):
|
|
||||||
if . == null then . else . | ensureType end;
|
|
||||||
|
|
||||||
def ensureKey($type; $key): if (. | has($key) | not) then typeError("\($type):\($key)") end;
|
|
||||||
def ensureKey($value; $type; $key): $value | ensureKey($type; $key);
|
|
||||||
|
|
||||||
def ensureIfKey($key; ensureType): if (. | has($key)) then .[$key] | ensureType end;
|
|
||||||
|
|
||||||
def ensureWrapError($newType; ensureType):
|
|
||||||
. as $value |
|
|
||||||
try (. | ensureType)
|
|
||||||
catch (
|
|
||||||
. as $prevError |
|
|
||||||
if typecheckingDebug then debug({$newType, $prevError}) end |
|
|
||||||
error(typeErrorText($newType))
|
|
||||||
);
|
|
||||||
|
|
||||||
def ensureWrapError($value; $newType; ensureType):
|
|
||||||
$value | ensureWrapError($newType; ensureType);
|
|
||||||
|
|
||||||
# JQ_TYPECHECKING=true required for tests
|
|
||||||
def typeLibTests:
|
|
||||||
testLib::expectPassed(testLib::runTest(
|
|
||||||
"null is null";
|
|
||||||
(null | ensureNull);
|
|
||||||
true;
|
|
||||||
false
|
|
||||||
)) |
|
|
||||||
testLib::expectPassed(testLib::runTest(
|
|
||||||
"boolean is not null";
|
|
||||||
(true | ensureNull);
|
|
||||||
(. == typeErrorText("null"));
|
|
||||||
true
|
|
||||||
));
|
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import "stringLib" as stringLib;
|
|
||||||
|
|
||||||
def debugLog($target; $value):
|
|
||||||
if
|
|
||||||
($ENV["JQ_DEBUG"] == $target)
|
|
||||||
or
|
|
||||||
($target == "*")
|
|
||||||
or
|
|
||||||
($ENV["JQ_DEBUG"] | split(",") | any(. as $debugTarget | $target | startswith($debugTarget | split("*")[0])))
|
|
||||||
then
|
|
||||||
debug({$target, $value})
|
|
||||||
end;
|
|
||||||
|
|
||||||
def assert(cond; $msg): if cond then . else error($msg) end;
|
|
||||||
def assert($loc; cond; $msg): assert(cond; "\($loc.file):\($loc.line): " + $msg);
|
|
||||||
|
|
||||||
def firstN($n): .[:$n];
|
|
||||||
|
|
||||||
def orderedUnique:
|
|
||||||
(reduce .[] as $value ([];
|
|
||||||
if
|
|
||||||
(. | any(index($value)) | not)
|
|
||||||
then . += [$value]
|
|
||||||
else . end
|
|
||||||
));
|
|
||||||
|
|
||||||
def sortFilterFromString($filterString):
|
|
||||||
($filterString | split("|")).[] as $filter |
|
|
||||||
if
|
|
||||||
$filter == "reverse" then . | reverse
|
|
||||||
elif ($filter | startswith("firstN")) then
|
|
||||||
($filter | ltrimstr("firstN(") | rtrimstr(")")) as $arg |
|
|
||||||
. | firstN($arg | try fromjson catch error("invalid number passed to firstN"))
|
|
||||||
end;
|
|
322
tool/main.jq
322
tool/main.jq
|
@ -1,322 +0,0 @@
|
||||||
import "lib/typeLib" as typeLib;
|
|
||||||
import "lib/argsLib" as argsLib;
|
|
||||||
import "lib/stringLib" as stringLib;
|
|
||||||
import "lib/tableLib" as tableLib;
|
|
||||||
import "lib/utilsLib" as utilsLib;
|
|
||||||
import "lib/journalLib" as journalLib;
|
|
||||||
import "lib/gojqExtendedLib" as gojqExtendedLib;
|
|
||||||
import "lib/journalTypes" as journalTypes;
|
|
||||||
|
|
||||||
import "journalUtils" as journalUtils;
|
|
||||||
|
|
||||||
def printExperienceStats($stats; $substanceFilter; $consumerFilter; $withTitle):
|
|
||||||
. as $experience |
|
|
||||||
|
|
||||||
($consumerFilter // ["default"]) as $consumerFilter |
|
|
||||||
|
|
||||||
$experience.ingestions |
|
|
||||||
journalLib::filterIngestions($substanceFilter; $consumerFilter) |
|
|
||||||
sort_by(.sortDate) as $ingestions |
|
|
||||||
|
|
||||||
($ingestions | journalLib::ingestionsSubstanceNames) as $substanceNames |
|
|
||||||
($ingestions | journalLib::ingestionsByConsumer) as $ingestionsByConsumer |
|
|
||||||
|
|
||||||
($ingestionsByConsumer | keys) as $consumerNames |
|
|
||||||
|
|
||||||
"" as $experienceStatsText |
|
|
||||||
$experienceStatsText |
|
|
||||||
if $withTitle then
|
|
||||||
. += ($experience | journalUtils::formatExperienceTitle | . + "\n")
|
|
||||||
end | . as $experienceStatsText |
|
|
||||||
|
|
||||||
reduce $consumerNames[] as $consumerName ($experienceStatsText;
|
|
||||||
. as $experienceStatsText |
|
|
||||||
$experienceStatsText |
|
|
||||||
if ($consumerNames != ["default"])
|
|
||||||
then . += "Consumer: \($consumerName)\n"
|
|
||||||
end | . as $experienceStatsText |
|
|
||||||
|
|
||||||
($ingestionsByConsumer[$consumerName] | journalLib::ingestionsSubstanceNames) as $consumerSubstanceNames |
|
|
||||||
|
|
||||||
$experienceStatsText | reduce $consumerSubstanceNames[] as $substanceName (.;
|
|
||||||
. as $experienceStatsText |
|
|
||||||
|
|
||||||
($stats.[$consumerName].[$substanceName] | keys) as $ingestionMethods |
|
|
||||||
|
|
||||||
($experienceStatsText | . += "Substance: \($substanceName)\n") as $experienceStatsText |
|
|
||||||
|
|
||||||
reduce ($stats.[$consumerName].[$substanceName] | to_entries)[] as $ingestionMethodInfo ($experienceStatsText;
|
|
||||||
. as $experienceStatsText |
|
|
||||||
|
|
||||||
$ingestionMethodInfo |
|
|
||||||
.key as $ingestionMethod |
|
|
||||||
.value as $ingestionInfo |
|
|
||||||
|
|
||||||
def formatIngestionInfo:
|
|
||||||
if $ingestionInfo.dose == null then
|
|
||||||
"Unknown \($ingestionInfo.unit)"
|
|
||||||
else
|
|
||||||
if $ingestionInfo.isEstimate then "~" else "" end +
|
|
||||||
"\($ingestionInfo.dose * 100 | round / 100)" +
|
|
||||||
if $ingestionInfo.standardDeviation != null then
|
|
||||||
"±\($ingestionInfo.standardDeviation)"
|
|
||||||
else "" end +
|
|
||||||
|
|
||||||
if $ingestionInfo.isUnknown then "+ Unknown" else "" end +
|
|
||||||
" \($ingestionInfo.unit)"
|
|
||||||
end;
|
|
||||||
|
|
||||||
$experienceStatsText |
|
|
||||||
. += "Dose (\($ingestionMethod | stringLib::titleCase)): \($ingestionInfo | formatIngestionInfo)\n" |
|
|
||||||
. as $experienceStatsText |
|
|
||||||
|
|
||||||
$experienceStatsText
|
|
||||||
) | . as $experienceStatsText |
|
|
||||||
|
|
||||||
$experienceStatsText | if ($ingestionMethods | length > 1) then
|
|
||||||
($stats | journalLib::statsCalculateCombinedDose($substanceName; $consumerName)) as $combinedDose |
|
|
||||||
. += "Combined Dose: \($combinedDose.dose // "Unknown") \($combinedDose.unit)\n"
|
|
||||||
end | . as $experienceStatsText |
|
|
||||||
|
|
||||||
$experienceStatsText | . += "\n"
|
|
||||||
)
|
|
||||||
) | rtrimstr("\n\n");
|
|
||||||
|
|
||||||
def printExperienceLog($customUnits; $substanceFilter; $consumerFilter; $pretty; $withTitle):
|
|
||||||
. as $experience |
|
|
||||||
($consumerFilter // ["default"]) as $consumerFilter |
|
|
||||||
|
|
||||||
$experience.ingestions |
|
|
||||||
journalLib::filterIngestions($substanceFilter; $consumerFilter) |
|
|
||||||
sort_by(.sortDate) as $ingestions |
|
|
||||||
|
|
||||||
$ingestions | journalLib::ingestionsConsumerNames as $consumerNames |
|
|
||||||
|
|
||||||
if ($consumerNames != ["default"]) then
|
|
||||||
["Substance", "Dose", "ROA", "Consumer", "Time"]
|
|
||||||
else
|
|
||||||
["Substance", "Dose", "ROA", "Time"]
|
|
||||||
end | . as $columnTitles |
|
|
||||||
|
|
||||||
[
|
|
||||||
$ingestions[] as $ingestion |
|
|
||||||
$ingestion |
|
|
||||||
.substanceName as $substanceName |
|
|
||||||
journalLib::ingestionConsumerName as $consumerName |
|
|
||||||
journalUtils::formatIngestionDose($customUnits) as $doseText |
|
|
||||||
journalUtils::formatIngestionROA($customUnits) as $roaText |
|
|
||||||
journalUtils::formatIngestionTime as $timeText |
|
|
||||||
if ($consumerNames != ["default"])
|
|
||||||
then [$substanceName, $doseText, $roaText, $consumerName, $timeText]
|
|
||||||
else [$substanceName, $doseText, $roaText, $timeText] end
|
|
||||||
] as $rows |
|
|
||||||
|
|
||||||
tableLib::printPrettyTable(
|
|
||||||
if $withTitle then ($experience | journalUtils::formatExperienceTitle) else null end;
|
|
||||||
$columnTitles;
|
|
||||||
$rows
|
|
||||||
);
|
|
||||||
|
|
||||||
def printExperiences($customUnits; $substanceFilter; $consumerFilter):
|
|
||||||
. as $experiences |
|
|
||||||
|
|
||||||
$experiences |
|
|
||||||
.[] as $entry |
|
|
||||||
$entry.experience as $experience |
|
|
||||||
$entry.stats as $stats |
|
|
||||||
($experience | printExperienceLog(
|
|
||||||
$customUnits;
|
|
||||||
$substanceFilter;
|
|
||||||
$consumerFilter;
|
|
||||||
true;
|
|
||||||
true
|
|
||||||
)) +
|
|
||||||
"\nCumulative Doses:\n" +
|
|
||||||
($experience | printExperienceStats(
|
|
||||||
$stats;
|
|
||||||
$substanceFilter;
|
|
||||||
$consumerFilter;
|
|
||||||
false
|
|
||||||
)) + "\n";
|
|
||||||
|
|
||||||
|
|
||||||
def main:
|
|
||||||
def usage:
|
|
||||||
[
|
|
||||||
"psychonaut_journal_stats {printExperience,printExperiences}",
|
|
||||||
""
|
|
||||||
] | join("\n") | halt_error(1);
|
|
||||||
|
|
||||||
($ARGS | argsLib::parseArgs) as $parsedArgs |
|
|
||||||
|
|
||||||
$parsedArgs.nonArgs[0] as $program |
|
|
||||||
($parsedArgs | .nonArgs |= $parsedArgs.nonArgs[1:]) as $parsedArgs |
|
|
||||||
|
|
||||||
if gojqExtendedLib::checkSupported then
|
|
||||||
if $parsedArgs.longArgs["export-file"] then
|
|
||||||
$parsedArgs.longArgs["export-file"]
|
|
||||||
else
|
|
||||||
$ARGS.named["exportFileName"]
|
|
||||||
end | . as $exportFileName |
|
|
||||||
{
|
|
||||||
name: $exportFileName,
|
|
||||||
content: gojqExtendedLib::readFile($exportFileName) | fromjson
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if $parsedArgs.longArgs | has("export-file") then
|
|
||||||
"--export-file was provided but this version of jq doesn't support reading files" +
|
|
||||||
"using EXPORT_FILE instead\n" | stderr
|
|
||||||
end |
|
|
||||||
{
|
|
||||||
name: $ARGS.named["exportFileName"],
|
|
||||||
content: $ARGS.named["exportFile"][0]
|
|
||||||
}
|
|
||||||
end | . as $exportFile |
|
|
||||||
|
|
||||||
$exportFile.name as $exportFileName |
|
|
||||||
$exportFile.content as $exportData |
|
|
||||||
|
|
||||||
if $exportData == null then
|
|
||||||
if gojqExtendedLib::checkSupported then
|
|
||||||
"please set EXPORT_FILE= or --export-file to a valid psychonaut journal export file\n" |
|
|
||||||
halt_error(1)
|
|
||||||
else
|
|
||||||
"please set EXPORT_FILE= to a valid psychonaut journal export file\n" |
|
|
||||||
halt_error(1)
|
|
||||||
end
|
|
||||||
end |
|
|
||||||
|
|
||||||
$exportData | journalTypes::ensureExportData |
|
|
||||||
|
|
||||||
if $program == null then
|
|
||||||
if any($parsedArgs.shortArgs[]; . == "h") then usage end |
|
|
||||||
if ($parsedArgs.longArgs | has("help")) then usage end |
|
|
||||||
|
|
||||||
usage
|
|
||||||
elif $program == "printExperience" then
|
|
||||||
def printExperienceUsage($reason):
|
|
||||||
[
|
|
||||||
$reason,
|
|
||||||
"Usage: printExperience [experienceTitle] --title=bool --stats=bool --substance-filter=[substanceNames,] --consumer-filter=[consumerNames,]",
|
|
||||||
""
|
|
||||||
] | map(select(. != null)) | join("\n") | halt_error(1);
|
|
||||||
|
|
||||||
if any($parsedArgs.shortArgs[]; . == "h") then printExperienceUsage(null) end |
|
|
||||||
if ($parsedArgs.longArgs | has("help")) then printExperienceUsage(null) end |
|
|
||||||
|
|
||||||
$parsedArgs.nonArgs[0] as $experienceTitle |
|
|
||||||
if $experienceTitle == null then printExperienceUsage("experienceTitle not provided") end |
|
|
||||||
|
|
||||||
{
|
|
||||||
substanceFilter: null,
|
|
||||||
consumerFilter: null,
|
|
||||||
withTitle: true,
|
|
||||||
withStats: true,
|
|
||||||
} as $defaultOptions |
|
|
||||||
$defaultOptions as $options |
|
|
||||||
|
|
||||||
reduce ($parsedArgs.longArgs | to_entries[]) as $longArg ($options; (
|
|
||||||
$longArg.key as $arg |
|
|
||||||
$longArg.value as $value |
|
|
||||||
|
|
||||||
if $arg == "title" then
|
|
||||||
.withTitle |= ($value // $defaultOptions.withTitle | argsLib::parseArgBool)
|
|
||||||
end |
|
|
||||||
if $arg == "stats" then
|
|
||||||
.withStats |= ($value // $defaultOptions.withStats | argsLib::parseArgBool)
|
|
||||||
end |
|
|
||||||
if $arg == "substance-filter" then
|
|
||||||
.substanceFilter |= ($parsedArgs.longArgs.["substance-filter"] | split(","))
|
|
||||||
end |
|
|
||||||
if $arg == "consumer-filter" then
|
|
||||||
.consumerFilter |= ($parsedArgs.longArgs.["consumer-filter"] | split(","))
|
|
||||||
end
|
|
||||||
)) | . as $options |
|
|
||||||
|
|
||||||
$exportData.experiences | journalLib::experienceByTitle($experienceTitle) as $experience |
|
|
||||||
if $experience == null then error("Experience not found") end |
|
|
||||||
|
|
||||||
($experience | printExperienceLog(
|
|
||||||
$exportData.customUnits;
|
|
||||||
$options.substanceFilter;
|
|
||||||
$options.consumerFilter;
|
|
||||||
$options.pretty;
|
|
||||||
$options.withTitle
|
|
||||||
)) as $ingestionLog |
|
|
||||||
|
|
||||||
if $options.withStats then
|
|
||||||
($experience | journalLib::experienceStats($exportData.customUnits)) as $stats |
|
|
||||||
$ingestionLog +
|
|
||||||
"\n\nCumulative Doses:\n" +
|
|
||||||
($experience | printExperienceStats(
|
|
||||||
$stats;
|
|
||||||
$options.substanceFilter;
|
|
||||||
$options.consumerFilter;
|
|
||||||
false
|
|
||||||
))
|
|
||||||
else
|
|
||||||
$ingestionLog
|
|
||||||
end
|
|
||||||
elif $program == "printExperiences" then
|
|
||||||
def printExperiencesUsage($reason):
|
|
||||||
[
|
|
||||||
$reason,
|
|
||||||
"Usage: printExperiences --substance-filter=[substanceNames,] --consumer-filter=[consumerNames,] --sort-method={old-to-new,highest-combined-dose,highest-dose-for-method} --sort-option-substance-name=[string] --sort-options-ingestion-method=[string] --sort-options-consumer-name=[string] --sort-filter={firstN(x),reverse}",
|
|
||||||
""
|
|
||||||
] | map(select(. != null)) | join("\n") | halt_error(1);
|
|
||||||
|
|
||||||
if any($parsedArgs.shortArgs[]; . == "h") then printExperiencesUsage(null) end |
|
|
||||||
if ($parsedArgs.longArgs | has("help")) then printExperiencesUsage(null) end |
|
|
||||||
|
|
||||||
{
|
|
||||||
substanceFilter: null,
|
|
||||||
consumerFilter: null,
|
|
||||||
sortMethod: "old-to-new",
|
|
||||||
sortOptions: {},
|
|
||||||
sortFilter: null
|
|
||||||
} as $defaultOptions |
|
|
||||||
$defaultOptions as $options |
|
|
||||||
|
|
||||||
reduce ($parsedArgs.longArgs | to_entries[]) as $longArg ($options; (
|
|
||||||
$longArg.key as $arg |
|
|
||||||
$longArg.value as $value |
|
|
||||||
if $arg == "substance-filter" then
|
|
||||||
.substanceFilter |= ($parsedArgs.longArgs.["substance-filter"] | split(","))
|
|
||||||
end |
|
|
||||||
if $arg == "consumer-filter" then
|
|
||||||
.consumerFilter |= ($parsedArgs.longArgs.["consumer-filter"] | split(","))
|
|
||||||
end |
|
|
||||||
if $arg == "sort-method" then
|
|
||||||
.sortMethod |= $parsedArgs.longArgs.["sort-method"]
|
|
||||||
end |
|
|
||||||
if $arg == "sort-option-substance-name" then
|
|
||||||
.sortOptions.substanceName |= $parsedArgs.longArgs.["sort-option-substance-name"]
|
|
||||||
end |
|
|
||||||
if $arg == "sort-option-ingestion-method" then
|
|
||||||
.sortOptions.ingestionMethod |= $parsedArgs.longArgs.["sort-option-ingestion-method"]
|
|
||||||
end |
|
|
||||||
if $arg == "sort-option-consumer-name" then
|
|
||||||
.sortOptions.consumerName |= $parsedArgs.longArgs.["sort-option-consumer-name"]
|
|
||||||
end |
|
|
||||||
if $arg == "sort-filter" then
|
|
||||||
.sortFilter |= $parsedArgs.longArgs.["sort-filter"]
|
|
||||||
end
|
|
||||||
)) | . as $options |
|
|
||||||
|
|
||||||
$exportData.experiences |
|
|
||||||
journalLib::filterSortExperiences(
|
|
||||||
$exportData.customUnits;
|
|
||||||
$options.substanceFilter;
|
|
||||||
$options.consumerFilter;
|
|
||||||
$options.sortMethod;
|
|
||||||
$options.sortOptions
|
|
||||||
) |
|
|
||||||
if ($options.sortFilter != null) then utilsLib::sortFilterFromString($options.sortFilter) end |
|
|
||||||
printExperiences(
|
|
||||||
$exportData.customUnits;
|
|
||||||
$options.substanceFilter;
|
|
||||||
$options.consumerFilter
|
|
||||||
)
|
|
||||||
else
|
|
||||||
usage
|
|
||||||
end;
|
|
205
tool/testdata/tests_export.json
vendored
205
tool/testdata/tests_export.json
vendored
|
@ -1,205 +0,0 @@
|
||||||
{
|
|
||||||
"substanceCompanions": [
|
|
||||||
{
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"color": "BLUE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"color": "BROWN",
|
|
||||||
"substanceName": "N-Acetylcysteine"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"substanceName": "Custom",
|
|
||||||
"color": "CYAN"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"customUnits": [
|
|
||||||
{
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"isEstimate": false,
|
|
||||||
"isArchived": false,
|
|
||||||
"creationDate": 1730892759000,
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"unit": "pill",
|
|
||||||
"originalUnit": "mg",
|
|
||||||
"id": 1251361475,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"name": "Tablet",
|
|
||||||
"dose": 200,
|
|
||||||
"note": ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"experiences": [
|
|
||||||
{
|
|
||||||
"isFavorite": false,
|
|
||||||
"text": "",
|
|
||||||
"creationDate": 1730892508000,
|
|
||||||
"title": "Experience 1",
|
|
||||||
"ratings": [],
|
|
||||||
"sortDate": 1730892507000,
|
|
||||||
"timedNotes": [],
|
|
||||||
"ingestions": [
|
|
||||||
{
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"dose": 20,
|
|
||||||
"stomachFullness": null,
|
|
||||||
"administrationRoute": "INSUFFLATED",
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"creationDate": 1730892508000,
|
|
||||||
"units": "mg",
|
|
||||||
"time": 1730892507000,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"notes": "",
|
|
||||||
"consumerName": null,
|
|
||||||
"customUnitId": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"customUnitId": null,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"time": 1730892510000,
|
|
||||||
"stomachFullness": null,
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"dose": 20,
|
|
||||||
"notes": "",
|
|
||||||
"creationDate": 1730892511000,
|
|
||||||
"isDoseAnEstimate": true,
|
|
||||||
"units": "mg",
|
|
||||||
"consumerName": null,
|
|
||||||
"administrationRoute": "INSUFFLATED"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"dose": 100,
|
|
||||||
"units": "mg",
|
|
||||||
"creationDate": 1730892529000,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"consumerName": null,
|
|
||||||
"notes": "",
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"time": 1730892528000,
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"customUnitId": null,
|
|
||||||
"stomachFullness": "EMPTY"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"notes": "",
|
|
||||||
"customUnitId": null,
|
|
||||||
"time": 1730892533000,
|
|
||||||
"isDoseAnEstimate": true,
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"units": "mg",
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"dose": 100,
|
|
||||||
"creationDate": 1730892534000,
|
|
||||||
"stomachFullness": "EMPTY",
|
|
||||||
"consumerName": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"estimatedDoseStandardDeviation": 20,
|
|
||||||
"isDoseAnEstimate": true,
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"dose": 100,
|
|
||||||
"time": 1730892549000,
|
|
||||||
"units": "mg",
|
|
||||||
"consumerName": null,
|
|
||||||
"creationDate": 1730892554000,
|
|
||||||
"notes": "",
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"stomachFullness": "EMPTY",
|
|
||||||
"customUnitId": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"stomachFullness": "EMPTY",
|
|
||||||
"notes": "",
|
|
||||||
"dose": 250,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"time": 1730892600000,
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"creationDate": 1730892603000,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"units": "mg",
|
|
||||||
"consumerName": null,
|
|
||||||
"customUnitId": null,
|
|
||||||
"substanceName": "N-Acetylcysteine"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"location": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"text": "",
|
|
||||||
"sortDate": 1730892605000,
|
|
||||||
"isFavorite": false,
|
|
||||||
"ingestions": [
|
|
||||||
{
|
|
||||||
"stomachFullness": "EMPTY",
|
|
||||||
"dose": 250,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"substanceName": "N-Acetylcysteine",
|
|
||||||
"notes": "",
|
|
||||||
"consumerName": null,
|
|
||||||
"customUnitId": null,
|
|
||||||
"creationDate": 1730892610000,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"time": 1730892605000,
|
|
||||||
"units": "mg",
|
|
||||||
"administrationRoute": "ORAL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"substanceName": "Custom",
|
|
||||||
"stomachFullness": null,
|
|
||||||
"customUnitId": null,
|
|
||||||
"time": 1730892696000,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"units": "mg",
|
|
||||||
"notes": "",
|
|
||||||
"consumerName": null,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"administrationRoute": "SMOKED",
|
|
||||||
"creationDate": 1730892698000,
|
|
||||||
"dose": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"dose": null,
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"substanceName": "Custom",
|
|
||||||
"units": "mg",
|
|
||||||
"administrationRoute": "SMOKED",
|
|
||||||
"creationDate": 1730892704000,
|
|
||||||
"notes": "",
|
|
||||||
"consumerName": null,
|
|
||||||
"customUnitId": null,
|
|
||||||
"time": 1730892702000,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"stomachFullness": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"stomachFullness": "EMPTY",
|
|
||||||
"time": 1730892770000,
|
|
||||||
"consumerName": null,
|
|
||||||
"dose": 1,
|
|
||||||
"isDoseAnEstimate": false,
|
|
||||||
"customUnitId": 1251361475,
|
|
||||||
"substanceName": "Caffeine",
|
|
||||||
"notes": "",
|
|
||||||
"estimatedDoseStandardDeviation": null,
|
|
||||||
"administrationRoute": "ORAL",
|
|
||||||
"units": "mg",
|
|
||||||
"creationDate": 1730892771000
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"title": "Experience 2",
|
|
||||||
"creationDate": 1730892610000,
|
|
||||||
"location": null,
|
|
||||||
"ratings": [],
|
|
||||||
"timedNotes": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"customSubstances": [
|
|
||||||
{
|
|
||||||
"description": "",
|
|
||||||
"name": "Custom",
|
|
||||||
"units": "mg"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import "lib/testLib" as testLib;
|
|
||||||
import "lib/typeLib" as typeLib;
|
|
||||||
import "lib/journalLibTests" as journalLibTests;
|
|
||||||
|
|
||||||
def testsMain:
|
|
||||||
testLib::testTests |
|
|
||||||
typeLib::typeLibTests |
|
|
||||||
journalLibTests::journalLibTests |
|
|
||||||
"Tests Passed\n" | halt_error(0);
|
|
Loading…
Reference in a new issue