2024-11-07 08:58:38 +00:00
|
|
|
# run as: jq export.json -f tool.jq -Cr --args --
|
|
|
|
|
|
|
|
include "utils";
|
2024-11-07 09:11:29 +00:00
|
|
|
include "argsLib";
|
2024-11-07 08:58:38 +00:00
|
|
|
include "journalUtils";
|
|
|
|
|
|
|
|
def printExperienceStats($stats; $substanceFilter; $consumerFilter; $withTitle):
|
|
|
|
. as $experience |
|
|
|
|
|
|
|
|
($consumerFilter // ["default"]) as $consumerFilter |
|
|
|
|
|
|
|
|
$experience.ingestions | filterIngestions($substanceFilter; $consumerFilter) as $ingestions |
|
|
|
|
($ingestions | ingestionsByConsumer) as $ingestionsByConsumer |
|
|
|
|
|
|
|
|
($ingestionsByConsumer | keys) as $consumerNames |
|
|
|
|
|
|
|
|
"" as $experienceStatsText |
|
|
|
|
$experienceStatsText |
|
|
|
|
if $withTitle then
|
|
|
|
. += ($experience | formatExperienceTitle | . + "\n")
|
|
|
|
end | . as $experienceStatsText |
|
|
|
|
|
|
|
|
reduce $consumerNames[] as $consumerName ($experienceStatsText;
|
|
|
|
. as $experienceStatsText |
|
|
|
|
$experienceStatsText |
|
|
|
|
if ($consumerNames != ["default"])
|
|
|
|
then . += "Consumer: \($consumerName)\n"
|
|
|
|
end | . as $experienceStatsText |
|
|
|
|
|
|
|
|
($stats.[$consumerName] | keys) as $substanceNames |
|
|
|
|
|
|
|
|
|
|
|
|
$experienceStatsText | reduce $substanceNames[] as $substanceName (.;
|
|
|
|
. as $experienceStatsText |
|
|
|
|
|
|
|
|
($stats.[$consumerName].[$substanceName] | keys) as $ingestionMethods |
|
|
|
|
|
|
|
|
($experienceStatsText | . += "Substance: \($substanceName)\n") as $experienceStatsText |
|
|
|
|
|
|
|
|
reduce ($stats.[$consumerName].[$substanceName] | to_entries)[] as $substanceStats ($experienceStatsText;
|
|
|
|
. as $experienceStatsText |
|
|
|
|
|
|
|
|
$substanceStats |
|
|
|
|
.key as $ingestionMethod |
|
|
|
|
ifNullDefault(.value.dose; "Unknown") as $dose |
|
|
|
|
.value.unit as $unit |
|
|
|
|
|
|
|
|
($experienceStatsText | . += "Dose (\($ingestionMethod | titleCase)): \($dose) \($unit)\n") as $experienceStatsText |
|
|
|
|
$experienceStatsText
|
|
|
|
) | . as $experienceStatsText |
|
|
|
|
|
|
|
|
$experienceStatsText | if ($ingestionMethods | length > 1) then
|
|
|
|
($stats | calculateCombinedDose($substanceName; $consumerName)) as $combinedDose |
|
|
|
|
. += "Combined Dose: \(ifNullDefault($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 | sort_by(.sortDate) | filterIngestions($substanceFilter; $consumerFilter) as $ingestions |
|
|
|
|
|
|
|
|
$ingestions | ingestionsConsumerNames as $consumerNames |
|
|
|
|
|
|
|
|
if ($consumerNames == ["default"])
|
|
|
|
then
|
|
|
|
["Substance", "Dose", "ROA", "Consumer", "Time"]
|
|
|
|
else
|
|
|
|
["Substance", "Dose", "ROA", "Time"]
|
|
|
|
end | . as $columnTitles |
|
|
|
|
|
|
|
|
(reduce $ingestions[] as $ingestion ([]; . as $rows |
|
|
|
|
$ingestion |
|
|
|
|
.substanceName as $substanceName |
|
|
|
|
ifNullDefault(.consumerName; "default") as $consumerName |
|
|
|
|
formatIngestionDose($customUnits) as $doseText |
|
|
|
|
formatIngestionROA($customUnits) as $roaText |
|
|
|
|
formatIngestionTime as $timeText |
|
|
|
|
$rows | . += [
|
|
|
|
if ($consumerNames != ["default"])
|
|
|
|
then [$substanceName, $doseText, $roaText, $consumerName, $timeText]
|
|
|
|
else [$substanceName, $doseText, $roaText, $timeText] end
|
|
|
|
]
|
|
|
|
)) as $rows |
|
|
|
|
|
|
|
|
if $pretty then
|
|
|
|
printPrettyTable(
|
|
|
|
if $withTitle then ($experience | formatExperienceTitle) else null end;
|
|
|
|
$columnTitles;
|
|
|
|
$rows
|
|
|
|
)
|
|
|
|
else
|
|
|
|
$rows | map(join(" | ")) | rtrimstr(" ") as $rows |
|
|
|
|
(if $withTitle then [$experience | formatExperienceTitle] else [] end) + $rows | join("\n")
|
|
|
|
end | . as $ingestionLog |
|
|
|
|
|
|
|
|
$ingestionLog;
|
|
|
|
|
|
|
|
def printExperiencesAdvanced($customUnits; $substanceFilter; $consumerFilter; $sortMethod; $sortOptions; $sortFilterString; sortFilter):
|
|
|
|
. as $experiences |
|
|
|
|
($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 sortFilterExperiences:
|
|
|
|
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 |
|
|
|
|
(reduce $experiencesData[] as $experienceData ([];
|
|
|
|
($experienceData.experience.ingestions) as $ingestions |
|
|
|
|
. +=
|
|
|
|
if ($experienceData.experience.ingestions |
|
|
|
|
any(
|
|
|
|
.substanceName as $substanceName |
|
|
|
|
$substanceFilter |
|
|
|
|
any(index($substanceName))
|
|
|
|
)
|
|
|
|
) then [$experienceData] else [] end
|
|
|
|
));
|
|
|
|
|
|
|
|
def filterByConsumerFilter:
|
|
|
|
. as $experiencesData |
|
|
|
|
(reduce $experiencesData[] as $experienceData ([];
|
|
|
|
($experienceData.experience.ingestions) as $ingestions |
|
|
|
|
. +=
|
|
|
|
if ($experienceData.experience.ingestions |
|
|
|
|
any(
|
|
|
|
ifNullDefault(.consumerName; "default") 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
|
|
|
|
ifNullDefault(.consumerName; "default") == $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
|
|
|
|
assert($sortOptions.substanceName != null; "substanceName not provided as sortOption") |
|
|
|
|
filterBySubstanceAndConsumer |
|
|
|
|
sort_by(highestCombinedDoseSort, oldToNewSort) |
|
|
|
|
reverse
|
|
|
|
elif
|
|
|
|
$sortMethod == "highest-dose-for-method"
|
|
|
|
then
|
|
|
|
assert($sortOptions.substanceName != null; "substanceName not provided as sortOption") |
|
|
|
|
filterByIngestionMethodForSubstance |
|
|
|
|
sort_by(highestMethodDoseSort, oldToNewSort) |
|
|
|
|
reverse
|
|
|
|
end;
|
|
|
|
|
|
|
|
def sortFilterFromString($filterString):
|
|
|
|
(reduce ($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
|
|
|
|
));
|
|
|
|
|
|
|
|
def experiencesWithExtraData($customUnits):
|
|
|
|
. as $experiences |
|
|
|
|
(reduce $experiences[] as $experience ([];
|
|
|
|
. += [{
|
|
|
|
stats: $experience | experienceStats($customUnits),
|
|
|
|
$experience
|
|
|
|
}]
|
|
|
|
));
|
|
|
|
|
|
|
|
$experiences |
|
|
|
|
experiencesWithExtraData($customUnits) |
|
|
|
|
sortFilterExperiences |
|
|
|
|
if ($sortFilterString != null) then . | sortFilterFromString($sortFilterString) end |
|
|
|
|
if (sortFilter != null) then . | sortFilter end |
|
|
|
|
.[] 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($ARGS):
|
|
|
|
def usage:
|
|
|
|
[
|
|
|
|
"psychonaut_journal_stats {printExperience,printExperiencesAdvanced}",
|
|
|
|
""
|
|
|
|
] | join("\n") | halt_error(1);
|
|
|
|
|
|
|
|
. as $exportData |
|
|
|
|
|
|
|
|
($ARGS | parseArgs) as $parsedArgs |
|
|
|
|
|
|
|
|
$parsedArgs.nonArgs[0] as $program |
|
|
|
|
($parsedArgs | .nonArgs |= $parsedArgs.nonArgs[1:]) as $parsedArgs |
|
|
|
|
|
|
|
|
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] --pretty=bool --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,
|
|
|
|
pretty: true,
|
|
|
|
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 == "pretty" then
|
|
|
|
.pretty |= (ifNullDefault($value; $defaultOptions.pretty) | parseArgBool)
|
|
|
|
end |
|
|
|
|
if $arg == "title" then
|
|
|
|
.withTitle |= (ifNullDefault($value; $defaultOptions.withTitle) | parseArgBool)
|
|
|
|
end |
|
|
|
|
if $arg == "stats" then
|
|
|
|
.withStats |= (ifNullDefault($value; $defaultOptions.withStats) | 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 | 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 | experienceStats($exportData.customUnits)) as $stats |
|
|
|
|
$ingestionLog +
|
|
|
|
"\n\nCumulative Doses:\n" +
|
|
|
|
($experience | printExperienceStats(
|
|
|
|
$stats;
|
|
|
|
$options.substanceFilter;
|
|
|
|
$options.consumerFilter;
|
|
|
|
false
|
|
|
|
))
|
|
|
|
else
|
|
|
|
$ingestionLog
|
|
|
|
end
|
|
|
|
elif $program == "printExperiencesAdvanced" then
|
|
|
|
def printExperiencesAdvancedUsage($reason):
|
|
|
|
[
|
|
|
|
$reason,
|
|
|
|
"Usage: printExperiencesAdvanced --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 printExperiencesAdvancedUsage(null) end |
|
|
|
|
if ($parsedArgs.longArgs | has("help")) then printExperiencesAdvancedUsage(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 |
|
|
|
|
printExperiencesAdvanced(
|
|
|
|
$exportData.customUnits;
|
|
|
|
$options.substanceFilter;
|
|
|
|
$options.consumerFilter;
|
|
|
|
$options.sortMethod;
|
|
|
|
$options.sortOptions;
|
|
|
|
$options.sortFilter; null
|
|
|
|
)
|
|
|
|
else
|
|
|
|
usage
|
|
|
|
end;
|
|
|
|
|
|
|
|
main($ARGS)
|