telescope-term 1.5 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/telescope +65 -44
- metadata +7 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c74c6c6a0d418a1418cf442f5a67763a20308eee58c24bbbd98377c363ec4373
|
|
4
|
+
data.tar.gz: 59a75595a9ea9db796e7d492e184fd46c37d5114cef29947a2f16d39088be193
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1fd26d33a924c73dbb95798ea53e02fb82579bee93a12caba77e02d17bfd1151fc35b7d8ca47c2687e2374f4439a8bea64b975797dd66215975ec46f98378d8b
|
|
7
|
+
data.tar.gz: a95af60950cce3a01c047dd5597f25703c395b40977e39931adebdc4911c37d0dfb82ecd1e7ca0719e3b7d8ea7d6816818ab1becd25bbe5f09ab8be6c28ed4b9
|
data/bin/telescope
CHANGED
|
@@ -37,7 +37,7 @@ require 'json'
|
|
|
37
37
|
require 'csv'
|
|
38
38
|
|
|
39
39
|
# Version
|
|
40
|
-
VERSION = "1
|
|
40
|
+
VERSION = "2.0.1"
|
|
41
41
|
|
|
42
42
|
# Persistence paths
|
|
43
43
|
SAVE = File.join(Dir.home, '.telescope')
|
|
@@ -159,8 +159,6 @@ def create_backup
|
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
# Load saved data if present
|
|
162
|
-
SAVE = File.join(Dir.home, '.telescope') # Persistence path
|
|
163
|
-
|
|
164
162
|
if File.exist?(SAVE)
|
|
165
163
|
create_backup
|
|
166
164
|
load SAVE # expects plaintext: @ts = [...] and @ep = [...]
|
|
@@ -195,47 +193,49 @@ module Rcurses
|
|
|
195
193
|
end
|
|
196
194
|
|
|
197
195
|
# OPTICAL FORMULAS {{{1
|
|
198
|
-
def tfr(app, tfl); (tfl.to_f / app); end
|
|
199
|
-
def mlim(app); (5 * Math::log(app / 10, 10) + 7.5); end
|
|
200
|
-
def xeye(app); (app.to_f ** 2 / 49);
|
|
201
|
-
def minx(app, tfl); (tfl / (7 *
|
|
202
|
-
def mine(app, tfl); (7 * tfr(app, tfl));
|
|
203
|
-
def maxx(app); (2 * app.to_f);
|
|
204
|
-
def maxe(app, tfl);
|
|
205
|
-
def sepr(app); (3600.0 * Math::asin(671E-6 / app).rad); end
|
|
206
|
-
def sepd(app); (115.824 / app); end
|
|
207
|
-
def e_st(app, tfl); (6.4 * tfl / app); end
|
|
208
|
-
def e_gx(app, tfl); (3.6 * tfl / app); end
|
|
209
|
-
def e_pl(app, tfl); (2.1 * tfl / app); end
|
|
210
|
-
def e_2s(app, tfl); (1.3 * tfl / app); end
|
|
211
|
-
def e_t2(app, tfl); (0.7 * tfl / app); end
|
|
212
|
-
def moon(tfl); (384E6*Math::tan((115.824.deg / tfl)/360)); end
|
|
213
|
-
def sun(tfl); (moon(tfl) / 2.5668);
|
|
214
|
-
def
|
|
215
|
-
def
|
|
216
|
-
def
|
|
196
|
+
def tfr(app, tfl); return 0.0 if app.to_f == 0; (tfl.to_f / app); end
|
|
197
|
+
def mlim(app); return 0.0 if app.to_f <= 0; (5 * Math::log(app / 10, 10) + 7.5); end
|
|
198
|
+
def xeye(app); (app.to_f ** 2 / 49); end
|
|
199
|
+
def minx(app, tfl); r = tfr(app, tfl); return 0.0 if r == 0; (tfl / (7 * r)); end
|
|
200
|
+
def mine(app, tfl); (7 * tfr(app, tfl)); end
|
|
201
|
+
def maxx(app); (2 * app.to_f); end
|
|
202
|
+
def maxe(app, tfl); m = maxx(app); return 0.0 if m == 0; (tfl / m); end
|
|
203
|
+
def sepr(app); return 0.0 if app.to_f == 0; (3600.0 * Math::asin(671E-6 / app).rad); end
|
|
204
|
+
def sepd(app); return 0.0 if app.to_f == 0; (115.824 / app); end
|
|
205
|
+
def e_st(app, tfl); return 0.0 if app.to_f == 0; (6.4 * tfl / app); end
|
|
206
|
+
def e_gx(app, tfl); return 0.0 if app.to_f == 0; (3.6 * tfl / app); end
|
|
207
|
+
def e_pl(app, tfl); return 0.0 if app.to_f == 0; (2.1 * tfl / app); end
|
|
208
|
+
def e_2s(app, tfl); return 0.0 if app.to_f == 0; (1.3 * tfl / app); end
|
|
209
|
+
def e_t2(app, tfl); return 0.0 if app.to_f == 0; (0.7 * tfl / app); end
|
|
210
|
+
def moon(tfl); return 0.0 if tfl.to_f == 0; (384E6*Math::tan((115.824.deg / tfl)/360)); end
|
|
211
|
+
def sun(tfl); (moon(tfl) / 2.5668); end
|
|
212
|
+
def magx(tfl, epfl); return 0.0 if epfl.to_f == 0; (tfl.to_f / epfl); end
|
|
213
|
+
def tfov(tfl, epfl, afov); m = magx(tfl, epfl); return 0.0 if m == 0; (afov.to_f / m); end
|
|
214
|
+
def pupl(app, tfl, epfl); m = magx(tfl, epfl); return 0.0 if m == 0; (app.to_f / m); end
|
|
217
215
|
|
|
218
216
|
# VALIDATION FUNCTIONS {{{1
|
|
217
|
+
# Returns nil on success, or an error message string on failure.
|
|
219
218
|
def validate_telescope_input(input_array)
|
|
220
|
-
return
|
|
221
|
-
|
|
219
|
+
return "Need at least: name, aperture, focal length" unless input_array.size >= 3
|
|
220
|
+
|
|
222
221
|
name, app, fl = input_array[0..2]
|
|
223
|
-
return
|
|
224
|
-
return
|
|
225
|
-
return
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
return "Name cannot be empty" if name.nil? || name.strip.empty?
|
|
223
|
+
return "Aperture must be a positive number" unless app.to_s.strip =~ /\A\d+(\.\d+)?\z/ && app.to_f > 0
|
|
224
|
+
return "Focal length must be a positive number" unless fl.to_s.strip =~ /\A\d+(\.\d+)?\z/ && fl.to_f > 0
|
|
225
|
+
|
|
226
|
+
nil
|
|
228
227
|
end
|
|
229
228
|
|
|
229
|
+
# Returns nil on success, or an error message string on failure.
|
|
230
230
|
def validate_eyepiece_input(input_array)
|
|
231
|
-
return
|
|
232
|
-
|
|
231
|
+
return "Need at least: name, focal length, AFOV" unless input_array.size >= 3
|
|
232
|
+
|
|
233
233
|
name, fl, afov = input_array[0..2]
|
|
234
|
-
return
|
|
235
|
-
return
|
|
236
|
-
return
|
|
237
|
-
|
|
238
|
-
|
|
234
|
+
return "Name cannot be empty" if name.nil? || name.strip.empty?
|
|
235
|
+
return "Focal length must be a positive number" unless fl.to_s.strip =~ /\A\d+(\.\d+)?\z/ && fl.to_f > 0
|
|
236
|
+
return "AFOV must be between 0 and 180 degrees" unless afov.to_s.strip =~ /\A\d+(\.\d+)?\z/ && afov.to_f > 0 && afov.to_f <= 180
|
|
237
|
+
|
|
238
|
+
nil
|
|
239
239
|
end
|
|
240
240
|
|
|
241
241
|
def safe_file_write(file, content)
|
|
@@ -306,6 +306,7 @@ def render_ts #{{{2
|
|
|
306
306
|
end
|
|
307
307
|
|
|
308
308
|
def ep_nice(app, tfl, e) #{{{2
|
|
309
|
+
return '' if app.to_f == 0
|
|
309
310
|
r = (tfl / app)
|
|
310
311
|
out = ''
|
|
311
312
|
# Enhanced color coding with background highlights for optimal ranges - aligned with header
|
|
@@ -356,6 +357,13 @@ def ep_nice(app, tfl, e) #{{{2
|
|
|
356
357
|
end
|
|
357
358
|
|
|
358
359
|
def render_ep #{{{2
|
|
360
|
+
if @ts.empty?
|
|
361
|
+
@pEP.text = "\n Add a telescope first (press 't')"
|
|
362
|
+
@pEP.refresh
|
|
363
|
+
@pEPh.full_refresh
|
|
364
|
+
return
|
|
365
|
+
end
|
|
366
|
+
@pTS.index = [[@pTS.index, 0].max, @ts.size - 1].min
|
|
359
367
|
app = @ts[@pTS.index][1].to_f
|
|
360
368
|
tfl = @ts[@pTS.index][2].to_f
|
|
361
369
|
@pEP.text = "\n"
|
|
@@ -597,6 +605,8 @@ Signal.trap('WINCH') do
|
|
|
597
605
|
end
|
|
598
606
|
|
|
599
607
|
# MAIN LOOP {{{1
|
|
608
|
+
# Initialize rcurses (required for rcurses 6.0.0+)
|
|
609
|
+
Rcurses.init!
|
|
600
610
|
refresh_all
|
|
601
611
|
loop do
|
|
602
612
|
render_ts
|
|
@@ -621,8 +631,9 @@ loop do
|
|
|
621
631
|
refresh_all
|
|
622
632
|
when 't'
|
|
623
633
|
inp=@pTSa.ask('name, app, fl [, notes]: ','').split(', ')
|
|
624
|
-
|
|
625
|
-
|
|
634
|
+
err = validate_telescope_input(inp)
|
|
635
|
+
if err
|
|
636
|
+
@pST.say(" #{err} - Press any key")
|
|
626
637
|
getchr
|
|
627
638
|
next
|
|
628
639
|
end
|
|
@@ -633,8 +644,9 @@ loop do
|
|
|
633
644
|
@current = @ts
|
|
634
645
|
when 'e'
|
|
635
646
|
inp=@pEPa.ask('name, fl, afov [, notes]: ','').split(', ')
|
|
636
|
-
|
|
637
|
-
|
|
647
|
+
err = validate_eyepiece_input(inp)
|
|
648
|
+
if err
|
|
649
|
+
@pST.say(" #{err} - Press any key")
|
|
638
650
|
getchr
|
|
639
651
|
next
|
|
640
652
|
end
|
|
@@ -644,25 +656,29 @@ loop do
|
|
|
644
656
|
@ep_unsorted << inp # keep master list updated
|
|
645
657
|
@current = @ep
|
|
646
658
|
when 'ENTER'
|
|
659
|
+
next if @current.empty?
|
|
647
660
|
val = @current[@focus.index].join(', ')
|
|
648
661
|
arr=@pST.ask('Edit: ', val).split(', ')
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
@pST.say("
|
|
662
|
+
err = @current.equal?(@ts) ? validate_telescope_input(arr) : validate_eyepiece_input(arr)
|
|
663
|
+
if err
|
|
664
|
+
@pST.say(" #{err} - Press any key")
|
|
652
665
|
getchr
|
|
653
666
|
next
|
|
654
667
|
end
|
|
655
668
|
arr << '' if arr.size == 3 # Add empty notes if not provided
|
|
656
669
|
@current[@focus.index] = arr
|
|
657
670
|
when 'D'
|
|
671
|
+
next if @current.empty?
|
|
658
672
|
if @current.equal?(@ts)
|
|
659
673
|
removed = @ts.delete_at(@focus.index)
|
|
660
674
|
@ts_unsorted.delete(removed)
|
|
661
675
|
@tstag.delete_at(@focus.index)
|
|
676
|
+
@pTS.index = [[@pTS.index, 0].max, @ts.size - 1].min
|
|
662
677
|
else
|
|
663
678
|
removed = @ep.delete_at(@focus.index)
|
|
664
679
|
@ep_unsorted.delete(removed)
|
|
665
680
|
@eptag.delete_at(@focus.index)
|
|
681
|
+
@pEP.index = [[@pEP.index, 0].max, @ep.size - 1].min
|
|
666
682
|
end
|
|
667
683
|
when 'TAB'
|
|
668
684
|
@focus = (@focus == @pTS ? @pEP : @pTS)
|
|
@@ -673,20 +689,24 @@ loop do
|
|
|
673
689
|
@pTS.border_refresh
|
|
674
690
|
@pEP.border_refresh
|
|
675
691
|
when 'UP'
|
|
692
|
+
next if @current.empty?
|
|
676
693
|
@focus.index -= 1
|
|
677
694
|
@focus.index = @current.length - 1 if @focus.index < 0
|
|
678
695
|
when 'DOWN'
|
|
696
|
+
next if @current.empty?
|
|
679
697
|
@focus.index += 1
|
|
680
698
|
@focus.index = 0 if @focus.index > @current.length - 1
|
|
681
|
-
@focus == :ts ? @cursor_ts = 0 : @cursor_ep = 0
|
|
682
699
|
when 'HOME'
|
|
683
700
|
@focus.index = 0
|
|
684
701
|
when 'END'
|
|
702
|
+
next if @current.empty?
|
|
685
703
|
@focus.index = @current.length - 1
|
|
686
704
|
when 'S-UP'
|
|
705
|
+
next if @current.empty?
|
|
687
706
|
@current.insert([@focus.index - 1, 0].max, @current.delete_at(@focus.index))
|
|
688
707
|
@focus.index -= 1 if @focus.index != 0
|
|
689
708
|
when 'S-DOWN'
|
|
709
|
+
next if @current.empty?
|
|
690
710
|
@current.insert([@focus.index + 1, @current.size - 1].min, @current.delete_at(@focus.index))
|
|
691
711
|
@focus.index += 1 if @focus.index != @current.size - 1
|
|
692
712
|
when 'o' # Toggle-sort the currently focused list
|
|
@@ -710,6 +730,7 @@ loop do
|
|
|
710
730
|
@pEP.index = [@pEP.index, @ep.size - 1].min
|
|
711
731
|
end
|
|
712
732
|
when ' ' # SPACE: tag/untag current entry
|
|
733
|
+
next if @current.empty?
|
|
713
734
|
if @current.equal?(@ts)
|
|
714
735
|
idx = @pTS.index
|
|
715
736
|
@tstag[idx] = !@tstag[idx]
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: telescope-term
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Geir Isene
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rcurses
|
|
@@ -16,21 +16,19 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '6.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '6.0'
|
|
27
27
|
description: 'With this program you can list your telescopes and eyepieces and get
|
|
28
28
|
a set of calculations done for each scope and for the combination of scope and eyepiece.
|
|
29
|
-
Easy interface. Run the program, then hit ''?'' to show the help file. Version
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
1.5: Major feature update with notes, export, configuration, validation, backups,
|
|
33
|
-
and enhanced UI.'
|
|
29
|
+
Easy interface. Run the program, then hit ''?'' to show the help file. Version 2.0.1:
|
|
30
|
+
Improved input validation with descriptive errors, division-by-zero guards, empty
|
|
31
|
+
list safety.'
|
|
34
32
|
email: g@isene.com
|
|
35
33
|
executables:
|
|
36
34
|
- telescope
|