Mercurial > mercurial > hgweb_golang.cgi
diff src/kaigo/qtuti/95y/95.go @ 65:0369656be06c default tip
many changes.
author | pyon@macmini |
---|---|
date | Fri, 20 May 2022 06:30:34 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kaigo/qtuti/95y/95.go Fri May 20 06:30:34 2022 +0900 @@ -0,0 +1,653 @@ +/* + 95.go: Qfuhi Tsuchi + + Last Change: 2020-09-11 金 10:42:16. +*/ + +package main + +/* +#cgo LDFLAGS: -L. -lxdwapi -static +// +// 95.cpp: Qfuhi Tsuchi +// Last Change: 2020-09-08 火 15:20:43. +// + +#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 +#define ATN_N 20 + +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)) { + fprintf(stderr, "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; +} + +void xdw2txtb(const char* xdwfile, const char* txtfile) { + char in_path[_MAX_PATH], out_path[_MAX_PATH]; + _fullpath(in_path, xdwfile, _MAX_PATH); + _fullpath(out_path, txtfile, _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)) { + fprintf(stderr, "Error: cannot open %s\n", xdwfile); + return; + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; // 総ページ数を得る + XDW_GetDocumentInformation(h, &info); + int nPage = info.nPages; + + FILE *fp; + if ((fp = fopen(out_path, "w")) == NULL) { + fprintf(stderr, "Error: cannot open %s\n", out_path); + return; + } + + long datasize; + char* lpszvalue; + + for (int i = 1; i <= nPage; i++) { + datasize = XDW_GetPageTextToMemory(h, i, NULL, 0, NULL); + lpszvalue = (char*)malloc(sizeof(char)*datasize); + XDW_GetPageTextToMemory(h, i, lpszvalue, datasize, NULL); + fprintf(fp, "%s\n", lpszvalue); + free(lpszvalue); + } + + fclose(fp); + XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる + return; +} + +int xdwsplit1(const char* file, const char* workdir, const char* prefix) { + char file_path[_MAX_PATH]; + _fullpath(file_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(file_path, &h, (XDW_OPEN_MODE*)&mode)) { + fprintf(stderr, "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; + + char buf[_MAX_PATH]; + for (int i = 1; i <= nPage; i++) { + sprintf(buf, "%s/%s%05d.xdw", workdir, prefix, i); + //sprintf(buf, "%s_%05d.xdw", prefix, i); + _fullpath(file_path, buf, _MAX_PATH); + + int api_result = XDW_GetPage(h, i, file_path, NULL); + if (api_result < 0) { + fprintf(stderr, "XDW Error: cannot get page (%s p=%d)\n", file, i); + return -1; + } + } + + XDW_CloseDocumentHandle(h, NULL); + return 0; +} + +int xdwextpage(const char* infile, const int p, const char* outfile) { + char file_path[_MAX_PATH]; + _fullpath(file_path, infile, _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(file_path, &h, (XDW_OPEN_MODE*)&mode)) { + fprintf(stderr, "Error: cannot open %s\n", infile); + return -1; + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + int nPage = info.nPages; + + char buf[_MAX_PATH]; + _fullpath(file_path, outfile, _MAX_PATH); + + int api_result = XDW_GetPage(h, p, file_path, NULL); + if (api_result < 0) { + fprintf(stderr, "XDW Error: cannot get page (%s p=%d)\n", infile, p); + return -1; + } + + XDW_CloseDocumentHandle(h, NULL); + return 0; +} + +void xdwmerge(const char* list, const char* output) { + FILE *fp; + + if ((fp = fopen(list, "r")) == NULL) { + fprintf(stderr, "XDW Error: can't open file [%s]\n", list); + exit(1); + } + + char *all_path = (char*)malloc(MAXLINE * sizeof(char) * _MAX_PATH); + + if (all_path == NULL) { + fprintf(stderr, "XDW Error: can't allocate memory\n"); + exit(1); + } + + int n = 0; + char *q; + char buf[_MAX_PATH]; + + while (fgets(buf, sizeof buf, fp)) { + if ((q = strchr(buf, '\n')) != NULL) { + *q = '\0'; + } + _fullpath(buf, buf, _MAX_PATH); + strncpy(&all_path[n * _MAX_PATH], buf, _MAX_PATH); + n++; + } + fclose(fp); + + char *blk_path = (char*)malloc(BLOCKSZ * sizeof(char) * _MAX_PATH); + const char **blk_path_addr = (const char**)malloc((n / BLOCKSZ + 1) * sizeof(char*) * _MAX_PATH); + if (blk_path == NULL || blk_path_addr == NULL) { + fprintf(stderr, "XDW Error: can't allocate memory\n"); + exit(1); + } + + // process by block + int api_result; + int bn = 0; + for (int p = 0, m = 0; p < n; p++) { + m = p % BLOCKSZ; + if (m == 0 && p > 0) { + sprintf(buf, "tmp_b%04d.xdw", ++bn); + _fullpath(buf, buf, _MAX_PATH); + api_result = XDW_MergeXdwFiles(blk_path_addr, BLOCKSZ, buf, NULL); + if (api_result < 0) { + fprintf(stderr, "XDW Error: can't merge [1] (p = %d, m = %d)\n", p, m); + exit(1); + } + } + strncpy(&blk_path[m * _MAX_PATH], &all_path[p * _MAX_PATH], _MAX_PATH); + blk_path_addr[m] = &blk_path[m * _MAX_PATH]; + } + + sprintf(buf, "tmp_b%04d.xdw", ++bn); + _fullpath(buf, buf, _MAX_PATH); + + int mod = n % BLOCKSZ; + if (mod == 0) mod = BLOCKSZ; + api_result = XDW_MergeXdwFiles(blk_path_addr, mod, buf, NULL); + + if (api_result < 0) { + fprintf(stderr, "XDW Error: can't merge [2]\n"); + exit(1); + } + + // merge blocks + for (int b = 0; b < bn; b++) { + sprintf(buf, "tmp_b%04d.xdw", b + 1); + _fullpath(buf, buf, _MAX_PATH); + strncpy(&blk_path[b * _MAX_PATH], buf, _MAX_PATH); + blk_path_addr[b] = &blk_path[b * _MAX_PATH]; + } + + _fullpath(buf, output, _MAX_PATH ); + api_result = XDW_MergeXdwFiles(blk_path_addr, bn, buf, NULL); + + if (api_result < 0) { + fprintf(stderr, "XDW Error: can't merge [3]\n"); + exit(1); + } + + free(all_path); + free(blk_path); + free(blk_path_addr); + + for (int b = 0; b < bn; b++) { + sprintf(buf, "tmp_b%04d.xdw", b + 1); + _fullpath(buf, buf, _MAX_PATH); + remove(buf); + } +} + +int xdwaddatn(const char* xdwfile, const char* atnfile) { + FILE *fp; + char filepath[_MAX_PATH]; + _fullpath(filepath, atnfile, _MAX_PATH); + + if ((fp = fopen(filepath, "r")) == NULL) { + fprintf(stderr, "Error: cannot open %s\n", filepath); + return -1; + } + + char keyword[128]; + char *q; + fgets(keyword, sizeof keyword, fp); + if ((q = strchr(keyword, '\n')) != NULL) { + *q = '\0'; + } + + char buf[_MAX_PATH]; + int x[ATN_N], y[ATN_N], sz[ATN_N], tr[ATN_N]; + char txt[ATN_N][256]; + int an = 0; + while (fgets(buf, sizeof buf, fp)) { + if ((q = strchr(buf, '\n')) != NULL) { + *q = '\0'; + } + + x[an] = atoi(strtok(buf, ",")); + y[an] = atoi(strtok(NULL, ",")); + sz[an] = atoi(strtok(NULL, ",")); + tr[an] = atoi(strtok(NULL, ",")); + strcpy(txt[an], strtok(NULL, ",")); + an++; + //printf("x=%d y=%d txt=%s sz=%d tr=%d\n", x[an], y[an], txt[an], sz[an], tr[an]); + } + fclose(fp); + + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; + + _fullpath(filepath, xdwfile, _MAX_PATH); + int api_result = XDW_OpenDocumentHandle(filepath, &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_FOUND_HANDLE pFoundHandle = NULL; + for (int i = 0; i < info.nPages; i++) { + if (keyword[0] != '\0') { + api_result = XDW_FindTextInPage(h, i + 1, keyword, NULL, &pFoundHandle, NULL); + if (!pFoundHandle) { + XDW_CloseFoundHandle(pFoundHandle); + continue; + } + XDW_CloseFoundHandle(pFoundHandle); + } + for (int j = 0; j < an; j++ ) { + XDW_ANNOTATION_HANDLE annoation; + int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x[j], y[j], NULL, &annoation, NULL); + if (api_result < 0) return api_result; + + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, txt[j], 0, NULL); + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz[j], 0, NULL); + + int color = XDW_COLOR_WHITE; + if (tr[j]) { + 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 xdwaddatntool(const char* xdwfile, const char* toolfile, int n, int x, int y) { + char filepath[_MAX_PATH]; + _fullpath(filepath, xdwfile, _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(filepath, &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); + + _fullpath(filepath, toolfile, _MAX_PATH); + for (int i = 0; i < info.nPages; i++) { + XDW_ANNOTATION_HANDLE annoation; + int api_result = XDW_AddAnnotationFromAnnFile(h, filepath, n, i + 1, NULL, x, y, &annoation, NULL); + } + + XDW_SaveDocument(h, NULL); + XDW_CloseDocumentHandle(h, NULL); + + return 0; +} + + +*/ +import "C" + +import ( + "bufio" + "regexp" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +type Hhs struct { + No string + Name string + Page int // sinsei page + Tsuchi bool + Kaigo string + Xdw []string +} + +func(h *Hhs) AppendXdw(xdw string) { + h.Xdw = append(h.Xdw, xdw) +} + +func(h *Hhs) CsvString() string { + q := "" + if h.Tsuchi { + q = "○" + } + k := strings.Split(h.Kaigo, "") + return strings.Join([]string{h.No, h.Name, q, k[1] + k[3]}, ",") +} + +func(h *Hhs) Dump() string { + q := "false" + if h.Tsuchi { + q = "true" + } + p := fmt.Sprintf("%05d", h.Page) + x := strings.Join(h.Xdw, ",") + return strings.Join([]string{h.No, h.Name, q, h.Kaigo, p, x}, ",") +} + +type Config struct { + Indir string + Outdir string + Workdir string + Hhsdb string + Atnfile[] string +} + +var ( + ver = "0.1" + conf Config + confjson = "95.json" + logfile = "95.log" + osirase = "KBPA316G.xdw" + sinsei = "KBPA406G.xdw" + rule_s = "rules.ann" + + out_o = "o.xdw" + out_s = "s.xdw" + out_q = "q.xdw" + out_l = "l.csv" + + re_hhsno, re_name, re_kaigo *regexp.Regexp + + // option parameters + version bool +) + +func init() { + /* コンフィグファイルは JSON */ + content, err := ioutil.ReadFile(confjson) + if err != nil { + log.Fatal(err) + } + if err := json.Unmarshal(content, &conf); err != nil { + log.Fatal(err) + } + + osirase = filepath.Join(conf.Indir, osirase) + sinsei = filepath.Join(conf.Indir, sinsei) + + out_o = filepath.Join(conf.Outdir, out_o) + out_s = filepath.Join(conf.Outdir, out_s) + out_q = filepath.Join(conf.Outdir, out_q) + out_l = filepath.Join(conf.Outdir, out_l) + + logfile = filepath.Join(conf.Workdir, logfile) + + /* 一時ファイル消去 */ + os.RemoveAll(conf.Outdir) + os.RemoveAll(conf.Workdir) + os.Mkdir(conf.Outdir, 0755) + os.Mkdir(conf.Workdir, 0755) + + /* 変数初期化 */ + re_hhsno = regexp.MustCompile(`0[1238]00\d{6}`) + re_name = regexp.MustCompile(`日.{30}`) + re_kaigo = regexp.MustCompile(`要((介護)|(支援)).`) + + flag.BoolVar(&version, "v", false, "print version") +} + +func main() { + flag.Parse() + + if version { + fmt.Println("95 - version", ver) + os.Exit(0) + } + + hash_Hhs := make(map[string]Hhs) + + /* 申請書を漁り,構造体を初期化 */ + for p, t := range xdw2txt(sinsei) { + hno := re_hhsno.FindString(t) + name := re_name.FindString(t) + name = strings.Replace(name, "日", "", 1) + kaigo := re_kaigo.FindString(t) + o := fmt.Sprintf("o_%05d.xdw", p + 1) + s := fmt.Sprintf("s_%05d.xdw", p + 1) + h := Hhs{No: hno, Name: name, Kaigo: kaigo, Page:p + 1, Xdw: []string{o, s}} + hash_Hhs[hno] = h + } + + /* バックグラウンドで給付費通知から勧奨対象者を抽出 */ + ch := make(chan int) + go func() { + files, err := ioutil.ReadDir(conf.Indir) + if err != nil { + log.Fatal(err) + } + + qn := 1 + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".xdw") { + continue + } + if strings.HasPrefix(file.Name(), "KDPK016G") || strings.HasPrefix(file.Name(), "KDPK126G") { + qtsuchi := filepath.Join(conf.Indir, file.Name()) + tmptxt := filepath.Join(conf.Workdir, "tmp95.txt") + for p, t := range xdw2txtb(qtsuchi, tmptxt) { + hno := re_hhsno.FindString(t) + if h, ok := hash_Hhs[hno]; ok { + h.Tsuchi = true + q := fmt.Sprintf("q_%05d.xdw", qn) + h.AppendXdw(q) + hash_Hhs[hno] = h + q = filepath.Join(conf.Workdir, q) + C.xdwextpage(C.CString(qtsuchi), C.int(p + 1), C.CString(q)) + qn++ + //fmt.Println(qtsuchi, p, hno, h.Kaigo, h.Xdw) + } + } + } + } + + ch <- 1 + }() + + /* そのあいだにバラす */ + C.xdwsplit1(C.CString(osirase), C.CString(conf.Workdir), C.CString("o_")) + C.xdwsplit1(C.CString(sinsei), C.CString(conf.Workdir), C.CString("s_")) + <-ch + + /* ソート & マージ */ + var slice_Hhs []Hhs + for _, h := range hash_Hhs { + slice_Hhs = append(slice_Hhs, h) + } + sort.Slice(slice_Hhs, func(i, j int) bool { + if slice_Hhs[i].Tsuchi != slice_Hhs[j].Tsuchi { + return slice_Hhs[i].Tsuchi + } + if slice_Hhs[i].Kaigo != slice_Hhs[j].Kaigo { + return slice_Hhs[i].Kaigo < slice_Hhs[j].Kaigo + } + if slice_Hhs[i].Page != slice_Hhs[j].Page { + return slice_Hhs[i].Page < slice_Hhs[j].Page + } + return false + }) + + var list_o, list_s, list_q []string + for _, h := range slice_Hhs { + list_o = append(list_o, filepath.Join(conf.Workdir, h.Xdw[0])) + list_s = append(list_s, filepath.Join(conf.Workdir, h.Xdw[1])) + if h.Tsuchi { + for i, x := range h.Xdw { + if i > 1 { + buf := filepath.Join(conf.Workdir, x) + list_q = append(list_q, buf) + } + } + } + } + xdwmerge(list_o, out_o) + xdwmerge(list_s, out_s) + xdwmerge(list_q, out_q) + + /* リスト出力 & ログダンプ */ + csvtxt := "" + logtxt := "" + for _, h := range slice_Hhs { + csvtxt += h.CsvString() + "\n" + logtxt += h.Dump() + "\n" + } + csvtxt, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), csvtxt) + if err := ioutil.WriteFile(out_l, []byte(csvtxt), 0644); err != nil { + log.Fatal(err) + } + if err := ioutil.WriteFile(logfile, []byte(logtxt), 0644); err != nil { + log.Fatal(err) + } + + /* バックグラウンドで給付費通知を校正 */ + ch2 := make(chan int) + go func() { + for _, a := range conf.Atnfile { + xdwaddatn(out_q, a) + } + ch2 <- 1 + } () + + /* そのあいだに申請書に枠付け */ + xdwaddatntool(out_s, rule_s, 2, 1497, 803) + <-ch2 +} + +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 xdw2txtb(xdwfile, txtfile string) (txt []string) { + if _, err := os.Stat(txtfile); os.IsExist(err) { + os.Remove(txtfile) + } + + C.xdw2txtb(C.CString(xdwfile), C.CString(txtfile)) + content, err := ioutil.ReadFile(txtfile) + if err != nil { + return nil + } + + r := strings.NewReader(string(content)) + tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) + buf := bufio.NewScanner(tr) + for buf.Scan() { + txt = append(txt, buf.Text()) + } + return +} + +func xdwmerge(list []string, outfile string) (err error) { + order := strings.Join(list, "\n") + order, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), order) + orderfile := filepath.Join(conf.Workdir, "order95.txt") + if err := ioutil.WriteFile(orderfile, []byte(order), 0644); err != nil { + return err + } + C.xdwmerge(C.CString(orderfile), C.CString(outfile)) + return nil +} + +func xdwaddatn(xdwfile, atnfile string) (err error) { + C.xdwaddatn(C.CString(xdwfile), C.CString(atnfile)) + return nil +} + +func xdwaddatntool(xdwfile, toolfile string, n, x, y int) (err error) { + C.xdwaddatntool(C.CString(xdwfile), C.CString(toolfile), C.int(n), C.int(x), C.int(y)) + return nil +} +