Mercurial > mercurial > hgweb_golang.cgi
comparison src/kaigo/fwgo/fwgo.go @ 57:05f3d51ad966
add fwgo.
author | pyon@macmini |
---|---|
date | Wed, 15 Jul 2020 18:18:24 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
56:7396e7407abd | 57:05f3d51ad966 |
---|---|
1 /* | |
2 fwgo.go: Futan-Wariai de Go | |
3 | |
4 Last Change: 2020-07-14 火 15:04:09. | |
5 */ | |
6 package main | |
7 | |
8 /* | |
9 #cgo LDFLAGS: -L. -lxdwapi -static | |
10 #include <stdio.h> | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 #include <io.h> | |
14 #include <windows.h> | |
15 #include <xdw_api.h> | |
16 #include <xdwapian.h> | |
17 | |
18 #define MAXLINE 12000 | |
19 #define BLOCKSZ 128 | |
20 | |
21 void xdw2txt(const char* xdwfile, const char* txtfile) { | |
22 char in_path[_MAX_PATH]; | |
23 _fullpath(in_path, xdwfile, _MAX_PATH); | |
24 | |
25 XDW_DOCUMENT_HANDLE h = NULL; | |
26 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
27 if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { | |
28 printf("XDW Error: cannot open %s\n", xdwfile); | |
29 return; | |
30 } | |
31 | |
32 int api_result = XDW_GetFullText(h, txtfile, NULL); | |
33 if (api_result < 0) { | |
34 printf("Error: cannot write text\n"); | |
35 return; | |
36 } | |
37 XDW_CloseDocumentHandle(h, NULL); | |
38 } | |
39 | |
40 void xdwsplit1(const char* xdwfile) { | |
41 char in_path[_MAX_PATH]; | |
42 _fullpath(in_path, xdwfile, _MAX_PATH); | |
43 | |
44 XDW_DOCUMENT_HANDLE h = NULL; | |
45 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; | |
46 if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { | |
47 printf("Error: cannot open %s\n", xdwfile); | |
48 return; | |
49 } | |
50 | |
51 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
52 XDW_GetDocumentInformation(h, &info); | |
53 int nPage = info.nPages; | |
54 | |
55 char buf[_MAX_PATH]; | |
56 for (int i = 1; i <= nPage; i++) { | |
57 sprintf(buf, "fwtmp_%05d.xdw", i); | |
58 _fullpath(in_path, buf, _MAX_PATH); | |
59 | |
60 int api_result = XDW_GetPage(h, i, in_path, NULL); | |
61 if (api_result < 0) { | |
62 printf("XDW Error: cannot get page\n"); | |
63 return; | |
64 } | |
65 } | |
66 XDW_CloseDocumentHandle(h, NULL); | |
67 } | |
68 | |
69 void xdwmerge(const char* list, const char* output) { | |
70 | |
71 FILE *fp; | |
72 if ((fp = fopen(list, "r")) == NULL) { | |
73 fprintf(stderr, "can't open file [%s]\n", list); | |
74 exit(1); | |
75 } | |
76 | |
77 char *all_path = (char*)malloc(MAXLINE * sizeof(char) * _MAX_PATH); | |
78 if (all_path == NULL) { | |
79 fprintf(stderr, "can't allocate memory\n"); | |
80 exit(1); | |
81 } | |
82 | |
83 int n = 0; | |
84 char *q; | |
85 char buf[_MAX_PATH]; | |
86 | |
87 while (fgets(buf, sizeof buf, fp)) { | |
88 if ((q = strchr(buf, '\n')) != NULL) { | |
89 *q = '\0'; | |
90 } | |
91 _fullpath(buf, buf, _MAX_PATH); | |
92 strncpy(&all_path[n * _MAX_PATH], buf, _MAX_PATH); | |
93 n++; | |
94 } | |
95 fclose(fp); | |
96 | |
97 char *blk_path = (char*)malloc(BLOCKSZ * sizeof(char) * _MAX_PATH); | |
98 const char **blk_path_addr = (const char**)malloc((n / BLOCKSZ + 1) * sizeof(char*) * _MAX_PATH); | |
99 if (blk_path == NULL || blk_path_addr == NULL) { | |
100 fprintf(stderr, "can't allocate memory\n"); | |
101 exit(1); | |
102 } | |
103 | |
104 // process by block | |
105 int api_result; | |
106 int bn = 0; | |
107 for (int p = 0, m = 0; p < n; p++) { | |
108 m = p % BLOCKSZ; | |
109 if (m == 0 && p > 0) { | |
110 sprintf(buf, "fwtmp_b%04d.xdw", ++bn); | |
111 _fullpath(buf, buf, _MAX_PATH); | |
112 api_result = XDW_MergeXdwFiles(blk_path_addr, BLOCKSZ, buf, NULL); | |
113 if (api_result < 0) { | |
114 fprintf(stderr, "can't merge [1] (p = %d, m = %d)\n", p, m); | |
115 exit(1); | |
116 } | |
117 } | |
118 strncpy(&blk_path[m * _MAX_PATH], &all_path[p * _MAX_PATH], _MAX_PATH); | |
119 blk_path_addr[m] = &blk_path[m * _MAX_PATH]; | |
120 } | |
121 | |
122 sprintf(buf, "fwtmp_b%04d.xdw", ++bn); | |
123 _fullpath(buf, buf, _MAX_PATH); | |
124 int mod = n % BLOCKSZ; | |
125 if (mod == 0) mod = BLOCKSZ; | |
126 api_result = XDW_MergeXdwFiles(blk_path_addr, mod, buf, NULL); | |
127 if (api_result < 0) { | |
128 fprintf(stderr, "can't merge [2]\n"); | |
129 exit(1); | |
130 } | |
131 | |
132 // merge blocks | |
133 for (int b = 0; b < bn; b++) { | |
134 sprintf(buf, "fwtmp_b%04d.xdw", b + 1); | |
135 _fullpath(buf, buf, _MAX_PATH); | |
136 strncpy(&blk_path[b * _MAX_PATH], buf, _MAX_PATH); | |
137 blk_path_addr[b] = &blk_path[b * _MAX_PATH]; | |
138 } | |
139 _fullpath(buf, output, _MAX_PATH ); | |
140 api_result = XDW_MergeXdwFiles(blk_path_addr, bn, buf, NULL); | |
141 if (api_result < 0) { | |
142 fprintf(stderr, "can't merge [3]\n"); | |
143 exit(1); | |
144 } | |
145 | |
146 free(all_path); | |
147 free(blk_path); | |
148 free(blk_path_addr); | |
149 } | |
150 | |
151 int xdwaddannotation(XDW_DOCUMENT_HANDLE h, int page, int x, int y, char* string, int* sz, int tr) | |
152 { | |
153 XDW_ANNOTATION_HANDLE annoation; | |
154 int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, page, x, y, NULL, &annoation, NULL); | |
155 if (api_result < 0) { | |
156 fprintf(stderr, "can't make annotation\n"); | |
157 return -1; | |
158 } | |
159 | |
160 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, string, 0, NULL); | |
161 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)(sz), 0, NULL); | |
162 if (tr) { | |
163 int color = XDW_COLOR_NONE; | |
164 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)(&color), 0, NULL); | |
165 } | |
166 return 0; | |
167 } | |
168 | |
169 void xdwaddpage(const char* file, int sp, int atena) { | |
170 XDW_DOCUMENT_HANDLE h = NULL; | |
171 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
172 int api_result = XDW_OpenDocumentHandle(file, &h, (XDW_OPEN_MODE*)&mode); | |
173 if (api_result < 0) { | |
174 fprintf(stderr, "can't open file\n"); | |
175 exit(1); | |
176 } | |
177 | |
178 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0}; | |
179 XDW_GetDocumentInformation(h, &info); | |
180 int last_page = info.nPages; | |
181 | |
182 int sz = 80; | |
183 int tr = 1; | |
184 char pagenum[10]; | |
185 | |
186 for (int p = 0; p < last_page; p++) { | |
187 sprintf(pagenum, "FW-%05d", p + sp); | |
188 api_result = xdwaddannotation(h, p + 1, 8598, 335, pagenum, &sz, tr); | |
189 if (atena) api_result = xdwaddannotation(h, p + 1, 1270, 23615, pagenum, &sz, tr); | |
190 if (api_result < 0) break; | |
191 } | |
192 | |
193 if (api_result >= 0) api_result = XDW_SaveDocument(h, NULL); | |
194 | |
195 XDW_CloseDocumentHandle(h, NULL); | |
196 } | |
197 | |
198 | |
199 */ | |
200 import "C" | |
201 | |
202 import ( | |
203 "encoding/csv" | |
204 "flag" | |
205 "fmt" | |
206 "io" | |
207 "io/ioutil" | |
208 "log" | |
209 "os" | |
210 "regexp" | |
211 "strings" | |
212 "time" | |
213 | |
214 "golang.org/x/text/encoding/japanese" | |
215 "golang.org/x/text/transform" | |
216 ) | |
217 | |
218 type Data struct { | |
219 Hno string | |
220 Page string | |
221 Zip string | |
222 SendTo string | |
223 } | |
224 | |
225 func (d *Data) ToCsv() string { | |
226 s := []string{d.Hno, d.Page, d.Zip, d.SendTo} | |
227 return strings.Join(s, ",") | |
228 } | |
229 | |
230 var ( | |
231 ver = "0.1" | |
232 | |
233 clean bool | |
234 skip bool | |
235 debug bool | |
236 xdwfile string | |
237 | |
238 txtfile = "fwtmp_txt.txt" | |
239 infofile = "fwtmp_info.csv" | |
240 orderfile = "order.csv" // input | |
241 pagefile1 = "fwtmp_page1.txt" // send to sisetsu | |
242 pagefile2 = "fwtmp_page2.txt" // send to home | |
243 output1 = "output1.xdw" | |
244 output2 = "output2.xdw" | |
245 ) | |
246 | |
247 func init() { | |
248 /* INITIALIZE FLAGS */ | |
249 flag.BoolVar(&clean, "c", false, "clean temporary files & exit") | |
250 flag.BoolVar(&skip, "e", false, "use existed files") | |
251 flag.BoolVar(&debug, "d", false, "debug mode") | |
252 flag.StringVar(&xdwfile, "i", "KBPV016G.xdw", "target xdw file") | |
253 } | |
254 | |
255 func main() { | |
256 flag.Parse() | |
257 | |
258 /* PRINT HEADER */ | |
259 fmt.Println("=================================================") | |
260 fmt.Println(" 負担割合証を... ") | |
261 fmt.Printf(" - fwgo [ver %s] -\n", ver) | |
262 fmt.Println("=================================================\n") | |
263 print_time("now") | |
264 fmt.Println("[0] start ...") | |
265 | |
266 /* CLEAN TEMPORARY DIRECTORY */ | |
267 os.Remove(output1) | |
268 os.Remove(output2) | |
269 if !skip { | |
270 clean_full() | |
271 } | |
272 if clean { | |
273 os.Exit(0) | |
274 } | |
275 print_time("check done") | |
276 | |
277 fmt.Println("[1] extract ...") | |
278 if !skip { | |
279 C.xdw2txt(C.CString(xdwfile), C.CString(txtfile)) | |
280 } | |
281 print_time("extract done.") | |
282 | |
283 c := make(chan int) | |
284 fmt.Println("[2] split ... (run background)") | |
285 go func() { | |
286 if !skip { | |
287 C.xdwsplit1(C.CString(xdwfile)) | |
288 } | |
289 print_time("split done.") | |
290 c <- 1 | |
291 }() | |
292 | |
293 fmt.Println("[3] analize ...") | |
294 data_hash, err := analize(txtfile, infofile) | |
295 if err != nil { | |
296 log.Fatal(err) | |
297 } | |
298 print_time("analize done.") | |
299 debug_print(debug, fmt.Sprintf("len = %d", len(data_hash))) | |
300 | |
301 fmt.Println("[4] read order ...") | |
302 h_order, n, err := read_order(orderfile) | |
303 if err != nil { | |
304 log.Fatal(err) | |
305 } | |
306 print_time("read order done.") | |
307 debug_print(debug, fmt.Sprintf("len = %d / %d", len(h_order), n)) | |
308 | |
309 fmt.Println("[5] make_list ...") | |
310 n, m, l, err := make_list(h_order, data_hash, pagefile1, pagefile2) | |
311 if err != nil { | |
312 log.Fatal(err) | |
313 } | |
314 print_time("make list done.") | |
315 debug_print(debug, fmt.Sprintf("order, kunai, kugai = %d, %d, %d", n, m, l)) | |
316 | |
317 <-c | |
318 | |
319 fmt.Println("[6] merge ...") | |
320 clean_mini() | |
321 C.xdwmerge(C.CString(pagefile1), C.CString(output1)) | |
322 print_time("merge 1/2 done.") | |
323 clean_mini() | |
324 C.xdwmerge(C.CString(pagefile2), C.CString(output2)) | |
325 print_time("merge 2/2 done.") | |
326 | |
327 fmt.Println("[7] page ...") | |
328 C.xdwaddpage(C.CString(output1), C.int(1), C.int(0)) | |
329 print_time("page 1/2 done.") | |
330 C.xdwaddpage(C.CString(output2), C.int(n + 1), C.int(1)) | |
331 print_time("page 2/2 done.") | |
332 | |
333 if !debug { | |
334 fmt.Println("[9] clean ...") | |
335 clean_full() | |
336 print_time("clean done.") | |
337 } | |
338 } | |
339 | |
340 func analize(txtfile, infofile string) (map[string]Data, error) { | |
341 hash := make(map[string]Data) | |
342 | |
343 c, err := ioutil.ReadFile(txtfile) | |
344 if err != nil { | |
345 return hash, err | |
346 } | |
347 r := strings.NewReader(string(c)) | |
348 tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) | |
349 b, err := ioutil.ReadAll(tr) | |
350 if err != nil { | |
351 return hash, err | |
352 } | |
353 | |
354 regHid := regexp.MustCompile(`05[0-9]{4}0[1238][0-9]{8}`) | |
355 regZip := regexp.MustCompile(`[0123456789]{3}-[0123456789]{4}`) | |
356 | |
357 var csv string | |
358 | |
359 buf := strings.Split(string(b), "生年月日年月日") | |
360 for p, v := range buf[:len(buf)-1] { | |
361 hid := regHid.FindString(v) | |
362 hno := hid[6:16] | |
363 | |
364 zips := regZip.FindAllString(v, -1) | |
365 if len(zips) != 2 { | |
366 fmt.Println("warnig:", hno, "have not 2 zip-pattern") | |
367 } | |
368 | |
369 s := strings.Split(v, zips[1]) | |
370 s = strings.Split(s[len(s)-1], " 様 ") | |
371 send := strings.ReplaceAll(s[0], " ", "") | |
372 | |
373 page := fmt.Sprintf("%05d", p + 1) | |
374 | |
375 data := Data { | |
376 Hno: hno, | |
377 Page: page, | |
378 Zip: zips[1], | |
379 SendTo: send, | |
380 } | |
381 hash[hno] = data | |
382 | |
383 csv += data.ToCsv() + "\n" | |
384 } | |
385 | |
386 if err := ioutil.WriteFile(infofile, []byte(csv), 0644); err != nil { | |
387 return hash, err | |
388 } | |
389 return hash, nil; | |
390 } | |
391 | |
392 func read_order(csvfile string) ([]string, int, error) { | |
393 var order []string | |
394 | |
395 c, err := ioutil.ReadFile(csvfile) | |
396 if err != nil { | |
397 return order, -1, err | |
398 } | |
399 r := strings.NewReader(string(c)) | |
400 tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) | |
401 b, err := ioutil.ReadAll(tr) | |
402 if err != nil { | |
403 return order, -1, err | |
404 } | |
405 | |
406 n := 0 | |
407 cr := csv.NewReader(strings.NewReader(string(b))) | |
408 for { | |
409 record, err := cr.Read() | |
410 if err == io.EOF { | |
411 break | |
412 } | |
413 if err != nil { | |
414 return order, n, err | |
415 } | |
416 | |
417 if strings.HasPrefix(record[0], "0") { | |
418 order = append(order, record[0]) | |
419 } | |
420 n++ | |
421 } | |
422 return order, n, nil | |
423 } | |
424 | |
425 func make_list(h_order []string, hash map[string]Data, pagefile1, pagefile2 string) (int, int, int, error) { | |
426 var n, m, l int | |
427 var list1, list2 []string | |
428 done := make(map[string]bool) | |
429 | |
430 for _, h := range h_order { | |
431 if _, ok := done[h]; !ok { | |
432 if data, ok := hash[h]; ok { | |
433 list1 = append(list1, data.Page) | |
434 done[h] = true | |
435 n++ | |
436 } | |
437 } | |
438 } | |
439 | |
440 for _, z := range []string{"014-00", "014-01", "014-08", "014-1413"} { | |
441 for _, data := range hash { | |
442 h := data.Hno | |
443 if _, ok := done[h]; !ok { | |
444 if strings.HasPrefix(data.Zip, z) { | |
445 list2 = append(list2, data.Page) | |
446 done[h] = true | |
447 m++ | |
448 } | |
449 } | |
450 } | |
451 } | |
452 | |
453 for _, data := range hash { | |
454 h := data.Hno | |
455 if _, ok := done[h]; !ok { | |
456 list2 = append(list2, data.Page) | |
457 done[h] = true | |
458 l++ | |
459 } | |
460 } | |
461 | |
462 if err := write_pagefile(pagefile1, list1); err != nil { | |
463 return n, m, l, err | |
464 } | |
465 if err := write_pagefile(pagefile2, list2); err != nil { | |
466 return n, m, l, err | |
467 } | |
468 return n, m, l, nil | |
469 } | |
470 | |
471 func write_pagefile(file string, list []string) error { | |
472 f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0755) | |
473 if err != nil { | |
474 return err | |
475 } | |
476 for _, p := range list { | |
477 fmt.Fprintf(f, "fwtmp_%s.xdw\n", p) | |
478 } | |
479 if err := f.Close(); err != nil { | |
480 return err | |
481 } | |
482 return nil | |
483 } | |
484 | |
485 func print_time(msg string) { | |
486 now := time.Now() | |
487 fmt.Printf("\t%v # %s\n", now, msg) | |
488 } | |
489 | |
490 func debug_print(debug bool, msg string) { | |
491 if debug { | |
492 fmt.Printf("\t%s\n", msg) | |
493 } | |
494 } | |
495 | |
496 func clean_full() error { | |
497 return clean_file("fwtmp_") | |
498 } | |
499 | |
500 func clean_mini() error { | |
501 return clean_file("fwtmp_b") | |
502 } | |
503 | |
504 func clean_file(prefix string) error { | |
505 files, err := ioutil.ReadDir(".") | |
506 if err != nil { | |
507 return err | |
508 } | |
509 | |
510 for _, file := range files { | |
511 if strings.HasPrefix(file.Name(), prefix) { | |
512 os.Remove(file.Name()) | |
513 continue | |
514 } | |
515 } | |
516 return err | |
517 } | |
518 |