Mercurial > mercurial > hgweb_golang.cgi
diff src/kaigo/qtuti/95y/95y.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/95y.go Fri May 20 06:30:34 2022 +0900 @@ -0,0 +1,709 @@ +/* + 95y.go: Qfuhi Tsuchi (Year Version) + + Last Change: 2021-11-15 月 14:40:46. +*/ + +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" + "log" + "os" + "path/filepath" + "sort" + "strings" + + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +type Hhs struct { + No string + Name string + Weight int + //Text string + Xdw []string +} + +func(h *Hhs) AppendXdw(xdw string) { + h.Xdw = append(h.Xdw, xdw) +} + +func(h *Hhs) CsvString() string { + return strings.Join([]string{h.No, h.Name}, ",") +} + +func(h *Hhs) Dump() string { + x := strings.Join(h.Xdw, ",") + return strings.Join([]string{h.No, h.Name, fmt.Sprintf("%d", h.Weight), x}, "\t") +} + +type Config struct { + Indir string + Outdir string + Workdir string + Atnfile[] string +} + +var ( + ver = "0.1" + conf Config + confjson = "95y.json" + logfile = "95y.log" + whitexdw = "aiobo.xdw" + split_n = 9000 + + out_q1 = "q1.xdw" + out_q2 = "q2.xdw" + out_q3 = "q3.xdw" + out_l = "l.csv" + + delfile = "del.list" + sortfile = "sort.list" + + tmpfile = "95y.tmp" + + in_xdw []string + re_hhsno, re_name *regexp.Regexp + + // option parameters + version bool +) + +func init() { + /* コンフィグファイルは JSON */ + content, err := os.ReadFile(confjson) + if err != nil { + log.Fatal(err) + } + if err := json.Unmarshal(content, &conf); err != nil { + log.Fatal(err) + } + + out_q1 = filepath.Join(conf.Outdir, out_q1) + out_q2 = filepath.Join(conf.Outdir, out_q2) + out_q3 = filepath.Join(conf.Outdir, out_q3) + 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(`管理者 老 松 博 行.{14}`) + + /* Docuworksファイル列挙 */ + files, err := os.ReadDir(conf.Indir) + if err != nil { + log.Fatal(err) + } + + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".xdw") { + continue + } + if strings.HasPrefix(file.Name(), "KDPK016G") || strings.HasPrefix(file.Name(), "KDPK126G") { + in_xdw = append(in_xdw, file.Name()) + } + } + + flag.BoolVar(&version, "v", false, "print version") +} + +func main() { + flag.Parse() + + if version { + fmt.Println("95y - version", ver) + os.Exit(0) + } + + /* 重み付けの準備 */ + err, sort_list := file2slice(filepath.Join(conf.Indir, sortfile)) + if err != nil { + log.Fatal(err) + } + + /* 給付費通知を漁り,構造体を初期化 */ + hash_Hhs := make(map[string]Hhs) + for i, file := range in_xdw { + for p, t := range xdw2txtb(filepath.Join(conf.Indir, file), filepath.Join(conf.Workdir, tmpfile)) { + hno := re_hhsno.FindString(t) + _, ok := hash_Hhs[hno] + if strings.Contains(t, "大曲仙北広域市町村圏組合") && !ok { + name := re_name.FindString(t) + name = strings.Replace(name, "管理者 老 松 博 行", "", 1) + + w := 99 + for j, s := range sort_list { + if strings.Contains(t, s) { + w = j + } + } + + h := Hhs{No: hno, Name: name, Weight: w, Xdw: []string{fmt.Sprintf("%02d_%05d.xdw", i, p + 1)}} + hash_Hhs[hno] = h + } else { + h := hash_Hhs[hno] + h.AppendXdw(fmt.Sprintf("%02d_%05d.xdw", i, p + 1)) + hash_Hhs[hno] = h + } + //fmt.Println(file, i, "-", p) // <--- + } + } + fmt.Println("analize done") + + /* バックグラウンドで給付費通知をバラす */ + ch := make(chan int) + go func() { + for i, file := range in_xdw { + qtsuchi := filepath.Join(conf.Indir, file) + C.xdwsplit1(C.CString(qtsuchi), C.CString(conf.Workdir), C.CString(fmt.Sprintf("%02d_", i))) + } + ch <- 1 + fmt.Println("split done") + }() + + /* そのあいだに 不要者削除,ソート,マージ */ + err, del_list := file2slice(filepath.Join(conf.Indir, delfile)) + if err != nil { + log.Fatal(err) + } + for _, hno := range del_list { + delete(hash_Hhs, hno) + } + fmt.Println("delete done") + + /* ソート */ + 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].Weight != slice_Hhs[j].Weight { + return slice_Hhs[i].Weight < slice_Hhs[j].Weight + } + if slice_Hhs[i].No != slice_Hhs[j].No { + return slice_Hhs[i].No < slice_Hhs[j].No + } + return false + }) + fmt.Println("sort done") + + /* マージ */ + var list_q1, list_q2 []string + for _, h := range slice_Hhs { + if h.Weight < 99 { + for _, x := range h.Xdw { + buf := filepath.Join(conf.Workdir, x) + list_q1 = append(list_q1, buf) + } + if len(h.Xdw) % 2 == 1 { + list_q1 = append(list_q1, whitexdw) + } + } else { + for _, x := range h.Xdw { + buf := filepath.Join(conf.Workdir, x) + list_q2 = append(list_q2, buf) + } + if len(h.Xdw) % 2 == 1 { + list_q2 = append(list_q2, whitexdw) + } + } + } + + <-ch + xdwmerge(list_q1, out_q1) + if len(list_q2) <= split_n { + xdwmerge(list_q2, out_q2) + } else { + xdwmerge(list_q2[:split_n], out_q2) + xdwmerge(list_q2[split_n:], out_q3) + } + fmt.Println("merge done") + + /* バックグラウンドで給付費通知を校正 */ + ch_q1 := make(chan int) + go func() { + for _, a := range conf.Atnfile { + xdwaddatn(out_q1, a) + } + ch_q1 <- 1 + fmt.Println("correct1 done") + } () + + ch_q2 := make(chan int) + go func() { + for _, a := range conf.Atnfile { + xdwaddatn(out_q2, a) + } + ch_q2 <- 1 + fmt.Println("correct2 done") + } () + + ch_q3 := make(chan int) + if len(list_q2) > split_n { + go func() { + for _, a := range conf.Atnfile { + xdwaddatn(out_q3, a) + } + ch_q3 <- 1 + fmt.Println("correct3 done") + } () + } + + /* リスト出力 & ログダンプ */ + csvtxt := "" + logtxt := "" + for _, h := range slice_Hhs { + csvtxt += h.CsvString() + "\n" + logtxt += h.Dump() + "\n" + } + csvtxt, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), csvtxt) + if err := os.WriteFile(out_l, []byte(csvtxt), 0644); err != nil { + log.Fatal(err) + } + if err := os.WriteFile(logfile, []byte(logtxt), 0644); err != nil { + log.Fatal(err) + } + fmt.Println("logdump done") + + <-ch_q1 + <-ch_q2 + if len(list_q2) > split_n { + <-ch_q3 + } +} + +func file2slice(file string) (err error, list []string) { + f, err := os.Open(file) + if err != nil { + return err, nil + } + defer f.Close() + + buf := bufio.NewScanner(f) + for buf.Scan() { + list = append(list, buf.Text()) + } + return nil, list +} + +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 := os.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 := fmt.Sprintf("%s_order.txt", outfile) + if err := os.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 +} +