Mercurial > mercurial > hgweb_golang.cgi
view src/kaigo/Perori/perori.go @ 46:6ec28d3c3e00
small changes.
author | pyon@macmini |
---|---|
date | Sat, 18 Apr 2020 21:10:29 +0900 |
parents | b50f2a581cf8 |
children |
line wrap: on
line source
package main import ( "flag" "compress/gzip" "encoding/csv" "fmt" "html/template" "io/ioutil" "log" "os" "strings" "sort" "time" "golang.org/x/text/encoding/japanese" "golang.org/x/text/transform" ) var debug_log bool // Constants const version = "0.3b" const default_dbfile = "ikenshoirai.db" const default_csvfile = "ikenshoirai.csv" const tpl = ` <!DOCTYPE html> <html> <head> <style type="text/css"> body { font-size: 9pt; margin-left: 0px;} h2 { font-size: 11pt; margin-bottom: 1px; background-color: #ccccff; padding-left: 5px; } h3 { font-size: 11pt; margin-bottom: 1px; background-color: #f0a8a8; padding-left: 10px; } table, th, td { border: 0.3px #c0c0c0 solid; border-collapse:collapse; } table { margin-bottom: 5px; margin-left: 15px; } th { background-color: #ccffcc; } hr { page-break-before: always; } </style> <title> - </title> </head> <body> <h2> List <small>( Date = {{.Ymd}} / N = {{.NHhs}} / Dr = {{.NDr}} )</small> </h2> {{range .Doctors}} <h3>{{.Name}}<small> ..... {{.Hp}}:{{.Senmon}}</small></h3> {{range .Clients}} <table> <tr> <td width=140 style="background-color: #98f0f0; padding-left: 10px;">{{.Name}}</td> <td width=120 align=center>{{.Kubun}} {{.Ymd}}</td> <td width=480 style="padding-left: 10px;"> {{if .Prev.Ymd}} {{if eq .DrId .Prev.DrId}} {{str2cp932 "★ 継続 -"}} {{.Prev.Ymd}} {{else}} {{.Prev.Dr}} {{.Prev.Ymd}} {{end}} {{else}} New ! {{end}} </td> <td width=80 align=center>{{.Hhsno}}</td> </tr> <tr> <td colspan=4 style="font-family: serif; font-size: 8pt; padding-left: 30px;">{{.Biko}}</td> </tr> </table> {{end}} {{end}} <hr /> {{$hpno := 0}} <h2> N by Hp </h2> <table> <tr> <th> no </th> <th> hp </th> <th width=60> n </th> </tr> {{range $hp, $n := .Hp}} <tr> {{$hpno = add1 $hpno}} <td align=right style="padding-right: 5px;"> {{$hpno}} </td> <td style="padding-left: 5px;"> {{$hp}} </td> <td align=right style="padding-right: 5px;"> {{$n}} </td> </tr> {{end}} <tr> <td></td> <td align=right> sum > > ></td> <td align=right style="padding-right: 5px;"> <b> {{.HpSum}} </b> </td> </tr> </table> </body> </html>` // Define Types type PrevSinsei struct { Biko string DrId string Dr string IraiYmd string Ymd string Kubun string } type Sinsei struct { Hhsno string Name string Biko string DrId string Dr string DrKana string Hp string IraiYmd string Ymd string Kubun string Senmon string Prev PrevSinsei } func (s *Sinsei) SetPrev(prev PrevSinsei) { s.Prev = prev } func (s Sinsei) String() string { return strings.Join([]string{s.Hhsno, s.Name, s.Ymd, s.Kubun, s.Dr, s.Hp, s.Senmon, s.IraiYmd, s.Biko}, ",") } func (s *Sinsei) Humanize() { var buf string switch s.Kubun { case "01": buf = "新規" case "02": buf = "更新" case "10": buf = "支介" case "05": buf = "区変" case "03": buf = "転入" case "09": buf = "証交" } s.Kubun, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), buf) s.Ymd = strings.Join([]string{s.Ymd[2:4], s.Ymd[4:6], s.Ymd[6:8]}, ".") } type Doctor struct { Id string Name string Kana string Hp string Senmon string Clients []Sinsei } func (d *Doctor) AddClient(sinsei Sinsei) { d.Clients = append(d.Clients, sinsei) } func (d Doctor) String() string { return d.Name } // Main func main() { var csvfile, dbfile, date string today := time.Now().Format("20060102") flag.StringVar(&csvfile, "c", default_csvfile, "csv file") flag.StringVar(&dbfile, "b", default_dbfile, "db file") flag.StringVar(&date, "r", today, "Ikensho Irai YMD") flag.BoolVar(&debug_log, "d", false, "print debug-log (stderr)") flag.Parse() csvdata, hhshash, err := getdata_fromCSV(csvfile, date) if err != nil { log.Fatal(err) } print_debug_log(fmt.Sprintf("csvdata: n=%d", len(csvdata))) // print_debug_log(fmt.Sprintf("hhshash: n=%d", len(hhshash))) // dbdata, err := getdata_fromDB(dbfile, hhshash) if err != nil { log.Fatal(err) } print_debug_log(fmt.Sprintf("dbdata: n=%d", len(dbdata))) // dbdata = append(dbdata, csvdata...) print_debug_log(fmt.Sprintf("dbdata: n=%d", len(dbdata))) // sort.Slice(dbdata, func(i, j int) bool { if dbdata[i].Hhsno != dbdata[j].Hhsno { return dbdata[i].Hhsno < dbdata[j].Hhsno } if dbdata[i].Ymd != dbdata[j].Ymd { return dbdata[i].Ymd > dbdata[j].Ymd } if dbdata[i].IraiYmd != dbdata[j].IraiYmd { return dbdata[i].IraiYmd > dbdata[j].IraiYmd } return false }) var dbdata2 []Sinsei // delete same Ymd (for changing Dr.) var lasthhsno, lastymd string for _, ss := range dbdata { if ss.Hhsno == lasthhsno && lastymd == ss.Ymd { continue } dbdata2 = append(dbdata2, ss) lasthhsno = ss.Hhsno lastymd = ss.Ymd } var lastdata []Sinsei prevhash := make(map[string]PrevSinsei) hhscnt := make(map[string]int) for _, ss := range dbdata2 { ss.Humanize() switch hhscnt[ss.Hhsno] { case 0: lastdata = append(lastdata, ss) case 1: prevhash[ss.Hhsno] = PrevSinsei{ Biko: ss.Biko, DrId: ss.DrId, Dr: ss.Dr + "(" + ss.Hp + ":" + ss.Senmon + ")", IraiYmd: ss.IraiYmd, Ymd: ss.Ymd, Kubun: ss.Kubun, } } hhscnt[ss.Hhsno]++; } print_debug_log(fmt.Sprintf("lastdata: n=%d", len(lastdata))) // doctorhash := make(map[string]Doctor) hpcnt := make(map[string]int) var hpcntsum int for _, ss := range lastdata { ss.SetPrev(prevhash[ss.Hhsno]) if d, ok := doctorhash[ss.DrId]; !ok { doctorhash[ss.DrId] = Doctor{ Id: ss.DrId, Name: ss.Dr, Kana: ss.DrKana, Hp: ss.Hp, Senmon: ss.Senmon, Clients: []Sinsei{ss}, } } else { d.AddClient(ss) doctorhash[ss.DrId] = d } hpcnt[ss.Hp]++ hpcntsum++ } var doctors []Doctor for _, dr := range doctorhash { doctors = append(doctors, dr) } sort.Slice(doctors, func(i, j int) bool { if doctors[i].Kana != doctors[j].Kana { return doctors[i].Kana < doctors[j].Kana } if doctors[i].Id != doctors[j].Id { return doctors[i].Id < doctors[j].Id } return false }) irai := struct { Ymd string NHhs int //NSinsei int NDr int Doctors []Doctor Hp map[string]int HpSum int }{ Ymd: strings.Join([]string{date[0:4], date[4:6], date[6:8]}, "."), NHhs: len(hhshash), //NSinsei: len(dbdata), NDr: len(doctors), Doctors: doctors, Hp: hpcnt, HpSum: hpcntsum, } funcmap := template.FuncMap{ "shorten": shorten, "str2cp932": str2cp932, "add1": func(a int) int { return a + 1 }, } t, err := template.New("webpage").Funcs(funcmap).Parse(tpl) if err != nil { log.Fatal(err) } err = t.Execute(os.Stdout, irai) if err != nil { log.Fatal(err) } } // Utility functions func csv2sinsei(record []string) Sinsei { return Sinsei{ Hhsno: strings.TrimSpace(record[0]), Name: strings.TrimSpace(record[1]), Biko: strings.TrimSpace(record[2]), DrId: strings.TrimSpace(record[3]), Dr: strings.TrimSpace(record[4]), DrKana: strings.TrimSpace(record[5]), Hp: strings.TrimSpace(record[6]), IraiYmd: strings.TrimSpace(record[7]), Ymd: strings.TrimSpace(record[8]), Kubun: strings.TrimSpace(record[9]), Senmon: strings.TrimSpace(record[10]), } } func getdata_fromCSV(file, date string) (sinsei []Sinsei, hhshash map[string]bool, err error) { hhshash = make(map[string]bool) data, err := ioutil.ReadFile(file) if err != nil { return sinsei, hhshash, err } r := csv.NewReader(strings.NewReader(string(data))) records, err := r.ReadAll() if err != nil { return sinsei, hhshash, err } for _, record := range records { ss := csv2sinsei(record) if ss.IraiYmd == date { hhshash[ss.Hhsno] = true } } for _, record := range records { ss := csv2sinsei(record) if _, ok := hhshash[ss.Hhsno]; ok { sinsei = append(sinsei, ss) } } return sinsei, hhshash, nil } func getdata_fromDB(file string, hhshash map[string]bool) (sinsei []Sinsei, err error) { f, err := os.Open(file) if err != nil { return sinsei, err } defer f.Close() zr, err := gzip.NewReader(f) if err != nil { return sinsei, err } data, err := ioutil.ReadAll(zr) if err != nil { return sinsei, err } if err := zr.Close(); err != nil { return sinsei, err } r := csv.NewReader(strings.NewReader(string(data))) records, err := r.ReadAll() if err != nil { return sinsei, err } for _, record := range records { hno := strings.TrimSpace(record[0]) if _, ok := hhshash[hno]; ok { sinsei = append(sinsei, csv2sinsei(record)) } } return sinsei, nil } func shorten(msg string, length int) string { if len(msg) > length { msg = msg[0:length] + "..." } return msg } func str2cp932(s string) string { s, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), s) return s } func print_debug_log(msg string) { if debug_log { fmt.Fprintf(os.Stderr, "%s\n", msg) } }