Mercurial > mercurial > hgweb_kaigo.hg.cgi
comparison Nk/nk.go @ 0:aaaa401818a1 draft
first commit.
| author | pyon <pyon@macmini> |
|---|---|
| date | Mon, 24 May 2021 21:32:58 +0900 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:aaaa401818a1 |
|---|---|
| 1 /* | |
| 2 nk.go: Nintei Kekka | |
| 3 | |
| 4 Last Change: 2020-10-16 金 14:27:50. | |
| 5 */ | |
| 6 | |
| 7 package main | |
| 8 | |
| 9 /* | |
| 10 #cgo LDFLAGS: -L. -lxdwapi -static | |
| 11 #include <stdio.h> | |
| 12 #include <stdlib.h> | |
| 13 #include <string.h> | |
| 14 #include <io.h> | |
| 15 #include <windows.h> | |
| 16 #include <xdw_api.h> | |
| 17 #include <xdwapian.h> | |
| 18 | |
| 19 #define MAXCOL 1024 | |
| 20 #define MAXLINE 9999 | |
| 21 #define BLOCKSZ 128 | |
| 22 | |
| 23 int xdwpages(const char* file) { | |
| 24 char in_path[_MAX_PATH]; | |
| 25 _fullpath(in_path, file, _MAX_PATH); | |
| 26 | |
| 27 XDW_DOCUMENT_HANDLE h = NULL; // 文書ハンドルを開く | |
| 28 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
| 29 if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { | |
| 30 printf("Error: cannot open %s\n", file); | |
| 31 return -1; | |
| 32 } | |
| 33 | |
| 34 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; // 総ページ数を得る | |
| 35 XDW_GetDocumentInformation(h, &info); | |
| 36 int nPage = info.nPages; | |
| 37 | |
| 38 XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる | |
| 39 | |
| 40 return nPage; | |
| 41 } | |
| 42 | |
| 43 char* xdw2txt(const char* file) { | |
| 44 char in_path[_MAX_PATH]; | |
| 45 _fullpath(in_path, file, _MAX_PATH); | |
| 46 | |
| 47 XDW_DOCUMENT_HANDLE h = NULL; // 文書ハンドルを開く | |
| 48 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
| 49 if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { | |
| 50 printf("Error: cannot open %s\n", file); | |
| 51 return NULL; | |
| 52 } | |
| 53 | |
| 54 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; // 総ページ数を得る | |
| 55 XDW_GetDocumentInformation(h, &info); | |
| 56 int nPage = info.nPages; | |
| 57 | |
| 58 // メイン処理 | |
| 59 char *lpszvalue, *all_lpszvalue; | |
| 60 long datasize[9999]; | |
| 61 for (int i=1; i<=nPage; i++) { | |
| 62 datasize[i] = XDW_GetPageTextToMemory(h, i, NULL, 0, NULL); | |
| 63 datasize[0] += datasize[i]; | |
| 64 } | |
| 65 datasize[0] += nPage - 1; // for "\n" | |
| 66 all_lpszvalue = (char*)malloc(sizeof(char)*datasize[0]); | |
| 67 all_lpszvalue[0] = '\0'; | |
| 68 for (int i=1; i<=nPage; i++) { | |
| 69 if (i<nPage) datasize[i]++; // for "\n" | |
| 70 lpszvalue = (char*)malloc(sizeof(char)*(datasize[i])); | |
| 71 XDW_GetPageTextToMemory(h, i, lpszvalue, datasize[i], NULL); | |
| 72 strcat(all_lpszvalue, lpszvalue); | |
| 73 if (i<nPage) strcat(all_lpszvalue, "\n"); | |
| 74 free(lpszvalue); | |
| 75 } | |
| 76 | |
| 77 XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる | |
| 78 return all_lpszvalue; | |
| 79 } | |
| 80 | |
| 81 int xdwpush(const char* file1, const char* file2) { | |
| 82 char in_path[_MAX_PATH], add_path[_MAX_PATH]; | |
| 83 _fullpath(in_path, file1, _MAX_PATH); | |
| 84 _fullpath(add_path, file2, _MAX_PATH); | |
| 85 | |
| 86 XDW_DOCUMENT_HANDLE h = NULL; | |
| 87 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 88 | |
| 89 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 90 if (api_result < 0) return api_result; | |
| 91 | |
| 92 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 93 XDW_GetDocumentInformation(h, &info); | |
| 94 int last_page = info.nPages; | |
| 95 | |
| 96 api_result = XDW_InsertDocument(h, last_page+1, add_path, NULL); | |
| 97 if (api_result < 0) api_result; | |
| 98 | |
| 99 XDW_SaveDocument(h, NULL); | |
| 100 XDW_CloseDocumentHandle(h, NULL); | |
| 101 | |
| 102 return (api_result >= 0); | |
| 103 } | |
| 104 | |
| 105 int xdwhbaddatn(const char* file, char* atnlist) { | |
| 106 char in_path[_MAX_PATH]; | |
| 107 _fullpath(in_path, file, _MAX_PATH); | |
| 108 | |
| 109 XDW_DOCUMENT_HANDLE h = NULL; | |
| 110 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 111 | |
| 112 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 113 if (api_result < 0) return api_result; | |
| 114 | |
| 115 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 116 XDW_GetDocumentInformation(h, &info); | |
| 117 | |
| 118 char *str, *token; | |
| 119 char *saveptr1, *saveptr2; | |
| 120 int x, y, sz, tr; | |
| 121 char *s; | |
| 122 | |
| 123 for (str = atnlist; ; str = NULL) { | |
| 124 token = strtok_r(str, ":", &saveptr1); | |
| 125 if (token == NULL) break; | |
| 126 //printf("%s\n", token); | |
| 127 | |
| 128 // atn.X, atn.Y, atn.Sz, tr, atn.Txt | |
| 129 x = atoi(strtok_r(token, ",", &saveptr2)); | |
| 130 y = atoi(strtok_r(NULL , ",", &saveptr2)); | |
| 131 sz = atoi(strtok_r(NULL, ",", &saveptr2)); | |
| 132 tr = atoi(strtok_r(NULL, ",", &saveptr2)); | |
| 133 s = strtok_r(NULL, ",", &saveptr2); | |
| 134 //printf("x=%d y=%d txt=%s sz=%d tr=%d\n", x, y, s, sz, tr); | |
| 135 | |
| 136 for (int i = 0; i < info.nPages; i++ ) { | |
| 137 XDW_ANNOTATION_HANDLE annoation; | |
| 138 int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x, y, NULL, &annoation, NULL); | |
| 139 | |
| 140 if (api_result < 0) return api_result; | |
| 141 | |
| 142 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, s, 0, NULL); | |
| 143 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 144 | |
| 145 if (tr) { | |
| 146 int color = XDW_COLOR_NONE; | |
| 147 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)&color, 0, NULL); | |
| 148 } | |
| 149 } | |
| 150 } | |
| 151 | |
| 152 XDW_SaveDocument(h, NULL); | |
| 153 XDW_CloseDocumentHandle(h, NULL); | |
| 154 | |
| 155 return 0; | |
| 156 } | |
| 157 | |
| 158 int xdwsort(const char* file, const char* sorted, const char* order, const char* workdir, const char* prefix) { | |
| 159 char buf[MAXCOL]; | |
| 160 | |
| 161 // メモリ確保 | |
| 162 char *sl = (char*)malloc(MAXLINE * sizeof(char) * MAXCOL); | |
| 163 if (sl == NULL) return -1; | |
| 164 | |
| 165 int slN = 0; | |
| 166 char *p; | |
| 167 p = strtok(order, ":"); | |
| 168 strncpy(&sl[slN * MAXCOL], p, MAXCOL); | |
| 169 slN++; | |
| 170 | |
| 171 while (p = strtok(NULL, ":")) { | |
| 172 strncpy(&sl[slN * MAXCOL], p, MAXCOL); | |
| 173 slN++; | |
| 174 } | |
| 175 | |
| 176 //for (int j = 0; j < slN; j++) printf("%d : %s\n", j, &sl[j * MAXCOL]); | |
| 177 //return 0; | |
| 178 | |
| 179 // 重み付け = 並び順 | |
| 180 char in_path[_MAX_PATH]; | |
| 181 _fullpath(in_path, file, _MAX_PATH); | |
| 182 | |
| 183 XDW_DOCUMENT_HANDLE h = NULL; | |
| 184 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
| 185 | |
| 186 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 187 if (api_result < 0) return api_result; | |
| 188 | |
| 189 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 190 XDW_GetDocumentInformation(h, &info); | |
| 191 int last_page = info.nPages; | |
| 192 | |
| 193 int *table = (int*)malloc(sizeof(int) * last_page); | |
| 194 for (int p = 0; p < last_page; p++) *(table + p) = 9999; | |
| 195 | |
| 196 int index = 0; | |
| 197 XDW_FOUND_HANDLE pFoundHandle = NULL; | |
| 198 for (int i = 0; i < slN; i++) { | |
| 199 for (int p = 0; p < last_page; p++) { | |
| 200 if (*(table + p) != 9999) continue; | |
| 201 | |
| 202 api_result = XDW_FindTextInPage(h, p + 1, &sl[i * MAXCOL], NULL, &pFoundHandle, NULL); | |
| 203 if (api_result < 0) return api_result; | |
| 204 | |
| 205 if (pFoundHandle != NULL) { | |
| 206 *(table + p) = ++index; | |
| 207 pFoundHandle = NULL; | |
| 208 } | |
| 209 } | |
| 210 } | |
| 211 free(sl); | |
| 212 | |
| 213 for (int p = 0; p < last_page; p++) { | |
| 214 if (*(table + p) == 9999) *(table + p) = ++index; | |
| 215 | |
| 216 sprintf(buf, "%s/%s_%04d.xdw", workdir, prefix, *(table + p)); | |
| 217 _fullpath(in_path, buf, _MAX_PATH); | |
| 218 | |
| 219 api_result = XDW_GetPage(h, p + 1, in_path, NULL); | |
| 220 if (api_result < 0) return api_result; | |
| 221 } | |
| 222 free(table); | |
| 223 XDW_CloseDocumentHandle(h, NULL); | |
| 224 | |
| 225 // ブロック処理 | |
| 226 char *blk_path = (char*)malloc(BLOCKSZ * sizeof(char) * _MAX_PATH); | |
| 227 const char **blk_path_addr = (const char**)malloc((last_page / BLOCKSZ + 1) * sizeof(char*) * _MAX_PATH); | |
| 228 | |
| 229 int bn = 0; | |
| 230 for (int p = 0, m = 0; p < last_page; p++) { | |
| 231 m = p % BLOCKSZ; | |
| 232 | |
| 233 if (m == 0 && p > 0) { | |
| 234 sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, ++bn); | |
| 235 _fullpath(in_path, buf, _MAX_PATH); | |
| 236 | |
| 237 api_result = XDW_MergeXdwFiles(blk_path_addr, BLOCKSZ, in_path, NULL); | |
| 238 if (api_result < 0) return api_result; | |
| 239 } | |
| 240 | |
| 241 sprintf(buf, "%s/%s_%04d.xdw", workdir, prefix, p + 1); | |
| 242 _fullpath(in_path, buf, _MAX_PATH); | |
| 243 | |
| 244 strncpy(&blk_path[m * _MAX_PATH], in_path, _MAX_PATH); | |
| 245 | |
| 246 blk_path_addr[m] = &blk_path[m * _MAX_PATH]; | |
| 247 } | |
| 248 | |
| 249 sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, ++bn); | |
| 250 _fullpath(in_path, buf, _MAX_PATH); | |
| 251 | |
| 252 int mod = last_page % BLOCKSZ; | |
| 253 if (mod == 0) mod = BLOCKSZ; | |
| 254 | |
| 255 api_result = XDW_MergeXdwFiles(blk_path_addr, mod, in_path, NULL); | |
| 256 if (api_result < 0) return api_result; | |
| 257 | |
| 258 for (int b = 0; b < bn; b++) { | |
| 259 sprintf(buf, "%s/%s_b%04d.xdw", workdir, prefix, b + 1); | |
| 260 | |
| 261 _fullpath(in_path, buf, _MAX_PATH); | |
| 262 strncpy(&blk_path[b * _MAX_PATH], in_path, _MAX_PATH); | |
| 263 | |
| 264 blk_path_addr[b] = &blk_path[b * _MAX_PATH]; | |
| 265 } | |
| 266 | |
| 267 _fullpath(in_path, sorted, _MAX_PATH); | |
| 268 | |
| 269 api_result = XDW_MergeXdwFiles(blk_path_addr, bn, in_path, NULL); | |
| 270 if (api_result < 0) return api_result; | |
| 271 | |
| 272 free(blk_path); | |
| 273 free(blk_path_addr); | |
| 274 | |
| 275 return 0; | |
| 276 } | |
| 277 | |
| 278 int xdwerase(const char* in_file, const char* ktxt, const char* htxt) { | |
| 279 int x = 20000; | |
| 280 int y = 3685; | |
| 281 int sz = 480; | |
| 282 | |
| 283 char in_path[_MAX_PATH]; | |
| 284 _fullpath(in_path, in_file, _MAX_PATH); | |
| 285 | |
| 286 XDW_DOCUMENT_HANDLE h = NULL; | |
| 287 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 288 | |
| 289 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 290 if (api_result < 0) return api_result; | |
| 291 | |
| 292 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 293 XDW_GetDocumentInformation(h, &info); | |
| 294 | |
| 295 XDW_FOUND_HANDLE pFoundHandle = NULL; | |
| 296 for (int i = 0; i < info.nPages; i++) { | |
| 297 api_result = XDW_FindTextInPage(h, i + 1, htxt, NULL, &pFoundHandle, NULL); | |
| 298 if (pFoundHandle == NULL) continue; | |
| 299 | |
| 300 api_result = XDW_FindTextInPage(h, i + 1, ktxt, NULL, &pFoundHandle, NULL); | |
| 301 if (pFoundHandle == NULL) continue; | |
| 302 | |
| 303 XDW_ANNOTATION_HANDLE annoation; | |
| 304 int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x, y, NULL, &annoation, NULL); | |
| 305 if (api_result < 0) return api_result; | |
| 306 | |
| 307 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, " ", 0, NULL); | |
| 308 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 309 } | |
| 310 | |
| 311 XDW_SaveDocument(h, NULL); | |
| 312 XDW_CloseDocumentHandle(h, NULL); | |
| 313 | |
| 314 return 0; | |
| 315 } | |
| 316 | |
| 317 int xdw2pdf(const char* xdwfile, const char* pdffile) { | |
| 318 char in_path[_MAX_PATH], out_path[_MAX_PATH]; | |
| 319 _fullpath(in_path, xdwfile, _MAX_PATH); | |
| 320 _fullpath(out_path, pdffile, _MAX_PATH); | |
| 321 | |
| 322 remove(out_path); | |
| 323 int api_result = 0; | |
| 324 | |
| 325 XDW_DOCUMENT_HANDLE h = NULL; | |
| 326 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
| 327 | |
| 328 api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 329 if (api_result < 0) return api_result; | |
| 330 | |
| 331 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 332 XDW_GetDocumentInformation(h, &info); | |
| 333 | |
| 334 XDW_IMAGE_OPTION_PDF pdf = { | |
| 335 sizeof(XDW_IMAGE_OPTION_PDF), | |
| 336 XDW_COMPRESS_MRC_NORMAL, | |
| 337 XDW_CONVERT_MRC_OS, | |
| 338 info.nPages | |
| 339 }; | |
| 340 | |
| 341 XDW_IMAGE_OPTION_EX ex = { | |
| 342 sizeof(XDW_IMAGE_OPTION_EX), | |
| 343 600, // dpi | |
| 344 XDW_IMAGE_MONO_HIGHQUALITY, | |
| 345 XDW_IMAGE_PDF, | |
| 346 &pdf | |
| 347 }; | |
| 348 | |
| 349 api_result = XDW_ConvertPageToImageFile(h, 1, out_path, (XDW_IMAGE_OPTION*)&ex); | |
| 350 | |
| 351 XDW_SaveDocument(h, NULL); | |
| 352 XDW_CloseDocumentHandle(h, NULL); | |
| 353 | |
| 354 return 0; | |
| 355 } | |
| 356 | |
| 357 int xdwopt(const char* in, const char* out) { | |
| 358 char in_path[_MAX_PATH], out_path[_MAX_PATH]; | |
| 359 _fullpath(in_path, in, _MAX_PATH); | |
| 360 _fullpath(out_path, out, _MAX_PATH); | |
| 361 | |
| 362 int api_result = XDW_OptimizeDocument(in_path, out_path, NULL); | |
| 363 return (api_result >= 0); | |
| 364 } | |
| 365 */ | |
| 366 import "C" | |
| 367 | |
| 368 import ( | |
| 369 "bufio" | |
| 370 "encoding/json" | |
| 371 "fmt" | |
| 372 "flag" | |
| 373 "io/ioutil" | |
| 374 "log" | |
| 375 "os" | |
| 376 "os/exec" | |
| 377 "path/filepath" | |
| 378 "regexp" | |
| 379 "sort" | |
| 380 "strings" | |
| 381 "time" | |
| 382 | |
| 383 "golang.org/x/text/encoding/japanese" | |
| 384 "golang.org/x/text/transform" | |
| 385 ) | |
| 386 | |
| 387 var ( | |
| 388 ver = "0.3" | |
| 389 | |
| 390 flg_hb int | |
| 391 flg_time bool | |
| 392 flg_log bool | |
| 393 flg_debug bool | |
| 394 flg_clean bool | |
| 395 | |
| 396 confjson = "nk.json" | |
| 397 logfile = "nk.log" | |
| 398 hhscsv = "hhsdb.csv" | |
| 399 tmpdir string | |
| 400 tmpprefix = "nktemp_" | |
| 401 inputdir = "input" | |
| 402 outputdir = "output" | |
| 403 outcsv = "out.csv" | |
| 404 | |
| 405 start time.Time | |
| 406 | |
| 407 hb string // 発番 | |
| 408 fw, hs, kt = "", "", "kttemp.xdw" // 負担割合証, 被保険者証, 結果通知 | |
| 409 | |
| 410 step, totalstep = 1, 14 | |
| 411 ) | |
| 412 | |
| 413 type Annotation struct { | |
| 414 X, Y int | |
| 415 Sz int | |
| 416 Tr bool | |
| 417 Txt string | |
| 418 } | |
| 419 | |
| 420 type Config struct { | |
| 421 Atns []Annotation | |
| 422 Kyotaku []string | |
| 423 } | |
| 424 | |
| 425 func (c *Config) ProcessTemplate() { | |
| 426 today := time.Now().Format("令和 r 年 1 月 2 日") | |
| 427 y := time.Now().Year() - 2018 | |
| 428 if y == 1 { | |
| 429 today = strings.ReplaceAll(today, "r", "元") | |
| 430 } else { | |
| 431 today = strings.ReplaceAll(today, "r", fmt.Sprintf("%d", y)) | |
| 432 } | |
| 433 | |
| 434 var atns []Annotation | |
| 435 for _, atn := range c.Atns { | |
| 436 s := atn.Txt | |
| 437 if atn.Txt == "date" { | |
| 438 s = today | |
| 439 } | |
| 440 if strings.ContainsAny(atn.Txt, "hb") { | |
| 441 s = strings.ReplaceAll(atn.Txt, "hb", hb) | |
| 442 } | |
| 443 atns = append(atns, Annotation{atn.X, atn.Y, atn.Sz, atn.Tr, s}) | |
| 444 } | |
| 445 c.Atns = atns | |
| 446 } | |
| 447 | |
| 448 func (c *Config) KyotakuList() []string { | |
| 449 return c.Kyotaku | |
| 450 } | |
| 451 | |
| 452 func (c *Config) AnnotationList() (al []string) { | |
| 453 for _, atn := range c.Atns { | |
| 454 tr := 0 | |
| 455 if atn.Tr { | |
| 456 tr = 1 | |
| 457 } | |
| 458 s := fmt.Sprintf("%d,%d,%d,%d,%s", atn.X, atn.Y, atn.Sz, tr, atn.Txt) | |
| 459 al = append(al, s) | |
| 460 } | |
| 461 return | |
| 462 } | |
| 463 | |
| 464 func init() { | |
| 465 /* INITIALIZE FLAGS */ | |
| 466 flag.IntVar(&flg_hb, "b", 0, "set hatsuban") | |
| 467 flag.BoolVar(&flg_time, "t", false, "print time") | |
| 468 flag.BoolVar(&flg_log, "l", false, "save log") | |
| 469 flag.BoolVar(&flg_debug, "d", false, "print data for debug") | |
| 470 flag.BoolVar(&flg_clean, "c", false, "clean temporary directory & exit") | |
| 471 | |
| 472 /* CREAN OUTPUT-FILE & TEMP-FILE */ | |
| 473 if err := os.RemoveAll(outputdir); err != nil { | |
| 474 log.Fatal(err) | |
| 475 } | |
| 476 os.Remove(logfile) | |
| 477 | |
| 478 /* PREPARATE OUTPUT-DIR & TEMP-DIR */ | |
| 479 if err := os.Mkdir(outputdir, 0755); err != nil { | |
| 480 log.Fatal(err) | |
| 481 } | |
| 482 | |
| 483 var err error | |
| 484 tmpdir, err = ioutil.TempDir(".", tmpprefix) | |
| 485 if err != nil { | |
| 486 log.Fatal(err) | |
| 487 } | |
| 488 logfile = filepath.Join(tmpdir, logfile) | |
| 489 kt = filepath.Join(tmpdir, kt) | |
| 490 } | |
| 491 | |
| 492 func main() { | |
| 493 flag.Parse() | |
| 494 | |
| 495 /* CLEAN TEMPORARY DIRECTORY */ | |
| 496 if flg_clean { | |
| 497 files, err := ioutil.ReadDir(".") | |
| 498 if err != nil { | |
| 499 log.Fatal(err) | |
| 500 } | |
| 501 for _, file := range files { | |
| 502 if strings.HasPrefix(file.Name(), tmpprefix) { | |
| 503 if err := os.RemoveAll(file.Name()); err != nil { | |
| 504 log.Fatal(err) | |
| 505 } | |
| 506 } | |
| 507 } | |
| 508 os.Exit(0) | |
| 509 } | |
| 510 | |
| 511 /* PRINT HEADER */ | |
| 512 fmt.Println("=======================================") | |
| 513 fmt.Println(" 被保険者証と結果通知と負担割合証を... ") | |
| 514 fmt.Printf(" - nk [ver %s] -\n", ver) | |
| 515 fmt.Println("=======================================\n") | |
| 516 | |
| 517 /* USER INPUT */ | |
| 518 hb = fmt.Sprintf("%d", flg_hb) | |
| 519 if flg_hb == 0 { | |
| 520 fmt.Print("発番 > ") | |
| 521 fmt.Scan(&hb) | |
| 522 } | |
| 523 | |
| 524 start = time.Now() | |
| 525 | |
| 526 /* READ CONFIG FROM JSON */ | |
| 527 print_step("設定読込み") | |
| 528 conf, err := read_conf(confjson) | |
| 529 if err != nil { | |
| 530 log.Fatal(err) | |
| 531 } | |
| 532 conf.ProcessTemplate() | |
| 533 step_start := print_time(start) | |
| 534 | |
| 535 /* CHECK INPUT-FILE */ | |
| 536 print_step("入力ファイルのチェック") | |
| 537 files, err := ioutil.ReadDir(inputdir) | |
| 538 if err != nil { | |
| 539 log.Fatal(err) | |
| 540 } | |
| 541 | |
| 542 var kts []string | |
| 543 for _, file := range files { | |
| 544 if strings.HasSuffix(file.Name(), ".xdw") { | |
| 545 print_debug([]string{file.Name()}) | |
| 546 switch file.Name()[0:8] { | |
| 547 case "KBPV016G": | |
| 548 fw = filepath.Join(inputdir, file.Name()) | |
| 549 case "KBPG316G": | |
| 550 hs = filepath.Join(inputdir, file.Name()) | |
| 551 case "KBPG206G", "KBPG706G": | |
| 552 f := filepath.Join(inputdir, file.Name()) | |
| 553 kts = append(kts, f) | |
| 554 } | |
| 555 } | |
| 556 } | |
| 557 | |
| 558 fmt.Println() | |
| 559 fmt.Printf(" 負担割合証ファイル = %s\n", fw) | |
| 560 fmt.Printf(" 被保険者証ファイル = %s\n", hs) | |
| 561 fmt.Print(" 結果通知ファイル =") | |
| 562 for _, f := range kts { | |
| 563 fmt.Printf(" %s", f) | |
| 564 } | |
| 565 fmt.Println() | |
| 566 if fw == "" || hs == "" || len(kts) == 0 { | |
| 567 fmt.Fprintf(os.Stderr, "Input file is wrong.\n") | |
| 568 os.Exit(1) | |
| 569 } | |
| 570 | |
| 571 bytes, err := ioutil.ReadFile(hhscsv) | |
| 572 if err != nil { | |
| 573 log.Fatal(err) | |
| 574 } | |
| 575 hash_hhs := make(map[string]string) // 被保険者氏名のハッシュ | |
| 576 r := strings.NewReader(string(bytes)) | |
| 577 tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) | |
| 578 buf := bufio.NewScanner(tr) | |
| 579 for buf.Scan() { | |
| 580 records := strings.Split(buf.Text(), ",") | |
| 581 hash_hhs[records[0]] = records[2] | |
| 582 } | |
| 583 fmt.Printf(" 被保険者ファイル = %s\n", hhscsv) | |
| 584 | |
| 585 step_start = print_time(step_start) | |
| 586 | |
| 587 /* CONCATNATE INPUT-FILE */ | |
| 588 print_step("結果通知ファイルの連結") | |
| 589 b, err := ioutil.ReadFile(kts[0]) | |
| 590 if err != nil { | |
| 591 log.Fatal(err) | |
| 592 } | |
| 593 if err = ioutil.WriteFile(kt, b, 0644); err != nil { | |
| 594 log.Fatal(err) | |
| 595 } | |
| 596 if len(kts) > 1 { | |
| 597 pp := 0 | |
| 598 fmt.Println() | |
| 599 for _, file := range kts { | |
| 600 p, _ := C.xdwpages(C.CString(file)) | |
| 601 fmt.Printf(" %s\t= %d ページ\n", file, int(p)) | |
| 602 pp += int(p) | |
| 603 } | |
| 604 fmt.Printf(" 合計\t= %d ページ\n", pp) | |
| 605 for _, file := range kts[1:] { | |
| 606 C.xdwpush(C.CString(kt), C.CString(file)) | |
| 607 } | |
| 608 } | |
| 609 step_start = print_time(step_start) | |
| 610 | |
| 611 /* MAKE SORT-TABEL */ | |
| 612 print_step("並び順の決定") | |
| 613 | |
| 614 re_hhs := regexp.MustCompile(`05((2126)|(2159)|(4346))0[1238]\d{8}`) | |
| 615 re_kaigo := regexp.MustCompile(`要((介護)|(支援)).`) | |
| 616 | |
| 617 hash_fw := make(map[string]int) // 負担割合証発行者のハッシュ | |
| 618 for _, t := range xdw2txt(fw) { | |
| 619 hash_fw[re_hhs.FindString(t)]++ | |
| 620 print_debug([]string{re_hhs.FindString(t)}) | |
| 621 } | |
| 622 | |
| 623 kyotaku := conf.KyotakuList() | |
| 624 | |
| 625 hash_kaigo := make(map[string]string) // 被保険者証発行者の要介護度のハッシュ | |
| 626 hash_kyotaku := make(map[string]string) // 被保険者証発行者の居宅介護支援事業所のハッシュ | |
| 627 var sorttable []string | |
| 628 for _, t := range xdw2txt(hs) { | |
| 629 h := re_hhs.FindString(t) | |
| 630 hash_kaigo[h] = re_kaigo.FindString(t) | |
| 631 for _, k := range kyotaku { | |
| 632 if strings.Contains(t, k) { | |
| 633 hash_kyotaku[h] = k | |
| 634 } | |
| 635 } | |
| 636 key := make_sort_key(hash_fw[h], re_kaigo.FindString(t), h) | |
| 637 s := fmt.Sprintf("%s#%d:%s:%s#%s", key, hash_fw[h], re_kaigo.FindString(t), hash_kyotaku[h], h) | |
| 638 sorttable = append(sorttable, s) | |
| 639 } | |
| 640 //sort.Sort(sort.Reverse(sort.StringSlice(sorttable))) | |
| 641 sort.Sort(sort.StringSlice(sorttable)) | |
| 642 print_debug(sorttable) | |
| 643 step_start = print_time(step_start) | |
| 644 | |
| 645 /* DO SORT */ | |
| 646 order := "" | |
| 647 for _, s := range sorttable { | |
| 648 t := strings.Split(s, "#") | |
| 649 order += ":" + t[len(t)-1][6:] | |
| 650 } | |
| 651 order = strings.Replace(order, ":", "", 1) | |
| 652 | |
| 653 print_step("被保険者証並び替え") | |
| 654 hs_sorted := filepath.Join(tmpdir, "hs.xdw") | |
| 655 C.xdwsort(C.CString(hs), C.CString(hs_sorted), C.CString(order), C.CString(tmpdir), C.CString("hs")) | |
| 656 step_start = print_time(step_start) | |
| 657 | |
| 658 print_step("負担割合証並び替え") | |
| 659 fw_sorted := filepath.Join(tmpdir, "fw.xdw") | |
| 660 C.xdwsort(C.CString(fw), C.CString(fw_sorted), C.CString(order), C.CString(tmpdir), C.CString("fw")) | |
| 661 step_start = print_time(step_start) | |
| 662 | |
| 663 print_step("結果通知並び替え") | |
| 664 kt_sorted := filepath.Join(tmpdir, "kt.xdw") | |
| 665 C.xdwsort(C.CString(kt), C.CString(kt_sorted), C.CString(order), C.CString(tmpdir), C.CString("kt")) | |
| 666 step_start = print_time(step_start) | |
| 667 | |
| 668 /* ADD HATSUBAN */ | |
| 669 print_step("発番印字") | |
| 670 al := strings.Join(conf.AnnotationList(), ":") | |
| 671 al, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), al) | |
| 672 C.xdwhbaddatn(C.CString(kt_sorted), C.CString(al)) | |
| 673 step_start = print_time(step_start) | |
| 674 | |
| 675 /* ERASE HOUKATSU */ | |
| 676 print_step("包括除去") | |
| 677 ktxt, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), "要介護") | |
| 678 htxt, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), "包括支援センター") | |
| 679 C.xdwerase(C.CString(hs_sorted), C.CString(ktxt), C.CString(htxt)) | |
| 680 step_start = print_time(step_start) | |
| 681 | |
| 682 /* OPTIMIZE OUTPUT-FILE */ | |
| 683 print_step("最適化") | |
| 684 hs_opt := filepath.Join(outputdir, "hs.xdw") | |
| 685 C.xdwopt(C.CString(hs_sorted), C.CString(hs_opt)) | |
| 686 fw_opt := filepath.Join(outputdir, "fw.xdw") | |
| 687 C.xdwopt(C.CString(fw_sorted), C.CString(fw_opt)) | |
| 688 kt_opt := filepath.Join(outputdir, "kt.xdw") | |
| 689 C.xdwopt(C.CString(kt_sorted), C.CString(kt_opt)) | |
| 690 step_start = print_time(step_start) | |
| 691 | |
| 692 /* OUTPUT CSV */ | |
| 693 print_step("CSV出力") | |
| 694 outcsv = filepath.Join(outputdir, outcsv) | |
| 695 fcsv, err := os.OpenFile(outcsv, os.O_RDWR|os.O_CREATE, 0644) | |
| 696 if err != nil { | |
| 697 log.Fatal(err) | |
| 698 } | |
| 699 for i, s := range sorttable { | |
| 700 t := strings.Split(s, "#") | |
| 701 u := strings.ReplaceAll(t[1], ":", ",") | |
| 702 u, _, _ = transform.String(japanese.ShiftJIS.NewEncoder(), u) | |
| 703 c := t[2][0:6] | |
| 704 h := t[2][6:16] | |
| 705 n, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), hash_hhs[h]) | |
| 706 // seq, city, hno, name, kaigo, fw, kyotaku | |
| 707 fmt.Fprintf(fcsv, "%04d,%s,%s,%s,%s\n", i + 1, c, h, n, u) | |
| 708 } | |
| 709 if err := fcsv.Close(); err != nil { | |
| 710 log.Fatal(err) | |
| 711 } | |
| 712 step_start = print_time(step_start) | |
| 713 | |
| 714 /* PDF */ | |
| 715 print_step("負担割合証割付PDF作成") | |
| 716 fwpdf := filepath.Join(tmpdir, "fw.pdf") | |
| 717 C.xdw2pdf(C.CString(fw_opt), C.CString(fwpdf)) // 2min | |
| 718 step_start = print_time(step_start) | |
| 719 | |
| 720 print_step("負担割合証PDF割付") | |
| 721 fw4pdf := filepath.Join(outputdir, "fw4.pdf") | |
| 722 cmd := exec.Command("fw4.exe", fwpdf, fw4pdf, tmpdir) | |
| 723 if err := cmd.Run(); err != nil { | |
| 724 log.Fatal(err) | |
| 725 } | |
| 726 step_start = print_time(step_start) | |
| 727 | |
| 728 print_step("終了") | |
| 729 step_start = print_time(step_start) | |
| 730 | |
| 731 /* REMOVE TEMP-FILE */ | |
| 732 if flg_log { | |
| 733 logfile2 := filepath.Join(".", strings.Replace(logfile, tmpdir, "", 1)) | |
| 734 os.Link(logfile, logfile2) | |
| 735 } | |
| 736 | |
| 737 if !flg_debug { | |
| 738 if err := os.RemoveAll(tmpdir); err != nil { | |
| 739 log.Fatal(err) | |
| 740 } | |
| 741 } | |
| 742 } | |
| 743 | |
| 744 func make_sort_key(fw int, kaigo, h string) string { | |
| 745 key := fmt.Sprintf("%d:", 9 - fw) | |
| 746 if strings.HasPrefix(kaigo, "要支援") { | |
| 747 key += "1" | |
| 748 } | |
| 749 if strings.HasPrefix(kaigo, "要介護") { | |
| 750 key += "2" | |
| 751 } | |
| 752 switch { | |
| 753 case strings.HasSuffix(kaigo, "1"): | |
| 754 key += "1:" | |
| 755 case strings.HasSuffix(kaigo, "2"): | |
| 756 key += "2:" | |
| 757 case strings.HasSuffix(kaigo, "3"): | |
| 758 key += "3:" | |
| 759 case strings.HasSuffix(kaigo, "4"): | |
| 760 key += "4:" | |
| 761 case strings.HasSuffix(kaigo, "5"): | |
| 762 key += "5:" | |
| 763 default: | |
| 764 key += "00:" | |
| 765 } | |
| 766 return key + h | |
| 767 } | |
| 768 | |
| 769 func xdw2txt(file string) (txt []string) { | |
| 770 s := C.GoString(C.xdw2txt(C.CString(file))) | |
| 771 r := strings.NewReader(s) | |
| 772 tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) | |
| 773 buf := bufio.NewScanner(tr) | |
| 774 for buf.Scan() { | |
| 775 txt = append(txt, buf.Text()) | |
| 776 } | |
| 777 return; | |
| 778 } | |
| 779 | |
| 780 func read_conf(file string) (conf Config, err error) { | |
| 781 content, err := ioutil.ReadFile(file) | |
| 782 if err != nil { | |
| 783 log.Fatal(err) | |
| 784 } | |
| 785 err = json.Unmarshal(content, &conf) | |
| 786 return | |
| 787 } | |
| 788 | |
| 789 func print_step(msg string) { | |
| 790 s := fmt.Sprintf("\n[%d/%d] %s\n", step, totalstep, msg) | |
| 791 step++ | |
| 792 fmt.Print(s) | |
| 793 save_log(s) | |
| 794 } | |
| 795 | |
| 796 func print_time(t time.Time) time.Time { | |
| 797 now := time.Now() | |
| 798 if !flg_time { | |
| 799 return now | |
| 800 } | |
| 801 elapsed := now.Sub(t) | |
| 802 total := now.Sub(start) | |
| 803 s := fmt.Sprintf("---- Elapsed: %v (total = %v) @ %02d:%02d\n", elapsed, total, now.Hour(), now.Minute()) | |
| 804 fmt.Print(s) | |
| 805 save_log(s) | |
| 806 return now | |
| 807 } | |
| 808 | |
| 809 func print_debug(msg []string) { | |
| 810 if !flg_debug { | |
| 811 return | |
| 812 } | |
| 813 s := "" | |
| 814 if len(msg) == 1 { | |
| 815 s = fmt.Sprintf("----- %s\n", msg) | |
| 816 } | |
| 817 for i, s := range msg { | |
| 818 s += fmt.Sprintf("%05d %s\n", i, s) | |
| 819 } | |
| 820 fmt.Print(s) | |
| 821 save_log(s) | |
| 822 } | |
| 823 | |
| 824 func save_log(logtxt string) error { | |
| 825 if !flg_log { | |
| 826 return nil | |
| 827 } | |
| 828 f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) | |
| 829 if err != nil { | |
| 830 return err | |
| 831 } | |
| 832 if _, err := f.Write([]byte(logtxt)); err != nil { | |
| 833 f.Close() | |
| 834 return err | |
| 835 } | |
| 836 if err := f.Close(); err != nil { | |
| 837 return err | |
| 838 } | |
| 839 return nil | |
| 840 } | |
| 841 |
