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;