Files
astro/basic/star_catalog_names.go
T
b612 72460fa228 feat: 完善星表查询与跨版本回归验证
- 将星表名称数据收敛为 TSV/GZIP 单一数据源,补充中文名、别名、英文常用名及宿/垣区域字段
- 增加星表名称表加载校验、旧详情字段一致性校验和 GZIP 漂移检查
- 新增 StarDataByName、StarDataByNameAll、StarDataByNameIn ,统一中英文查询与重名消歧
- 优化日月食半影带、升落曲线和可见性回归测试,补充极区、拓扑及低精度场景覆盖
- 增加 Go 1.16/386 兼容门禁和测试案例,处理旧工具链的分配、拓扑、SVG字节及 ULP 差异
- 补充星表、坐标、日月食和低精度回归用例,完善测试文件与缓存忽略规则
2026-10-18 16:13:14 +08:00

109 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package basic
import (
"bytes"
"compress/gzip"
_ "embed"
"errors"
"fmt"
"io/ioutil"
"strconv"
"strings"
)
// star_catalog_names.tsv.gz 由同名 .tsv 压缩生成,测试校验两者一致。
//
//go:embed star_catalog_names.tsv.gz
var starCatalogNamesCompressed []byte
// starCatalogNameHeader 单一星名表的列顺序,生成端与加载端必须一致。
var starCatalogNameHeader = []string{"hr", "chinese", "aliases", "bayer_zh", "common", "cst", "cst_zh", "region"}
type starNameRecord struct {
chinese string
aliases []string
bayerZH string
common string
cst string
cstZH string
region string
}
func decodeStarNameTable(compressed []byte, starCount int) (map[uint16]starNameRecord, error) {
reader, err := gzip.NewReader(bytes.NewReader(compressed))
if err != nil {
return nil, fmt.Errorf("open star name table: %w", err)
}
defer reader.Close()
text, err := ioutil.ReadAll(reader)
if err != nil {
return nil, fmt.Errorf("read star name table: %w", err)
}
lines := strings.Split(string(text), "\n")
if len(lines) == 0 || strings.TrimSpace(lines[0]) == "" {
return nil, errors.New("empty star name table")
}
header := strings.Split(strings.TrimSuffix(lines[0], "\r"), "\t")
if len(header) != len(starCatalogNameHeader) {
return nil, fmt.Errorf("star name header has %d columns, want %d", len(header), len(starCatalogNameHeader))
}
for i, want := range starCatalogNameHeader {
if header[i] != want {
return nil, fmt.Errorf("star name header column %d = %q, want %q", i+1, header[i], want)
}
}
names := make(map[uint16]starNameRecord)
for index, line := range lines[1:] {
line = strings.TrimSuffix(line, "\r")
if line == "" {
continue
}
fields := strings.Split(line, "\t")
if len(fields) != len(starCatalogNameHeader) {
return nil, fmt.Errorf("star name line %d has %d columns, want %d", index+2, len(fields), len(starCatalogNameHeader))
}
hr, err := strconv.ParseUint(fields[0], 10, 16)
if err != nil || hr == 0 || int(hr) > starCount {
return nil, fmt.Errorf("star name line %d has invalid HR %q", index+2, fields[0])
}
key := uint16(hr)
if _, ok := names[key]; ok {
return nil, fmt.Errorf("star name line %d repeats HR %d", index+2, key)
}
chinese := fields[1]
region := fields[7]
rec := starNameRecord{
chinese: chinese,
aliases: splitStarAliases(fields[2]),
bayerZH: fields[3],
common: fields[4],
cst: fields[5],
cstZH: fields[6],
region: region,
}
if chinese == "" && len(rec.aliases) == 0 && rec.bayerZH == "" && rec.common == "" &&
rec.cst == "" && rec.cstZH == "" && rec.region == "" {
continue
}
names[key] = rec
}
if len(names) == 0 {
return nil, errors.New("empty star name table")
}
return names, nil
}
func splitStarAliases(value string) []string {
if strings.TrimSpace(value) == "" {
return nil
}
parts := strings.FieldsFunc(value, func(r rune) bool { return r == ';' || r == ';' })
out := make([]string, 0, len(parts))
for _, part := range parts {
if part = strings.TrimSpace(part); part != "" {
out = append(out, part)
}
}
return out
}