245 lines
5.6 KiB
Go
245 lines
5.6 KiB
Go
/*
|
|
history.go - 历史记录管理
|
|
定义了历史记录的数据结构和相关功能
|
|
*/
|
|
|
|
package calculator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// HistoryRecord 表示一条计算历史记录
|
|
type HistoryRecord struct {
|
|
Expression string `json:"expression"` // 表达式
|
|
Result float64 `json:"result"` // 计算结果
|
|
Timestamp time.Time `json:"timestamp"` // 计算时间
|
|
}
|
|
|
|
// NewHistoryRecord 创建新的历史记录
|
|
func NewHistoryRecord(expression string, result float64) HistoryRecord {
|
|
return HistoryRecord{
|
|
Expression: expression,
|
|
Result: result,
|
|
Timestamp: time.Now(),
|
|
}
|
|
}
|
|
|
|
// String 返回历史记录的字符串表示
|
|
func (h HistoryRecord) String() string {
|
|
return fmt.Sprintf("%s = %g (计算时间: %s)",
|
|
h.Expression,
|
|
h.Result,
|
|
h.Timestamp.Format("2006-01-02 15:04:05"))
|
|
}
|
|
|
|
// HistoryManager 历史记录管理器
|
|
type HistoryManager struct {
|
|
records []HistoryRecord
|
|
filePath string
|
|
maxSize int
|
|
}
|
|
|
|
// NewHistoryManager 创建新的历史记录管理器
|
|
func NewHistoryManager(filePath string, maxSize int) *HistoryManager {
|
|
return &HistoryManager{
|
|
records: make([]HistoryRecord, 0),
|
|
filePath: filePath,
|
|
maxSize: maxSize,
|
|
}
|
|
}
|
|
|
|
// Add 添加历史记录
|
|
func (hm *HistoryManager) Add(expression string, result float64) {
|
|
record := NewHistoryRecord(expression, result)
|
|
hm.records = append(hm.records, record)
|
|
|
|
// 限制历史记录数量
|
|
if len(hm.records) > hm.maxSize {
|
|
hm.records = hm.records[len(hm.records)-hm.maxSize:]
|
|
}
|
|
}
|
|
|
|
// GetAll 获取所有历史记录
|
|
func (hm *HistoryManager) GetAll() []HistoryRecord {
|
|
// 返回副本以防止外部修改
|
|
records := make([]HistoryRecord, len(hm.records))
|
|
copy(records, hm.records)
|
|
return records
|
|
}
|
|
|
|
// GetLast 获取最近的 n 条记录
|
|
func (hm *HistoryManager) GetLast(n int) []HistoryRecord {
|
|
if n <= 0 {
|
|
return []HistoryRecord{}
|
|
}
|
|
|
|
if n >= len(hm.records) {
|
|
return hm.GetAll()
|
|
}
|
|
|
|
start := len(hm.records) - n
|
|
records := make([]HistoryRecord, n)
|
|
copy(records, hm.records[start:])
|
|
return records
|
|
}
|
|
|
|
// Clear 清空历史记录
|
|
func (hm *HistoryManager) Clear() {
|
|
hm.records = make([]HistoryRecord, 0)
|
|
}
|
|
|
|
// Count 获取历史记录数量
|
|
func (hm *HistoryManager) Count() int {
|
|
return len(hm.records)
|
|
}
|
|
|
|
// SaveToFile 保存历史记录到文件
|
|
func (hm *HistoryManager) SaveToFile() error {
|
|
if hm.filePath == "" {
|
|
return fmt.Errorf("文件路径未设置")
|
|
}
|
|
|
|
data, err := json.MarshalIndent(hm.records, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("序列化历史记录失败: %v", err)
|
|
}
|
|
|
|
err = ioutil.WriteFile(hm.filePath, data, 0644)
|
|
if err != nil {
|
|
return fmt.Errorf("写入文件失败: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadFromFile 从文件加载历史记录
|
|
func (hm *HistoryManager) LoadFromFile() error {
|
|
if hm.filePath == "" {
|
|
return fmt.Errorf("文件路径未设置")
|
|
}
|
|
|
|
// 检查文件是否存在
|
|
if _, err := os.Stat(hm.filePath); os.IsNotExist(err) {
|
|
// 文件不存在,创建空的历史记录
|
|
hm.records = make([]HistoryRecord, 0)
|
|
return nil
|
|
}
|
|
|
|
data, err := ioutil.ReadFile(hm.filePath)
|
|
if err != nil {
|
|
return fmt.Errorf("读取文件失败: %v", err)
|
|
}
|
|
|
|
err = json.Unmarshal(data, &hm.records)
|
|
if err != nil {
|
|
return fmt.Errorf("反序列化历史记录失败: %v", err)
|
|
}
|
|
|
|
// 限制历史记录数量
|
|
if len(hm.records) > hm.maxSize {
|
|
hm.records = hm.records[len(hm.records)-hm.maxSize:]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Search 搜索包含指定关键词的历史记录
|
|
func (hm *HistoryManager) Search(keyword string) []HistoryRecord {
|
|
var results []HistoryRecord
|
|
|
|
for _, record := range hm.records {
|
|
if contains(record.Expression, keyword) {
|
|
results = append(results, record)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// GetStatistics 获取历史记录统计信息
|
|
func (hm *HistoryManager) GetStatistics() map[string]interface{} {
|
|
stats := make(map[string]interface{})
|
|
|
|
stats["total_count"] = len(hm.records)
|
|
|
|
if len(hm.records) == 0 {
|
|
return stats
|
|
}
|
|
|
|
// 统计运算符使用频率
|
|
operatorCount := make(map[string]int)
|
|
for _, record := range hm.records {
|
|
for _, char := range record.Expression {
|
|
switch char {
|
|
case '+':
|
|
operatorCount["addition"]++
|
|
case '-':
|
|
operatorCount["subtraction"]++
|
|
case '*':
|
|
operatorCount["multiplication"]++
|
|
case '/':
|
|
operatorCount["division"]++
|
|
}
|
|
}
|
|
}
|
|
stats["operator_usage"] = operatorCount
|
|
|
|
// 最早和最晚的计算时间
|
|
if len(hm.records) > 0 {
|
|
earliest := hm.records[0].Timestamp
|
|
latest := hm.records[0].Timestamp
|
|
|
|
for _, record := range hm.records {
|
|
if record.Timestamp.Before(earliest) {
|
|
earliest = record.Timestamp
|
|
}
|
|
if record.Timestamp.After(latest) {
|
|
latest = record.Timestamp
|
|
}
|
|
}
|
|
|
|
stats["earliest_calculation"] = earliest.Format("2006-01-02 15:04:05")
|
|
stats["latest_calculation"] = latest.Format("2006-01-02 15:04:05")
|
|
}
|
|
|
|
return stats
|
|
}
|
|
|
|
// ExportToCSV 导出历史记录为 CSV 格式
|
|
func (hm *HistoryManager) ExportToCSV(filePath string) error {
|
|
var csvContent strings.Builder
|
|
|
|
// CSV 头部
|
|
csvContent.WriteString("Expression,Result,Timestamp\n")
|
|
|
|
// 数据行
|
|
for _, record := range hm.records {
|
|
csvContent.WriteString(fmt.Sprintf("\"%s\",%g,\"%s\"\n",
|
|
record.Expression,
|
|
record.Result,
|
|
record.Timestamp.Format("2006-01-02 15:04:05")))
|
|
}
|
|
|
|
err := ioutil.WriteFile(filePath, []byte(csvContent.String()), 0644)
|
|
if err != nil {
|
|
return fmt.Errorf("导出 CSV 文件失败: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// contains 检查字符串是否包含子字符串(忽略大小写)
|
|
func contains(s, substr string) bool {
|
|
return len(s) >= len(substr) &&
|
|
(substr == "" ||
|
|
len(s) > 0 &&
|
|
(s == substr ||
|
|
strings.Contains(strings.ToLower(s), strings.ToLower(substr))))
|
|
}
|