Mercurial > mercurial > hgweb_golang.cgi
diff src/kaigo/Nk/nk.go @ 41:34a474fb83c3
add perori/porori/nk.
author | pyon@macmini |
---|---|
date | Wed, 04 Mar 2020 23:46:59 +0900 |
parents | |
children | c58172a59534 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kaigo/Nk/nk.go Wed Mar 04 23:46:59 2020 +0900 @@ -0,0 +1,795 @@ +/* + nk.go: Nintei Kekka + + Last Change: 2020-01-24 金 09:18:04. +*/ + +package main + +/* +#cgo LDFLAGS: -L. -lxdwapi -static +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <io.h> +#include <windows.h> +#include <xdw_api.h> +#include <xdwapian.h> + +#define MAXCOL 1024 +#define MAXLINE 9999 +#define BLOCKSZ 128 + +int xdwpages(const char* file) { + char in_path[_MAX_PATH]; + _fullpath(in_path, file, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; // 文書ハンドルを開く + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { + printf("Error: cannot open %s\n", file); + return -1; + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; // 総ページ数を得る + XDW_GetDocumentInformation(h, &info); + int nPage = info.nPages; + + XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる + + return nPage; +} + +char* xdw2txt(const char* file) { + char in_path[_MAX_PATH]; + _fullpath(in_path, file, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; // 文書ハンドルを開く + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { + printf("Error: cannot open %s\n", file); + return NULL; + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; // 総ページ数を得る + XDW_GetDocumentInformation(h, &info); + int nPage = info.nPages; + + // メイン処理 + char *lpszvalue, *all_lpszvalue; + long datasize[9999]; + for (int i=1; i<=nPage; i++) { + datasize[i] = XDW_GetPageTextToMemory(h, i, NULL, 0, NULL); + datasize[0] += datasize[i]; + } + datasize[0] += nPage - 1; // for "\n" + all_lpszvalue = (char*)malloc(sizeof(char)*datasize[0]); + all_lpszvalue[0] = '\0'; + for (int i=1; i<=nPage; i++) { + if (i<nPage) datasize[i]++; // for "\n" + lpszvalue = (char*)malloc(sizeof(char)*(datasize[i])); + XDW_GetPageTextToMemory(h, i, lpszvalue, datasize[i], NULL); + strcat(all_lpszvalue, lpszvalue); + if (i<nPage) strcat(all_lpszvalue, "\n"); + free(lpszvalue); + } + + XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる + return all_lpszvalue; +} + +int xdwpush(const char* file1, const char* file2) { + char in_path[_MAX_PATH], add_path[_MAX_PATH]; + _fullpath(in_path, file1, _MAX_PATH); + _fullpath(add_path, file2, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; + + int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); + if (api_result < 0) return api_result; + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + int last_page = info.nPages; + + api_result = XDW_InsertDocument(h, last_page+1, add_path, NULL); + if (api_result < 0) api_result; + + XDW_SaveDocument(h, NULL); + XDW_CloseDocumentHandle(h, NULL); + + return (api_result >= 0); +} + +int xdwaddatn(const char* file, char* atnlist) { + char in_path[_MAX_PATH]; + _fullpath(in_path, file, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; + + int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); + if (api_result < 0) return api_result; + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + + char *str, *token; + char *saveptr1, *saveptr2; + int x, y, sz, tr; + char *s; + + for (str = atnlist; ; str = NULL) { + token = strtok_r(str, ":", &saveptr1); + if (token == NULL) break; + //printf("%s\n", token); + + // atn.X, atn.Y, atn.Sz, tr, atn.Txt + x = atoi(strtok_r(token, ",", &saveptr2)); + y = atoi(strtok_r(NULL , ",", &saveptr2)); + sz = atoi(strtok_r(NULL, ",", &saveptr2)); + tr = atoi(strtok_r(NULL, ",", &saveptr2)); + s = strtok_r(NULL, ",", &saveptr2); + //printf("x=%d y=%d txt=%s sz=%d tr=%d\n", x, y, s, sz, tr); + + for (int i = 0; i < info.nPages; i++ ) { + XDW_ANNOTATION_HANDLE annoation; + int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x, y, NULL, &annoation, NULL); + + if (api_result < 0) return api_result; + + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, s, 0, NULL); + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); + + if (tr) { + int color = XDW_COLOR_NONE; + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)&color, 0, NULL); + } + } + } + + XDW_SaveDocument(h, NULL); + XDW_CloseDocumentHandle(h, NULL); + + return 0; +} + +int xdwsort(const char* file, const char* sorted, const char* order, const char* workdir, const char* prefix) { + char buf[MAXCOL]; + + // メモリ確保 + char *sl = (char*)malloc(MAXLINE * sizeof(char) * MAXCOL); + if (sl == NULL) return -1; + + int slN = 0; + char *p; + p = strtok(order, ":"); + strncpy(&sl[slN * MAXCOL], p, MAXCOL); + slN++; + + while (p = strtok(NULL, ":")) { + strncpy(&sl[slN * MAXCOL], p, MAXCOL); + slN++; + } + + //for (int j = 0; j < slN; j++) printf("%d : %s\n", j, &sl[j * MAXCOL]); + //return 0; + + // 重み付け = 並び順 + char in_path[_MAX_PATH]; + _fullpath(in_path, file, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + + int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); + if (api_result < 0) return api_result; + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + int last_page = info.nPages; + + int *table = (int*)malloc(sizeof(int) * last_page); + for (int p = 0; p < last_page; p++) *(table + p) = 9999; + + int index = 0; + XDW_FOUND_HANDLE pFoundHandle = NULL; + for (int i = 0; i < slN; i++) { + for (int p = 0; p < last_page; p++) { + if (*(table + p) != 9999) continue; + + api_result = XDW_FindTextInPage(h, p + 1, &sl[i * MAXCOL], NULL, &pFoundHandle, NULL); + if (api_result < 0) return api_result; + + if (pFoundHandle != NULL) { + *(table + p) = ++index; + pFoundHandle = NULL; + } + } + } + free(sl); + + for (int p = 0; p < last_page; p++) { + if (*(table + p) == 9999) *(table + p) = ++index; + + sprintf(buf, "%s/%s_%04d.xdw", workdir, prefix, *(table + p)); + _fullpath(in_path, buf, _MAX_PATH); + + api_result = XDW_GetPage(h, p + 1, in_path, NULL); + if (api_result < 0) return api_result; + } + free(table); + XDW_CloseDocumentHandle(h, NULL); + + // ブロック処理 + char *blk_path = (char*)malloc(BLOCKSZ * sizeof(char) * _MAX_PATH); + const char **blk_path_addr = (const char**)malloc((last_page / BLOCKSZ + 1) * sizeof(char*) * _MAX_PATH); + + int bn = 0; + for (int p = 0, m = 0; p < last_page; p++) { + m = p % BLOCKSZ; + + if (m == 0 && p > 0) { + sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, ++bn); + _fullpath(in_path, buf, _MAX_PATH); + + api_result = XDW_MergeXdwFiles(blk_path_addr, BLOCKSZ, in_path, NULL); + if (api_result < 0) return api_result; + } + + sprintf(buf, "%s/%s_%04d.xdw", workdir, prefix, p + 1); + _fullpath(in_path, buf, _MAX_PATH); + + strncpy(&blk_path[m * _MAX_PATH], in_path, _MAX_PATH); + + blk_path_addr[m] = &blk_path[m * _MAX_PATH]; + } + + sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, ++bn); + _fullpath(in_path, buf, _MAX_PATH); + + int mod = last_page % BLOCKSZ; + if (mod == 0) mod = BLOCKSZ; + + api_result = XDW_MergeXdwFiles(blk_path_addr, mod, in_path, NULL); + if (api_result < 0) return api_result; + + for (int b = 0; b < bn; b++) { + sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, b + 1); + + _fullpath(in_path, buf, _MAX_PATH); + strncpy(&blk_path[b * _MAX_PATH], in_path, _MAX_PATH); + + blk_path_addr[b] = &blk_path[b * _MAX_PATH]; + } + + _fullpath(in_path, sorted, _MAX_PATH); + + api_result = XDW_MergeXdwFiles(blk_path_addr, bn, in_path, NULL); + if (api_result < 0) return api_result; + + free(blk_path); + free(blk_path_addr); + + return 0; +} + +int xdw2pdf(const char* xdwfile, const char* pdffile) { + char in_path[_MAX_PATH], out_path[_MAX_PATH]; + _fullpath(in_path, xdwfile, _MAX_PATH); + _fullpath(out_path, pdffile, _MAX_PATH); + + remove(out_path); + int api_result = 0; + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + + api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); + if (api_result < 0) return api_result; + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + + XDW_IMAGE_OPTION_PDF pdf = { + sizeof(XDW_IMAGE_OPTION_PDF), + XDW_COMPRESS_MRC_NORMAL, + XDW_CONVERT_MRC_OS, + info.nPages + }; + + XDW_IMAGE_OPTION_EX ex = { + sizeof(XDW_IMAGE_OPTION_EX), + 600, // dpi + XDW_IMAGE_MONO_HIGHQUALITY, + XDW_IMAGE_PDF, + &pdf + }; + + api_result = XDW_ConvertPageToImageFile(h, 1, out_path, (XDW_IMAGE_OPTION*)&ex); + + XDW_SaveDocument(h, NULL); + XDW_CloseDocumentHandle(h, NULL); + + return 0; +} + +int xdwopt(const char* in, const char* out) { + char in_path[_MAX_PATH], out_path[_MAX_PATH]; + _fullpath(in_path, in, _MAX_PATH); + _fullpath(out_path, out, _MAX_PATH); + + int api_result = XDW_OptimizeDocument(in_path, out_path, NULL); + return (api_result >= 0); +} +*/ +import "C" + +import ( + "bufio" + "encoding/json" + "fmt" + "flag" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "regexp" + "sort" + "strings" + "time" + + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +var ( + ver = "0.1" + + flg_hb int + flg_time bool + flg_log bool + flg_debug bool + flg_clean bool + + confjson = "nk.json" + logfile = "nk.log" + hhscsv = "hhsdb.csv" + tmpdir string + tmpprefix = "nktemp_" + inputdir = "input" + outputdir = "output" + outcsv = "out.csv" + + start time.Time + + hb string // 発番 + fw, hs, kt = "", "", "kttemp.xdw" // 負担割合証, 被保険者証, 結果通知 + + step, totalstep = 1, 13 +) + +type Annotation struct { + X, Y int + Sz int + Tr bool + Txt string +} + +type Config struct { + Atns []Annotation + Kyotaku []string +} + +func (c *Config) ProcessTemplate() { + today := time.Now().Format("令和 r 年 1 月 2 日") + y := time.Now().Year() - 2018 + if y == 1 { + today = strings.ReplaceAll(today, "r", "元") + } else { + today = strings.ReplaceAll(today, "r", fmt.Sprintf("%d", y)) + } + + var atns []Annotation + for _, atn := range c.Atns { + s := atn.Txt + if atn.Txt == "date" { + s = today + } + if strings.ContainsAny(atn.Txt, "hb") { + s = strings.ReplaceAll(atn.Txt, "hb", hb) + } + atns = append(atns, Annotation{atn.X, atn.Y, atn.Sz, atn.Tr, s}) + } + c.Atns = atns +} + +func (c *Config) KyotakuList() []string { + return c.Kyotaku +} + +func (c *Config) AnnotationList() (al []string) { + for _, atn := range c.Atns { + tr := 0 + if atn.Tr { + tr = 1 + } + s := fmt.Sprintf("%d,%d,%d,%d,%s", atn.X, atn.Y, atn.Sz, tr, atn.Txt) + al = append(al, s) + } + return +} + +func init() { + /* INITIALIZE FLAGS */ + flag.IntVar(&flg_hb, "b", 0, "set hatsuban") + flag.BoolVar(&flg_time, "t", false, "print time") + flag.BoolVar(&flg_log, "l", false, "save log") + flag.BoolVar(&flg_debug, "d", false, "print data for debug") + flag.BoolVar(&flg_clean, "c", false, "clean temporary directory & exit") + + /* CREAN OUTPUT-FILE & TEMP-FILE */ + if err := os.RemoveAll(outputdir); err != nil { + log.Fatal(err) + } + os.Remove(logfile) + + /* PREPARATE OUTPUT-DIR & TEMP-DIR */ + if err := os.Mkdir(outputdir, 0755); err != nil { + log.Fatal(err) + } + + var err error + tmpdir, err = ioutil.TempDir(".", tmpprefix) + if err != nil { + log.Fatal(err) + } + logfile = filepath.Join(tmpdir, logfile) + kt = filepath.Join(tmpdir, kt) +} + +func main() { + flag.Parse() + + /* CLEAN TEMPORARY DIRECTORY */ + if flg_clean { + files, err := ioutil.ReadDir(".") + if err != nil { + log.Fatal(err) + } + for _, file := range files { + if strings.HasPrefix(file.Name(), tmpprefix) { + if err := os.RemoveAll(file.Name()); err != nil { + log.Fatal(err) + } + } + } + os.Exit(0) + } + + /* PRINT HEADER */ + fmt.Println("=======================================") + fmt.Println(" 被保険者証と結果通知と負担割合証を... ") + fmt.Printf(" - nk [ver %s] -\n", ver) + fmt.Println("=======================================\n") + + /* USER INPUT */ + hb = fmt.Sprintf("%d", flg_hb) + if flg_hb == 0 { + fmt.Print("発番 > ") + fmt.Scan(&hb) + } + + start = time.Now() + + /* READ CONFIG FROM JSON */ + print_step("設定読込み") + conf, err := read_conf(confjson) + if err != nil { + log.Fatal(err) + } + conf.ProcessTemplate() + step_start := print_time(start) + + /* CHECK INPUT-FILE */ + print_step("入力ファイルのチェック") + files, err := ioutil.ReadDir(inputdir) + if err != nil { + log.Fatal(err) + } + + var kts []string + for _, file := range files { + if strings.HasSuffix(file.Name(), ".xdw") { + print_debug([]string{file.Name()}) + switch file.Name()[0:8] { + case "KBPV016G": + fw = filepath.Join(inputdir, file.Name()) + case "KBPG316G": + hs = filepath.Join(inputdir, file.Name()) + case "KBPG206G", "KBPG706G": + f := filepath.Join(inputdir, file.Name()) + kts = append(kts, f) + } + } + } + + fmt.Println() + fmt.Printf(" 負担割合証ファイル = %s\n", fw) + fmt.Printf(" 被保険者証ファイル = %s\n", hs) + fmt.Print(" 結果通知ファイル =") + for _, f := range kts { + fmt.Printf(" %s", f) + } + fmt.Println() + if fw == "" || hs == "" || len(kts) == 0 { + fmt.Fprintf(os.Stderr, "Input file is wrong.\n") + os.Exit(1) + } + + bytes, err := ioutil.ReadFile(hhscsv) + if err != nil { + log.Fatal(err) + } + hash_hhs := make(map[string]string) // 被保険者氏名のハッシュ + r := strings.NewReader(string(bytes)) + tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) + buf := bufio.NewScanner(tr) + for buf.Scan() { + records := strings.Split(buf.Text(), ",") + hash_hhs[records[0]] = records[2] + } + fmt.Printf(" 被保険者ファイル = %s\n", hhscsv) + + step_start = print_time(step_start) + + /* CONCATNATE INPUT-FILE */ + print_step("結果通知ファイルの連結") + b, err := ioutil.ReadFile(kts[0]) + if err != nil { + log.Fatal(err) + } + if err = ioutil.WriteFile(kt, b, 0644); err != nil { + log.Fatal(err) + } + if len(kts) > 1 { + pp := 0 + fmt.Println() + for _, file := range kts { + p, _ := C.xdwpages(C.CString(file)) + fmt.Printf(" %s\t= %d ページ\n", file, int(p)) + pp += int(p) + } + fmt.Printf(" 合計\t= %d ページ\n", pp) + for _, file := range kts[1:] { + C.xdwpush(C.CString(kt), C.CString(file)) + } + } + step_start = print_time(step_start) + + /* MAKE SORT-TABEL */ + print_step("並び順の決定") + + re_hhs := regexp.MustCompile(`05((2126)|(2159)|(4346))0[1238]\d{8}`) + re_kaigo := regexp.MustCompile(`要((介護)|(支援)).`) + + hash_fw := make(map[string]int) // 負担割合証発行者のハッシュ + for _, t := range xdw2txt(fw) { + hash_fw[re_hhs.FindString(t)]++ + print_debug([]string{re_hhs.FindString(t)}) + } + + kyotaku := conf.KyotakuList() + + hash_kaigo := make(map[string]string) // 被保険者証発行者の要介護度のハッシュ + hash_kyotaku := make(map[string]string) // 被保険者証発行者の居宅介護支援事業所のハッシュ + var sorttable []string + for _, t := range xdw2txt(hs) { + h := re_hhs.FindString(t) + hash_kaigo[h] = re_kaigo.FindString(t) + for _, k := range kyotaku { + if strings.Contains(t, k) { + hash_kyotaku[h] = k + } + } + key := make_sort_key(hash_fw[h], re_kaigo.FindString(t), h) + s := fmt.Sprintf("%s#%d:%s:%s#%s", key, hash_fw[h], re_kaigo.FindString(t), hash_kyotaku[h], h) + sorttable = append(sorttable, s) + } + //sort.Sort(sort.Reverse(sort.StringSlice(sorttable))) + sort.Sort(sort.StringSlice(sorttable)) + print_debug(sorttable) + step_start = print_time(step_start) + + /* DO SORT */ + order := "" + for _, s := range sorttable { + t := strings.Split(s, "#") + order += ":" + t[len(t)-1][6:] + } + order = strings.Replace(order, ":", "", 1) + + print_step("被保険者証並び替え") + hs_sorted := filepath.Join(tmpdir, "hs.xdw") + C.xdwsort(C.CString(hs), C.CString(hs_sorted), C.CString(order), C.CString(tmpdir), C.CString("hs")) + step_start = print_time(step_start) + + print_step("負担割合証並び替え") + fw_sorted := filepath.Join(tmpdir, "fw.xdw") + C.xdwsort(C.CString(fw), C.CString(fw_sorted), C.CString(order), C.CString(tmpdir), C.CString("fw")) + step_start = print_time(step_start) + + print_step("結果通知並び替え") + kt_sorted := filepath.Join(tmpdir, "kt.xdw") + C.xdwsort(C.CString(kt), C.CString(kt_sorted), C.CString(order), C.CString(tmpdir), C.CString("kt")) + step_start = print_time(step_start) + + /* ADD ANNOTATION */ + print_step("発番印字") + al := strings.Join(conf.AnnotationList(), ":") + al, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), al) + C.xdwaddatn(C.CString(kt_sorted), C.CString(al)) + step_start = print_time(step_start) + + /* OPTIMIZE OUTPUT-FILE */ + print_step("最適化") + hs_opt := filepath.Join(outputdir, "hs.xdw") + C.xdwopt(C.CString(hs_sorted), C.CString(hs_opt)) + fw_opt := filepath.Join(outputdir, "fw.xdw") + C.xdwopt(C.CString(fw_sorted), C.CString(fw_opt)) + kt_opt := filepath.Join(outputdir, "kt.xdw") + C.xdwopt(C.CString(kt_sorted), C.CString(kt_opt)) + step_start = print_time(step_start) + + /* OUTPUT CSV */ + print_step("CSV出力") + outcsv = filepath.Join(outputdir, outcsv) + fcsv, err := os.OpenFile(outcsv, os.O_RDWR|os.O_CREATE, 0644) + if err != nil { + log.Fatal(err) + } + for i, s := range sorttable { + t := strings.Split(s, "#") + u := strings.ReplaceAll(t[1], ":", ",") + u, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), u) + c := t[2][0:6] + h := t[2][6:16] + n, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), hash_hhs[h]) + // seq, city, hno, name, kaigo, fw, kyotaku + fmt.Fprintf(fcsv, "%04d,%s,%s,%s,%s\n", i + 1, c, h, n, u) + } + if err := fcsv.Close(); err != nil { + log.Fatal(err) + } + step_start = print_time(step_start) + + /* PDF */ + print_step("負担割合証割付PDF作成") + fwpdf := filepath.Join(tmpdir, "fw.pdf") + C.xdw2pdf(C.CString(fw_opt), C.CString(fwpdf)) // 2min + step_start = print_time(step_start) + + print_step("負担割合証PDF割付") + fw4pdf := filepath.Join(outputdir, "fw4.pdf") + cmd := exec.Command("fw4.exe", fwpdf, fw4pdf, tmpdir) + if err := cmd.Run(); err != nil { + log.Fatal(err) + } + step_start = print_time(step_start) + + print_step("終了") + step_start = print_time(step_start) + + /* REMOVE TEMP-FILE */ + if flg_log { + logfile2 := filepath.Join(".", strings.Replace(logfile, tmpdir, "", 1)) + os.Link(logfile, logfile2) + } + + if !flg_debug { + if err := os.RemoveAll(tmpdir); err != nil { + log.Fatal(err) + } + } +} + +func make_sort_key(fw int, kaigo, h string) string { + key := fmt.Sprintf("%d:", 9 - fw) + if strings.HasPrefix(kaigo, "要支援") { + key += "1" + } + if strings.HasPrefix(kaigo, "要介護") { + key += "2" + } + switch { + case strings.HasSuffix(kaigo, "1"): + key += "1:" + case strings.HasSuffix(kaigo, "2"): + key += "2:" + case strings.HasSuffix(kaigo, "3"): + key += "3:" + case strings.HasSuffix(kaigo, "4"): + key += "4:" + case strings.HasSuffix(kaigo, "5"): + key += "5:" + default: + key += "00:" + } + return key + h +} + +func xdw2txt(file string) (txt []string) { + s := C.GoString(C.xdw2txt(C.CString(file))) + r := strings.NewReader(s) + tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) + buf := bufio.NewScanner(tr) + for buf.Scan() { + txt = append(txt, buf.Text()) + } + return; +} + +func read_conf(file string) (conf Config, err error) { + content, err := ioutil.ReadFile(file) + if err != nil { + log.Fatal(err) + } + err = json.Unmarshal(content, &conf) + return +} + +func print_step(msg string) { + s := fmt.Sprintf("\n[%d/%d] %s\n", step, totalstep, msg) + step++ + fmt.Print(s) + save_log(s) +} + +func print_time(t time.Time) time.Time { + now := time.Now() + if !flg_time { + return now + } + elapsed := now.Sub(t) + total := now.Sub(start) + s := fmt.Sprintf("---- Elapsed: %v (total = %v) @ %02d:%02d\n", elapsed, total, now.Hour(), now.Minute()) + fmt.Print(s) + save_log(s) + return now +} + +func print_debug(msg []string) { + if !flg_debug { + return + } + s := "" + if len(msg) == 1 { + s = fmt.Sprintf("----- %s\n", msg) + } + for i, s := range msg { + s += fmt.Sprintf("%05d %s\n", i, s) + } + fmt.Print(s) + save_log(s) +} + +func save_log(logtxt string) error { + if !flg_log { + return nil + } + f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + if _, err := f.Write([]byte(logtxt)); err != nil { + f.Close() + return err + } + if err := f.Close(); err != nil { + return err + } + return nil +} +