VBFPFPJ4UR2JASCF7MVZDM3DC5XKITAFCPROT64TIN72KKQMO53AC MNDAPW6MTTHAQ2RQFXRD4ZGX64ZM45MEU2CYVSSLWENA73KXZBEAC R4Q43KYCGC5QDFR2NA2LVHPWFPPAFTWTQZXNHSAEUVOQXRKGVSQAC DBOROCRFD6A5SJBMFYFEJI5S5M77X4EFEK6KDQWA5QDMQJKIHRWQC TLLVARZXOP2M3B5VTLF4SYDGMIBPHABE6LJFG77IU53QTSYGTKWAC GQNMVJQBC6DRV5XGK3K5L7YWG2GJUXR7EQE3OHNW72XK6BFY3AHQC 2IURSWW3ZXRBH3DPJO437YE2FGMG54MPFL6W6UCEF5HODPVWVVTQC RUF5K5CL542GK5UIIIBHPIMGGCXU72IWS5OFBVTI5DRX36OSPJDAC HHT7M27I3YKGGJOTVTMRVWXATDWUZKIVVLM7IVI7SJRB7FLT2DAQC MF6A3QKQ6SU7PYAHJOO7YFCRB47DO7FHRA7OIZ7KHQJYJR77PAIQC SB4FZEB6ZLUHQNM3M76OGNNJY6THOF55S6JO6Q7IGXWE7OA7INFAC PNAXYHCI5CUWXLZPF5SCODY5X6OIMSHR45O2LJIF6ICSBANTUXZQC W3A2EECCD23SVHJZN6MXPH2PAVFHH5CNFD2XHPQRRW6M4GUTG3FAC FileIdx intSegmentIdx intDirty boolPlayer *utils.AudioPlayerPlaybackSpeed float64 // Current playback speed (1.0 = normal, 0.5 = half speed)
FileIdx intSegmentIdx intDirty boolPlayer *utils.AudioPlayerPlaybackSpeed float64 // Current playback speed (1.0 = normal, 0.5 = half speed)TimeFilteredCount int // files skipped by --night or --day filter
// Day/night filter: runs after segment filter to avoid IsNight on irrelevant files.if config.Night || config.Day {wavPath := filepath.Clean(strings.TrimSuffix(df.FilePath, ".data"))result, err := IsNight(IsNightInput{FilePath: wavPath,Lat: config.Lat,Lng: config.Lng,Timezone: config.Timezone,})if err != nil {fmt.Fprintf(os.Stderr, "warning: skipping %s (isnight error: %v)\n", wavPath, err)timeFiltered++continue}if config.Night && !result.SolarNight {timeFiltered++continue}if config.Day && result.SolarNight {timeFiltered++continue}}
fmt.Fprintf(os.Stderr, " --night Only review solar-night recordings (requires --lat and --lng)\n")fmt.Fprintf(os.Stderr, " --day Only review solar-day recordings (requires --lat and --lng)\n")fmt.Fprintf(os.Stderr, " --lat <float> Latitude in decimal degrees (required with --night or --day)\n")fmt.Fprintf(os.Stderr, " --lng <float> Longitude in decimal degrees (required with --night or --day)\n")fmt.Fprintf(os.Stderr, " --timezone <zone> IANA timezone ID (e.g. Pacific/Auckland). Required for non-AudioMoth\n")fmt.Fprintf(os.Stderr, " recorders whose filenames embed local time (e.g. DOC AR4).\n")
i += 2case "--night":night = truei++case "--day":day = truei++case "--lat":if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --lat requires a value\n")os.Exit(1)}v, err := strconv.ParseFloat(args[i+1], 64)if err != nil {fmt.Fprintf(os.Stderr, "Error: --lat must be a number\n")os.Exit(1)}lat = vlatSet = truei += 2case "--lng":if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --lng requires a value\n")os.Exit(1)}v, err := strconv.ParseFloat(args[i+1], 64)if err != nil {fmt.Fprintf(os.Stderr, "Error: --lng must be a number\n")os.Exit(1)}lng = vlngSet = truei += 2case "--timezone":if i+1 >= len(args) {fmt.Fprintf(os.Stderr, "Error: --timezone requires a value\n")os.Exit(1)}timezone = args[i+1]
if night && day {fmt.Fprintf(os.Stderr, "Error: --night and --day are mutually exclusive\n\n")printClassifyUsage()os.Exit(1)}if (night || day) && (!latSet || !lngSet) {fmt.Fprintf(os.Stderr, "Error: --night/--day requires both --lat and --lng\n\n")printClassifyUsage()os.Exit(1)}
Adds `--night`, `--day`, `--lat`, `--lng`, and `--timezone` flags to `skraak calls classify`.Filtering happens at load time (before the TUI launches) inside `LoadDataFiles`, after theexisting segment filter — so `IsNight` is only called for files that have matching segments.Skipped file count is reported to stderr before the TUI starts.Same `--timezone` caveat as `calls clip`: required for non-AudioMoth recorders (e.g. DOC AR4)that embed local time in filenames. AudioMoth files don't need it.```bashskraak calls classify --folder F09/2026-04-06/ --species "Don't Know" \--night --lat -45.50603 --lng 167.47371```**Files changed:**- `tools/calls_classify.go` — `ClassifyConfig` (Night/Day/Lat/Lng/Timezone fields),`ClassifyState` (TimeFilteredCount), `LoadDataFiles` (day/night filter block).- `cmd/calls_classify.go` — flag parsing, mutual-exclusivity + lat/lng validation,config construction, skipped-count summary line, updated usage text.