go语言计算推算心率算法 http服务

news2024/11/29 2:38:22

目的

为了计算心率和并且将心率计算作为http服务来运行

几种计算方法

1 基本数据
a) hrv heart rate variability
b) 呼吸
2 傅里叶变换 计算频率 高频和低频
3 隐形马尔科夫 模型 hmm 重在于推测概率
根据最近的心率计算
4 神经网络计算

基本计算

hrv 5 min RR 间期 平均值标准差 sdann
24h 正常的RR间期总体标准差 sdnn
24h 每5分钟时段 标准差的平均值 sdnn index
两个相邻RR间期 差值的均方根RMSSD
24h 相邻两个正常RR 间期差值 大于50ms 的个数百分比pnn50
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

定义数据结构

type Data struct {
	Heart int
	Time  int64
	//Name  string
}

type Cmd struct {
	// 1 立刻返回,求数据结果立即返回,不用存储
	// 2 单人所有数据24 小时内所有数据
	// 3 其他
	Type int
	//设备号码,唯一标识
	Device string
	Data   []Data
}
type Repay struct {
	Code   int     `json:"code"`
	Device string  `json:"device"`
	Ret    string  `json:"ret"`
	Sdnn   int     `json:"sdnn"`
	Rmssd  int     `json:"rmssd"`
	Pnn50  float32 `json:"pnn50"`
}

声明http 服务

使用http 服务进行数据返回,使用gin 来制作一个server


// 创建一个错误处理函数,避免过多的 if err != nil{} 出现
func dropErr(e error) {
	if e != nil {
		panic(e)
	}
}

/*
 计算一个段落,比如5分钟,或者10分钟,等
*/
func calculate_parag(cmd *Cmd, f int, t int) *Repay {
	size := t - f + 1
	var in []float32 = make([]float32, size)
	var n int = 0
	for i := f; i <= t; i++ {
		in[n] = (float32)(cmd.Data[i].Heart)
		n++
	}

	vsdnn := sdnn.Get_Stddev(in)
	vrmssd := sdnn.Get_Rmssd(in)
	vpnn50 := sdnn.Get_Pnn50(in)

	Repays := &Repay{
		Code:   0,
		Device: cmd.Device,
		Ret:    "正常",
		Sdnn:   int(vsdnn),
		Rmssd:  int(vrmssd),
		Pnn50:  vpnn50,
	}
	return Repays
}

func calculate1(cmd *Cmd, c chan Repay, db *sql.DB) {
	//in1 := []float32{71, 72, 69, 70, 65, 74}
	size := len(cmd.Data)
	fmt.Println("device is ", cmd.Device, " len is ", size)

	if size == 0 {
		return
	}
	var in []float32 = make([]float32, size)

	for i, v := range cmd.Data {
		in[i] = (float32)(v.Heart)
	}

	//ret 为mean均值

	if cmd.Type == 1 {
		fmt.Println("type is 1")
		vsdnn := sdnn.Get_Stddev(in)
		//fmt.Fprintf(w, "%f", vsdnn)
		result := &Repay{
			Code:   0,
			Device: cmd.Device,
			Ret:    "正常",
			Sdnn:   int(vsdnn),
			Rmssd:  0,
			Pnn50:  0.0,
		}
		if vsdnn < 100 {

			if vsdnn < 50 {
				result.Ret = "良好"
			}
		} else {
			result.Ret = "疲劳"
		}
		c <- *result
		//fmt.Println("prepare send")
		//fmt.Fprintf(w, "%f", vsdnn)
		//io.WriteString(w, "hello, world!\n")
		// msg, err := json.Marshal(Repays)
		// if err != nil {
		// 	fmt.Println(err)
		// } else {
		// 	w.Header().Set("content-type", "text/json")
		// 	w.Write(msg)
		// 	fmt.Println(string(msg))
		// }

	} else if cmd.Type == 2 {
		//每5分钟或者10分钟求取一个值,存储,报表所用
		fmt.Println("start to calc")
		var nt int = 0
		var nf int = 0
		tf := cmd.Data[0].Time
		var result *Repay
		for {
			nt++
			if nt == size {
				c <- *result
				break
			}
			if cmd.Data[nt].Time-tf >= 300 { // 大于5分钟 5*60
				result = calculate_parag(cmd, nf, nt)
				fmt.Println(result)
				//记录到数据库
				//计算字符串时间
				time := time.Unix(cmd.Data[nf].Time, 0)
				timestr := calc_time_str(time)
				db_insert(cmd.Device, result.Sdnn, 0, result.Rmssd, result.Pnn50, timestr)
				nf = nt
				tf = cmd.Data[nf].Time

			}

		}

	} else if cmd.Type == 3 {
		fmt.Println("type is 3")
		vsdnn := sdnn.Get_Stddev(in)
		vrmssd := sdnn.Get_Rmssd(in)
		vpnn50 := sdnn.Get_Pnn50(in)
		//记录到数据库
		result := &Repay{
			Code:   0,
			Device: cmd.Device,
			Ret:    "",
			Sdnn:   int(vsdnn),
			Rmssd:  int(vrmssd),
			Pnn50:  vpnn50,
		}
		c <- *result
		//s := fmt.Sprintf(`{"sdnn":%f,"rmssd":%f,"pnn50":%f}`, vsdnn, vrmssd, vpnn50)

		//msg, _ := json.Marshal(Repays)
		//fmt.Println(string(msg))
		//w.Header().Set("content-type", "application/json;charset=UTF-8")
		//w.Write(msg)
	}

	//
}
func init() {
	//s := fmt.Sprintf(`{"sdnn":%f,"rmssd":%f,"pnn50":%f}`, 1.0, 2.0, 3.0)
	//fmt.Println(s)
}

func gin_server() {
	r := gin.Default()

	r.GET("/api/device/:name", func(c *gin.Context) {
		dname := c.Param("name")
		c.JSON(200, gin.H{
			"message": dname,
		})
	})

	r.POST("/book", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "POST",
		})
	})
	r.Run(":9000")
}

func main() {
	defer dbclose()
	config := config_init()

	storage_init()
	go gin_server()
	http.HandleFunc("/hrv", func(w http.ResponseWriter, r *http.Request) {

		fmt.Println(html.EscapeString(r.URL.Path))

		if r.Method == "POST" {
			b, err := ioutil.ReadAll(r.Body)
			if err != nil {
				log.Println("Read failed:", err)
			}
			//defer r.Body.Close()

			cmd := &Cmd{}
			err = json.Unmarshal(b, cmd)
			if err != nil {
				log.Println("json format error:", err)
			} else {
				//c := make(chan interface{}, 1)
				c := make(chan Repay, 1)
				go calculate1(cmd, c, db)

				select {
				//case <-ctx.Done():
				//	log.Printf("Context interrupt or timeout: %v\n", ctx.Err())

				case result := <-c:
					msg, _ := json.Marshal(result)
					fmt.Println(string(msg))
					w.Header().Set("content-type", "application/json;charset=UTF-8")
					w.Write(msg)
				}
				// log.Println("cmd:", string(b))
				// log.Println("cmd:", cmd.Data[0])
				//io.WriteString(w, "hello, world!\n")
				//w.ResponseWriter("1")
				//time.Sleep(1 * time.Second)
				//fmt.Fprintf(w, "%f", 100.0)
			}

		} else {

			log.Println("not support")

			w.WriteHeader(405)
			return
		}

	})

	serveraddress := ":" + config.Port
	fmt.Println("server lister at ", serveraddress)
	log.Fatal(http.ListenAndServe(serveraddress, nil))

}

以上的服务比较简单,不做过多解释,以下贴出使用sqlite的代码sqlite.go,go语言使用sqlite是要用mingw来编译sqlite的,这个注意以下,我就直接贴代码了

package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"unsafe"
	_ "github.com/mattn/go-sqlite3"
)

var db *sql.DB
var err error
var sql_table = `CREATE TABLE if not exists "data_1" (
    "id" INTEGER PRIMARY KEY AUTOINCREMENT,
    "deviceid" VARCHAR(64) NULL,
    "sdnn" INTEGER,
	"average" INTEGER,
    "rmssd" INTEGER,
	"pnn50" float,
    "timestart" TIMESTAMP default (datetime('now', 'localtime'))
);
CREATE INDEX deviceid_idx ON file_hash_list (deviceid);
`

type Data0 struct {
	id        int
	Deviceid  string
	Sdnn      int
	Average   int
	Rmssd     int
	Pnn50     float32
	Timestart string
}

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

func db_insert(did string, ssdn int, average int, rmssd int, pnn50 float32, timestart string) int64 {
	stmt, err := db.Prepare("INSERT INTO data_1(deviceid, sdnn,average,rmssd,pnn50,timestart) values(?,?,?,?,?,?)")
	checkErr(err)

	res, err := stmt.Exec(did, ssdn, average, rmssd, pnn50, timestart)
	checkErr(err)

	id, err := res.LastInsertId()
	checkErr(err)

	return id

}
func db_update_average( /*db *sql.DB,*/ deviceid string, average int) int64 {

	stmt, err := db.Prepare("update data_1 set deviceid=? where deviceid=?")
	checkErr(err)

	res, err := stmt.Exec(average, deviceid)
	checkErr(err)

	affect, err := res.RowsAffected()
	checkErr(err)
	return affect
}

func db_select_all( /*db *sql.DB,*/ data0 *Data0) {
	rows, err := db.Query("SELECT * FROM data_1")

	checkErr(err)

	for rows.Next() {
		err = rows.Scan(&data0.id, &data0.Deviceid, &data0.Sdnn, &data0.Average,
			&data0.Rmssd, &data0.Pnn50, &data0.Timestart)
		checkErr(err)
	}
}
func getJSON(sqlString string) (string, error) {
	stmt, err := db.Prepare(sqlString)
	if err != nil {
		return "", err
	}
	defer stmt.Close()
	rows, err := stmt.Query()
	if err != nil {
		return "", err
	}
	defer rows.Close()
	columns, err := rows.Columns()
	if err != nil {
		return "", err
	}
	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtrs[i] = &values[i]
		}
		rows.Scan(valuePtrs...)
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	jsonData, err := json.Marshal(tableData)
	if err != nil {
		return "", err
	}
	s1 := (*string)(unsafe.Pointer(&jsonData))
	return *s1, nil
	//return string(jsonData), nil
}

//size:每页显示条数,index页码
func db_select_by(tablename string, deviceid string, size int, index int) {
	//select * from GuestInfo order by GuestId limit {0} offset {0}*{1}", size, index-1);
	s := fmt.Sprintf("select * from %s where deviceid='%s' order by id desc limit %d offset %d",
		tablename, deviceid, size, size*(index-1))
	fmt.Println("sql is:", s)
	ret, err := getJSON(s)
	if err != nil {

	} else {
		//http 返回数据
		fmt.Println(ret)
	}
}

func db_delete_data(id int) int64 {
	stmt, err := db.Prepare("delete from data_1 where id=?")
	checkErr(err)

	res, err1 := stmt.Exec(id)
	checkErr(err1)

	affect, err2 := res.RowsAffected()
	checkErr(err2)

	return affect

}

func init() {
	fmt.Println("sqlite open")
	db, err = sql.Open("sqlite3", "./data.db")
	checkErr(err)
	db.Exec(sql_table) //执行数据表
	//defer db.Close()
}

func dbclose() {
	db.Close()
}

//just for unit test
func sqlite_test() {

	// db, err = sql.Open("sqlite3", "./data.db")
	// defer db.Close()
	// checkErr(err)
	// db.Exec(sql_table) //执行数据表
	// id := db_insert("qianbo", 15, 70, 20, 0.2, "2021-01-09 07:05:22")
	// fmt.Println("insert:", id)
	// id = db_insert("guanzhi", 16, 71, 25, 0.3, "2021-12-09 07:05:22")
	// fmt.Println("insert:", id)
	// affected := db_update_average("qianbo", 67)
	// fmt.Println("update:", affected)

	// var data0 Data0
	// db_select_all(&data0)
	// fmt.Println(id, data0.Deviceid)
	//'select * from data_1 where deviceid='qianbo' order by id desc limit 5 offset 0

	db_select_by("data_1", "qianbo", 5, 1)
	db_select_by("data_1", "qianbo", 5, 2)
}

配置文件

配置文件主要是用来配置端口和配置提交数据地址
config.yaml

port: 8080
postaddress: "http://127.0.0.1/qianbo"


package main

import (
	"fmt"

	"github.com/spf13/viper"
)

type Config struct {
	Port        string
	PostAddress string
}

func config_init() *Config {
	//监听事件

	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("Fatal error config file: %s \n", err))
	}

	config := &Config{}

	config.Port = viper.GetString("port")
	config.PostAddress = viper.GetString("postaddress")
	fmt.Println(config.Port, config.PostAddress)
	viper.WatchConfig()
	return config
	// gin.SetMode(gin.ReleaseMode)
	// //r := gin.Default()
	// if err := r.Run(fmt.Sprintf(":%d", viper.Get("port"))); err != nil {
	// 	panic(err)
	// }
}

算法

最后给出几个算法的计算方法,确实比较简单,直接看代码就行了

package sdnn

import (
	"fmt"
	"math"
)

func Print(arr []int) {
	for i, v := range arr {
		fmt.Printf("arr[%d]=%d\n", i, v)
	}
}
func Get_Average(arr []float32) float32 {
	var x float32 = 0.
	for _, v := range arr {
		//fmt.Printf("arr[%d]=%f\n", i, v)
		a := (60 * 1000) / v
		x += a
	}
	var ret float32 = 0.
	ret = x / (float32)(len(arr))
	return ret
}

//五分钟就是sdann
//24销售是sdnn
func Get_Stddev(arr []float32) float64 {
	var mean float32 = Get_Average(arr)
	var x float32 = 0.0
	for _, v := range arr {
		a := 60000 / v
		x += (a - mean) * (a - mean)
	}
	var size float64 = (float64)(len(arr))
	var ret float64 = math.Sqrt((float64)(x) / size)
	return ret
}
func Get_Rmssd(arr []float32) float64 {
	var x float32 = 0.0
	for i := 1; i < len(arr); i++ {
		a := 60000 / arr[i-1]
		b := 60000 / arr[i]
		x += (b - a) * (b - a)
	}
	var size float64 = (float64)(len(arr) - 1)
	var ret float64 = math.Sqrt((float64)(x) / size)
	return ret
}

//24h 相邻两个正常RR 间期差值 大于50ms 的个数百分比pnn50
//迷走神经
func Get_Pnn50(arr []float32) float32 {
	var pnn int = 0
	for i := 1; i < len(arr); i++ {
		a := 60000 / arr[i-1]
		b := 60000 / arr[i]
		if a > b {
			if (a - b) > 50 {
				pnn++
			}
		} else {
			if (b - a) > 50 {
				pnn++
			}
		}

	}
	var size float32 = (float32)(len(arr) - 1)
	return (float32)((float32)(pnn) / size)
}

post 测试数据

为了编写测试程序而写,当然最好使用python来做,不过go也可以了

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

type Data struct {
	Heart int
	Time  int
	Name  string
}
type Cmd struct {
	Type int
	Data []Data
}

var g_str = `{"Type":2,"Device":"qianbo","Data":[{"Heart":78,"Time":678},
{"Heart":75,"Time":700},
{"Heart":69,"Time":800},
{"Heart":72,"Time":900},
{"Heart":73,"Time":1000},
{"Heart":70,"Time":1100},
{"Heart":73,"Time":1200},
{"Heart":73,"Time":1300},
{"Heart":67,"Time":1400},
{"Heart":68,"Time":1500},
{"Heart":70,"Time":1600},
{"Heart":70,"Time":1700},
{"Heart":71,"Time":1750},
{"Heart":68,"Time":1850},
{"Heart":67,"Time":1900},
{"Heart":65,"Time":1950},
{"Heart":73,"Time":2000},
{"Heart":70,"Time":2050},
{"Heart":69,"Time":2100}
]}`

var g_url = "http://127.0.0.1:8080/hrv"
var g_jsonStr = []byte(g_str)

func GetPostResponse(url, bodyType string, body *[]byte) (rdata []byte, err error) {
	b := bytes.NewBuffer(*body)
	var r *http.Response
	r, err = http.Post(url, bodyType, b)

	if err == nil {
		rbody := (*r).Body
		defer rbody.Close()

		var nRead int
		nRead, err = rbody.Read(rdata)
		if err != nil {
			fmt.Printf("GetPostResponse from (%s), read data error.", url)
			fmt.Println(err.Error())
		}
		if nRead <= 0 {
			err = fmt.Errorf("GetPostResponse from (%s), read data error (%d)", url, nRead)
			fmt.Println(err.Error())
		}
	} else {
		fmt.Printf("GetPostResponse from (%s), get error.", url)
		fmt.Println(err.Error())
	}

	return rdata, err
}

func SamplePost() {
	reader := bytes.NewReader(g_jsonStr)

	request, err := http.NewRequest("POST", g_url, reader)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	client := http.Client{}
	resp, err := client.Do(request)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	//byte数组直接转成string,优化内存
	fmt.Println(string(respBytes))
	// str := (*string)(unsafe.Pointer(&respBytes))
	// fmt.Println(*str)
}

func main() {
	SamplePost()
}

func main2() {
	rdata, err := GetPostResponse(g_url, "application/json", &g_jsonStr)
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(len(rdata))
		fmt.Println(string(rdata))
	}
}

func main_() {
	//var arr [2]Data
	//json.Unmarshal([]byte(str), &s)

	// data := make(map[string]interface{})
	// data["Name"] = "qianbo"
	// data["Heart"] = 67
	// data["Time"] = 778

	// D := make(map[string]interface{})
	// D["Type"] = 1
	// D["Data"] = data
	// bytesData, err := json.Marshal(D)

	// if err != nil {
	// 	fmt.Println(err.Error())
	// 	return
	// }
	// reader := bytes.NewReader(bytesData)
	//request, err := http.NewRequest("POST", url, reader)

	client := http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				conn, err := net.DialTimeout(netw, addr, time.Second*5) //设置建立连接超时
				if err != nil {
					return nil, err
				}
				conn.SetDeadline(time.Now().Add(time.Second * 5)) //设置发送接受数据超时
				return conn, nil
			},
			ResponseHeaderTimeout: time.Second * 5,
		},
	}

	request, err := http.NewRequest("POST", g_url, bytes.NewBuffer(g_jsonStr))
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	request.Header.Set("Content-Type", "application/json;charset=UTF-8")
	request.Header.Set("Connection", "Keep-Alive")
	//request.Header.Set("Cookie", "name=anny")

	fmt.Println("send")
	resp, err := client.Do(request)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer resp.Body.Close()
	fmt.Println("recv")
	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {
		fmt.Println(err.Error())
		return
	}
	//byte数组直接转成string
	//strret := (*string)(unsafe.Pointer(&resp.Body))
	fmt.Println(len(body))
	fmt.Println(string(body))

}

缓存数据如何存储

下面是为了缓存数据而编写的入到redis里面而写,不一定要用

package main

import (
	"context"
	"fmt"
	"log"

	//"github.com/go-redis/redis"
	"github.com/go-redis/redis/v8"
)

var rdb *redis.Client
var ctx = context.Background()

// // 初始化连接
func storage_init() (err error) {

	rdb = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password set
		DB:       0,  // use default DB
	})

	_, err = rdb.Ping(ctx).Result()
	if err != nil {
		fmt.Println("error connect redis")
		return err
	}
	return nil
}
func get(key string) string {
	val, err := rdb.Get(ctx, key).Result()
	if err == redis.Nil {
		fmt.Println("key of ", key, "does not exists")
		return ""
	} else if err != nil {
		return ""
		//panic(err)
	} else {
		fmt.Println(key, val)
		return val
	}
}
func set(key string, value float32) {

	err := rdb.Set(ctx, key, value, 0).Err()
	if err != nil {
		panic(err)
	}
}
func hset(hashTable, key, val string) {
	isSetSuccessful, err := rdb.HSet(ctx, hashTable, key, val).Result()

	if err != nil {
		log.Fatal(err)
	}
	//如果键存在这返回false,如果键不存在则返回true
	fmt.Println(isSetSuccessful)
}

//redis命令:hget hashTable key
func hget(hashTable, key string) {
	val, err := rdb.HGet(ctx, hashTable, key).Result()

	if err != nil {
		log.Fatal(err)
	} else {
		fmt.Println(val)
	}
	// for k, v := range val {
	// 	fmt.Printf("k = %v v = %s\n", k, v)
	// }
}
func hgetall(hashTable string) {
	val, err := rdb.HGetAll(ctx, hashTable).Result()

	if err != nil {
		log.Fatal(err)
	} else {
		fmt.Println(val)
	}
	// for k, v := range val {
	// 	fmt.Printf("k = %v v = %s\n", k, v)
	// }
}

func main__() {
	storage_init()
	set("qianbo", 1000)
	get("qianbo")
	hset("device001", "1001", "{abc:100,d:23}")
	hset("device001", "1002", "{abc:101,d:123}")
	hset("device001", "1003", "{abc:102,d:223}")
	hget("device001", "1001")
	hget("device001", "1002")
	hget("device001", "1003")
	hgetall("device001")
}

时间测试

其中为了测试时间差也写了一些测试,一并贴出

package main

import (
	"fmt"
	"time"
)

func calc_seconds(t1 string, t2 string) int {

	f1, err := time.Parse("2006-01-02 15:04:05", t1)
	if err != nil {
		return -1
	}

	f2, err2 := time.Parse("2006-01-02 15:04:05", t2)
	if err2 != nil {
		return -1
	}
	d := (int)(f2.Sub(f1).Seconds())
	if d < 0 {
		x := 0 - d
		return x
	}
	return d
}
func calc_timenow() string {

	timeStr := time.Now().Format("2006-01-02 15:04:05")
	//fmt.Println(timeStr)
	return timeStr
}
func calc_time_str(t time.Time) string {
	return t.Format("2006-01-02 15:04:05")
}
func test_time() {
	timestamp := time.Now().Unix()
	fmt.Println(timestamp)
	x := time.Unix(timestamp, 0)
	fmt.Println(x)
	//获取时间戳
	fmt.Println(calc_timenow())
	f1 := "2021-04-11 13:34:37"
	f2 := "2021-04-11 13:34:30"
	fmt.Println(calc_seconds(f1, f2))

}

最后贴出go.mod 文件

module hrv

go 1.15

require (
	github.com/garyburd/redigo v1.6.3
	github.com/gin-gonic/gin v1.7.7
	github.com/go-redis/redis v6.15.9+incompatible
	github.com/go-redis/redis/v8 v8.11.4
	github.com/mattn/go-sqlite3 v1.14.10
	github.com/spf13/viper v1.10.1
)

以上是为了计算心率数据而做的非产品代码,读者可做参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/763630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

APP外包开发原生和H5的对比

在开发APP的技术中&#xff0c;除了原生开发外也可以使用H5框架来开发。原生开发的特点是质量高&#xff0c;用户体验更好&#xff0c;但成本高&#xff0c;适用于对质量要求高的APP项目。H5框架的特点是通用性较强&#xff0c;对开发人员的要求相对较低&#xff0c;成本也低&a…

23款奔驰GLE350轿跑加装前排原厂座椅通风系统,夏天必备的功能

通风座椅的主动通风功能可以迅速将座椅表面温度降至适宜程度&#xff0c;从而确保最佳座椅舒适性。该功能启用后&#xff0c;车内空气透过打孔皮饰座套被吸入座椅内部&#xff0c;持续时间为 8 分钟。然后&#xff0c;风扇会自动改变旋转方向&#xff0c;将更凉爽的环境空气从座…

怎么批量查询快递单号的物流状态并导出查询数据

随着互联网技术的不断发展&#xff0c;电商行业想做大做强&#xff0c;售后环节一定要做到位。想要做好售后服务&#xff0c;需要借助一些技巧与手段。今天小编给大家安利一款软件&#xff1a;“固乔快递查询助手”&#xff0c;这是一款可以批量查询快递信息的软件&#xff0c;…

python_PyQt5开发股票日数据更新工具

写在前面&#xff1a; 该工具更新的股票日数据来自优矿&#xff0c;为了把股票日数据在本地存储一份&#xff0c;这就面临需要定期更新的需求&#xff0c;为此开发了这个工具。 定期更新的股票日数据特征&#xff1a; 1 旧股票日数据&#xff08;也就是上次更新的数据&#…

【机器学习】吴恩达课程2-单变量线性回归

一、单变量线性回归 1. 模型描述 监督学习的流程 & 单变量线性回归函数 代价函数&#xff1a;&#xff0c;其中 m 表示训练样本的数量 公式为预测值与实际值的差&#xff0c;平方为最小二乘法和最佳平方/函数逼近。 目标&#xff1a;最小化代价函数&#xff0c;即 2. 只…

PR模板-33组故障干扰文字标题动画 Motion Glitch Typography

Motion Glitch Typography包含33组故障干扰文字标题动画pr模板。不需要任何插件或脚本&#xff0c;只需点击几下&#xff0c;您的视频就有很酷的故障标题动画&#xff0c;适用于预告片、宣传片或任何类型的视频。 适用软件&#xff1a;Premiere Pro 2020 或更高版本 分辨率&a…

Go语言之函数补充defer语句,递归函数,章节练习

defer语句是go语言提供的一种用于注册延迟调用的机制&#xff0c;是go语言中一种很有用的特性。 defer语句注册了一个函数调用&#xff0c;这个调用会延迟到defer语句所在的函数执行完毕后执行&#xff0c;所谓执行完毕是指该函数执行了return语句、函数体已执行完最后一条语句…

密码学学习笔记(十四):SHA-3 Sponge Construction - 海绵结构

SHA-3算法满足了哈希函数的三个安全属性&#xff0c;并且和SHA-2的变体达到同样级别的安全性。此外&#xff0c;SHA-3算法不容易受到长度扩展攻击&#xff0c;并可用于计算秘密消息的哈希值。 SHA-3是一种建立在Permutation(置换)之上的密码算法。 置换就是假设有两个数组a和…

Hadoop第一课之环境配置

1.配置一个模板机 要求&#xff1a;IP DNS地址页 网址 防火墙 安装包 1.ip ifconfig 查询 先用虚拟机看一下自己的网关 vim search/provides 命令 查找 # 修改网络配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33 如果提示找不到vim命令&#xff0c;使用yum下载v…

Springboot Excel 最简单的 多sheet表 导入导出

前言 上周学习群里有人问到&#xff0c;多个sheet的导出导入&#xff0c;我第一反应就是easypoi不是自己就有方法了么&#xff1f; 后面一想&#xff0c;可能有些看客还处于是 找工具类&#xff0c;然后调试 的写代码 的 阶段&#xff0c;可能还不会去看jar包的一些函数。 既然…

SpringMVC入门篇5 --- 拦截器

目录 1. 简介 拦截器&#xff08;Interceptor&#xff09;是一种动态拦截方法调用的机制。 作用&#xff1a; 在指定的方法调用前后执行预先设定后的代码。阻止原始方法的执行。 拦截器与过滤器的区别 归属不同&#xff1a;Filter属于Servlet技术&#xff0c;Interceptor…

使用vue3 + Ts + Vite + ElementPlus实现一个抽奖程序

一. 说明 这是一个通过vue3 Ts Vite ElementPlus实现的一个抽奖程序。项目链接 二. 整体架构与功能描述 左侧设置了奖品说明&#xff0c;每个奖项配有文字和图片简介。总共设置了四个奖项&#xff0c;分别是特等奖1名&#xff0c;一等奖2名&#xff0c;二等奖5名&#xf…

平安养老险党委书记、董事长甘为民:聚焦养老主业 助推养老保障事业高质量发展

每经记者 涂颖浩 每经编辑 马子卿 随着人口老龄化趋势加剧&#xff0c;中国养老金融市场呈现出巨大的潜力&#xff0c;逐步迈入养老新时代。近日&#xff0c;平安养老险党委书记、董事长甘为民在接受《每日经济新闻》记者专访时表示&#xff0c;过往单纯的养老发展模式难以满足…

Jmeter性能测试 —— 性能测试的概念

性能测试的概念 性能测试是指通过特定方式&#xff0c;对被测系统按照一定策略施加压力&#xff0c;获取系统 响应时间、TPS&#xff08;Transaction Per Second&#xff09;、吞吐量、资源利用率等性能指标&#xff0c;以期保证生产系统的性能能够满足用户需求的过程。 性能…

浅析编译与链接

生成可执行文件的四个过程 当编写和构建计算机程序时&#xff0c;预处理、编译、汇编和链接是将源代码转化为可执行程序的关键过程。以下是对每个阶段的详细解释&#xff1a; 1. 预处理&#xff08;Preprocessing&#xff09;&#xff1a;将.c/.cpp文件中的头文件展开、宏展开…

【PostgreSQL内核学习(一)—— Ubuntu源码安装PostgreSQL】

Ubuntu源码安装PostgreSQL 1. PostgreSQL官网下载压缩包2. 解压&安装2.1 解压文件2.2 安装依赖2.3 执行安装2.4 执行安装2.5 添加路径到文件 3. 初始化数据库与使用3.1 初始化数据库3.2 启动数据库服务3.3 启动数据库 1. PostgreSQL官网下载压缩包 下载地址&#xff1a;ht…

【黑马头条之freemarker入门】

本笔记内容为黑马头条项目的freemarker部分 目录 一、freemarker 介绍 二、环境搭建&&快速入门 1、创建测试工程 2、配置文件 3、创建模型类 4、创建模板 5、创建controller 6、创建启动类 7、测试 三、freemarker基础 1、基础语法种类 2、集合指令&#…

【iOS】—— 面向对象,Runtime,ARC等问题总结

对于暑假学习大多数是对之前学习的一个复习&#xff0c;在这里只做对之前学习欠缺知识的补充以及这些知识点涉及的一些问题&#xff0c;从问题入手学习。 文章目录 面向对象1.一个NSObject对象占多少内存&#xff1f;2.对象的isa指针指向哪里&#xff1f;3.OC的类信息存放在哪…

PLSQL编程

1.概念和目的 1.1. 什么是PL/SQL? PL/SQL&#xff08;Procedure Language/SQL&#xff09; 是Oracle对sql语言的过程化扩展 (类似于Basic)&#xff1b; 指在SQL命令语言中增加了过程处理语句&#xff08;如分支、循环等&#xff09;&#xff0c;使SQL语言具有过程处理能力。…

Spring @Autowired 注解原理

Spring Autowired 注解原理 1.Autowired 使用 ComponentScan("org.example.bean") public class AnnoContextDemo {Autowiredprivate User user;public static void main(String[] args) {AnnotationConfigApplicationContext context new AnnotationConfigApplic…