Mercurial > mercurial > hgweb_kaigo.hg.cgi
comparison Perori/bk.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 bk.go: Insert Biko & Hatsuban | |
| 3 | |
| 4 Last Change: 2020-06-24 水 10:16:00. | |
| 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 char* xdw2txt(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 NULL; | |
| 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 // メイン処理 | |
| 39 char *lpszvalue, *all_lpszvalue; | |
| 40 long datasize[9999]; | |
| 41 for (int i = 1; i <= nPage; i++) { | |
| 42 datasize[i] = XDW_GetPageTextToMemory(h, i, NULL, 0, NULL); | |
| 43 datasize[0] += datasize[i]; | |
| 44 } | |
| 45 datasize[0] += nPage - 1; // for "\n" | |
| 46 all_lpszvalue = (char*)malloc(sizeof(char)*datasize[0]); | |
| 47 all_lpszvalue[0] = '\0'; | |
| 48 for (int i = 1; i <= nPage; i++) { | |
| 49 if (i < nPage) datasize[i]++; // for "\n" | |
| 50 lpszvalue = (char*)malloc(sizeof(char)*(datasize[i])); | |
| 51 XDW_GetPageTextToMemory(h, i, lpszvalue, datasize[i], NULL); | |
| 52 strcat(all_lpszvalue, lpszvalue); | |
| 53 if (i < nPage) strcat(all_lpszvalue, "\n"); | |
| 54 free(lpszvalue); | |
| 55 } | |
| 56 | |
| 57 XDW_CloseDocumentHandle(h, NULL); // 文書ハンドルを閉じる | |
| 58 return all_lpszvalue; | |
| 59 } | |
| 60 | |
| 61 int xdwhb(const char* in_file, const char* out_file, char* hb, const char* stxt) { | |
| 62 int x = 18000; | |
| 63 int y = 1200; | |
| 64 int sz = 110; | |
| 65 | |
| 66 char in_path[_MAX_PATH], out_path[_MAX_PATH]; | |
| 67 _fullpath(in_path, in_file, _MAX_PATH); | |
| 68 _fullpath(out_path, out_file, _MAX_PATH); | |
| 69 | |
| 70 XDW_DOCUMENT_HANDLE h = NULL; | |
| 71 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 72 | |
| 73 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 74 if (api_result < 0) return api_result; | |
| 75 | |
| 76 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 77 XDW_GetDocumentInformation(h, &info); | |
| 78 | |
| 79 int color = XDW_COLOR_NONE; | |
| 80 XDW_FOUND_HANDLE pFoundHandle = NULL; | |
| 81 for (int i = 0; i < info.nPages; i++) { | |
| 82 api_result = XDW_FindTextInPage(h, i + 1, stxt, NULL, &pFoundHandle, NULL); | |
| 83 if (pFoundHandle == NULL) continue; | |
| 84 | |
| 85 XDW_ANNOTATION_HANDLE annoation; | |
| 86 int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x, y, NULL, &annoation, NULL); | |
| 87 if (api_result < 0) return api_result; | |
| 88 | |
| 89 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, hb, 0, NULL); | |
| 90 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 91 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)&color, 0, NULL); | |
| 92 } | |
| 93 | |
| 94 XDW_SaveDocument(h, NULL); | |
| 95 XDW_CloseDocumentHandle(h, NULL); | |
| 96 | |
| 97 api_result = XDW_OptimizeDocument(in_path, out_path, NULL); | |
| 98 return 0; | |
| 99 } | |
| 100 | |
| 101 int xdwbiko(const char* in_file, const int page, const int r, char* biko, char* kubun) { | |
| 102 int x1 = 2000; | |
| 103 int y1 = 4680 + r * 2720; | |
| 104 int sz = 90; | |
| 105 int x2 = 18950; | |
| 106 int y2 = 5090 + r * 2720; | |
| 107 | |
| 108 char in_path[_MAX_PATH]; | |
| 109 _fullpath(in_path, in_file, _MAX_PATH); | |
| 110 | |
| 111 XDW_DOCUMENT_HANDLE h = NULL; | |
| 112 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 113 | |
| 114 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 115 if (api_result < 0) return api_result; | |
| 116 | |
| 117 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 118 XDW_GetDocumentInformation(h, &info); | |
| 119 | |
| 120 XDW_ANNOTATION_HANDLE annoation1, annoation2; | |
| 121 int color = XDW_COLOR_NONE; | |
| 122 | |
| 123 api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, page, x1, y1, NULL, &annoation1, NULL); | |
| 124 if (api_result < 0) return api_result; | |
| 125 api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, page, x2, y2, NULL, &annoation2, NULL); | |
| 126 if (api_result < 0) return api_result; | |
| 127 | |
| 128 api_result = XDW_SetAnnotationAttribute(h, annoation1, XDW_ATN_Text, XDW_ATYPE_STRING, biko, 0, NULL); | |
| 129 api_result = XDW_SetAnnotationAttribute(h, annoation1, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 130 api_result = XDW_SetAnnotationAttribute(h, annoation1, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)&color, 0, NULL); | |
| 131 | |
| 132 api_result = XDW_SetAnnotationAttribute(h, annoation2, XDW_ATN_Text, XDW_ATYPE_STRING, kubun, 0, NULL); | |
| 133 api_result = XDW_SetAnnotationAttribute(h, annoation2, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 134 api_result = XDW_SetAnnotationAttribute(h, annoation2, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)&color, 0, NULL); | |
| 135 | |
| 136 XDW_SaveDocument(h, NULL); | |
| 137 XDW_CloseDocumentHandle(h, NULL); | |
| 138 | |
| 139 return 0; | |
| 140 } | |
| 141 | |
| 142 int xdweraren(const char* in_file, const char* stxt) | |
| 143 { | |
| 144 int x = 1870; | |
| 145 int y = 4680; | |
| 146 int yoff = 2830; | |
| 147 int sz = 90; | |
| 148 | |
| 149 char in_path[_MAX_PATH]; | |
| 150 _fullpath(in_path, in_file, _MAX_PATH); | |
| 151 | |
| 152 XDW_DOCUMENT_HANDLE h = NULL; | |
| 153 XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; | |
| 154 | |
| 155 int api_result = XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode); | |
| 156 if (api_result < 0) return api_result; | |
| 157 | |
| 158 XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; | |
| 159 XDW_GetDocumentInformation(h, &info); | |
| 160 | |
| 161 XDW_FOUND_HANDLE pFoundHandle = NULL; | |
| 162 for (int i = 0; i < info.nPages; i++) { | |
| 163 api_result = XDW_FindTextInPage(h, i + 1, stxt, NULL, &pFoundHandle, NULL); | |
| 164 if (pFoundHandle != NULL) continue; | |
| 165 | |
| 166 for (int r = 0; r < 9; r++) { | |
| 167 XDW_ANNOTATION_HANDLE annoation; | |
| 168 int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, i + 1, x, y + r * yoff, NULL, &annoation, NULL); | |
| 169 if (api_result < 0) return api_result; | |
| 170 | |
| 171 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, " ", 0, NULL); | |
| 172 api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)&sz, 0, NULL); | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 XDW_SaveDocument(h, NULL); | |
| 177 XDW_CloseDocumentHandle(h, NULL); | |
| 178 | |
| 179 return 0; | |
| 180 } | |
| 181 | |
| 182 */ | |
| 183 import "C" | |
| 184 | |
| 185 import ( | |
| 186 "bufio" | |
| 187 "encoding/csv" | |
| 188 "fmt" | |
| 189 "flag" | |
| 190 "io/ioutil" | |
| 191 "log" | |
| 192 "os" | |
| 193 "regexp" | |
| 194 "strconv" | |
| 195 "strings" | |
| 196 "time" | |
| 197 | |
| 198 "golang.org/x/text/encoding/japanese" | |
| 199 "golang.org/x/text/transform" | |
| 200 ) | |
| 201 | |
| 202 // Constants | |
| 203 const ( | |
| 204 version = "0.5" | |
| 205 default_ccsvfile = "chosairai.csv" | |
| 206 default_icsvfile = "ikenshoirai.csv" | |
| 207 default_cxdwfile = "KBPC116G.xdw" | |
| 208 default_ixdwfile = "KBPB116G.xdw" | |
| 209 default_tmpxdw = "tmp.xdw" | |
| 210 default_cout = "outc.xdw" | |
| 211 default_iout = "outi.xdw" | |
| 212 default_lout = "xyz.csv" | |
| 213 ) | |
| 214 | |
| 215 var ( | |
| 216 hbi, hbc string // 発番 | |
| 217 start time.Time | |
| 218 | |
| 219 flg_hb int | |
| 220 flg_time bool | |
| 221 | |
| 222 re_hhsno, re_date, re_city, re_name, re_zensp *regexp.Regexp | |
| 223 ) | |
| 224 | |
| 225 func init(){ | |
| 226 os.Remove(default_cout) | |
| 227 os.Remove(default_iout) | |
| 228 os.Remove(default_lout) | |
| 229 | |
| 230 re_hhsno = regexp.MustCompile(`0[1238]00\d{6}`) | |
| 231 re_date = regexp.MustCompile(`((明治)|(大正)|(昭和)|(平成)|(令和)).{1,2}年.\d月.\d日`) | |
| 232 re_city = regexp.MustCompile(`(((平成)|(令和)).{1,2}年.\d月.\d日){2}...`) | |
| 233 re_name = regexp.MustCompile(`0[1238]00\d{6}.*((平成)|(令和)).{1,2}年.\d月.\d日`) | |
| 234 re_zensp = regexp.MustCompile(` {2,}`) | |
| 235 } | |
| 236 | |
| 237 func main() { | |
| 238 start = time.Now() | |
| 239 /* PRINT HEADER */ | |
| 240 fmt.Println("=======================================") | |
| 241 fmt.Println(" 備考を...する") | |
| 242 fmt.Printf(" - bk [ver %s] -\n", version) | |
| 243 fmt.Println("=======================================\n") | |
| 244 | |
| 245 | |
| 246 /* INITIALIZE FLAGS */ | |
| 247 today := time.Now().Format("20060102") | |
| 248 | |
| 249 flag.StringVar(&today, "d", today, "irai ymd (default today)") | |
| 250 flag.IntVar(&flg_hb, "b", 0, "set hatsuban (default 0)") | |
| 251 flag.BoolVar(&flg_time, "t", false, "print time") | |
| 252 | |
| 253 flag.Parse() | |
| 254 | |
| 255 /* USER INPUT */ | |
| 256 hbi = fmt.Sprintf("%d", flg_hb) | |
| 257 if flg_hb == 0 { | |
| 258 fmt.Print("発番 > ") | |
| 259 fmt.Scan(&hbi) | |
| 260 } | |
| 261 i, err := strconv.Atoi(hbi) | |
| 262 if err != nil { | |
| 263 log.Fatal(err) | |
| 264 } | |
| 265 hbc = fmt.Sprintf("%d", i + 1) | |
| 266 | |
| 267 /* READ BIKO FROM CSV */ | |
| 268 bhash, err := getBiko_fromCSV(default_ccsvfile, today) | |
| 269 if err != nil { | |
| 270 log.Fatal(err) | |
| 271 } | |
| 272 fmt.Println(" 備考データ読込 ... done") | |
| 273 step_start := print_time(start) | |
| 274 | |
| 275 /* READ KUBUN FROM CSV */ | |
| 276 khash, err := getKubun_fromCSV(default_icsvfile, bhash) | |
| 277 if err != nil { | |
| 278 log.Fatal(err) | |
| 279 } | |
| 280 fmt.Println(" 申請区分データ読込 ... done") | |
| 281 step_start = print_time(start) | |
| 282 | |
| 283 /* INSERT BIKO */ | |
| 284 var ctxt []string | |
| 285 copy_tmp(default_cxdwfile) | |
| 286 for p, t := range xdw2txt(default_cxdwfile) { | |
| 287 for r, hno := range re_hhsno.FindAllString(t, -1) { | |
| 288 if bk, ok := bhash[hno]; ok { | |
| 289 C.xdwbiko(C.CString(default_tmpxdw), C.int(p + 1), C.int(r), C.CString(bk), C.CString(khash[hno])) | |
| 290 } | |
| 291 } | |
| 292 ctxt = append(ctxt, t) | |
| 293 } | |
| 294 fmt.Println(" 備考と申請区分を追加 ... done") | |
| 295 step_start = print_time(step_start) | |
| 296 | |
| 297 /* INSERT HATSU-BAN & OPTIMIZE */ | |
| 298 stxt, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), "大仙広介") | |
| 299 C.xdwhb(C.CString(default_tmpxdw), C.CString(default_cout), C.CString(hbc), C.CString(stxt)) | |
| 300 fmt.Println(" 発番追加(調査依頼ファイル)... done") | |
| 301 step_start = print_time(step_start) | |
| 302 | |
| 303 /* ERASE RENRAKUSAKI */ | |
| 304 copy_tmp(default_ixdwfile) | |
| 305 C.xdweraren(C.CString(default_tmpxdw), C.CString(stxt)) | |
| 306 fmt.Println(" 連絡先消去 ... done") | |
| 307 step_start = print_time(step_start) | |
| 308 | |
| 309 /* INSERT HATSU-BAN & OPTIMIZE */ | |
| 310 C.xdwhb(C.CString(default_tmpxdw), C.CString(default_iout), C.CString(hbi), C.CString(stxt)) | |
| 311 fmt.Println(" 発番追加( 意見書依頼ファイル)... done") | |
| 312 step_start = print_time(step_start) | |
| 313 | |
| 314 /* CHOSA IRAI LIST */ | |
| 315 f, err := os.Create(default_lout) | |
| 316 if err != nil { | |
| 317 log.Fatal(err) | |
| 318 } | |
| 319 defer f.Close() | |
| 320 w := bufio.NewWriter(transform.NewWriter(f, japanese.ShiftJIS.NewEncoder())) | |
| 321 | |
| 322 header := []string{"申請日", "被保番", "氏名", "生年月日", "市町村", "-", "-", "-", "依頼日"} | |
| 323 fmt.Fprintln(w, strings.Join(header, ",")) | |
| 324 | |
| 325 var req string | |
| 326 for _, txt := range ctxt { | |
| 327 str := strings.TrimRight(txt, " ") | |
| 328 if strings.HasSuffix(str, "依頼書") { | |
| 329 req = re_date.FindString(str) | |
| 330 req = strings.Replace(req, " ", "", -1) | |
| 331 } else { | |
| 332 row := strings.Split(str, "〒") | |
| 333 for i := 0; i < len(row) - 1; i++ { | |
| 334 var app, hhsno, name, birth, city, empty string | |
| 335 | |
| 336 d := re_date.FindAllString(row[i], -1) | |
| 337 if len(d) > 0 { | |
| 338 birth = strings.Replace(d[0], " ", "", -1) | |
| 339 app = strings.Replace(d[1], " ", "", -1) | |
| 340 } | |
| 341 if re_hhsno.MatchString(row[i]) { | |
| 342 hhsno = "=\"" + re_hhsno.FindString(row[i]) + "\"" | |
| 343 } | |
| 344 if re_name.MatchString(row[i]) { | |
| 345 n := []rune(re_name.FindString(row[i])) | |
| 346 kana := string(n[10:36]) | |
| 347 kana = strings.Trim(kana, " ") | |
| 348 name = string(n[37:55]) | |
| 349 name = strings.Trim(name, " ") | |
| 350 name = re_zensp.ReplaceAllString(name, "") | |
| 351 name += "(" + kana + ")" | |
| 352 } | |
| 353 if re_city.MatchString(row[i]) { | |
| 354 c := []rune(re_city.FindString(row[i])) | |
| 355 city = string(c[len(c)-3:]) | |
| 356 city = strings.Replace(city, "仙北郡", "美郷町", -1) | |
| 357 } | |
| 358 | |
| 359 if hhsno != "" { | |
| 360 fields := []string{app, hhsno, name, birth, city, empty, empty, empty, req} | |
| 361 fmt.Fprintln(w, strings.Join(fields, ",")) | |
| 362 } | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 w.Flush() | |
| 367 | |
| 368 fmt.Println(" 調査依頼リスト作成 ... done") | |
| 369 step_start = print_time(step_start) | |
| 370 | |
| 371 /* CLEAN */ | |
| 372 os.Remove(default_tmpxdw) | |
| 373 fmt.Println(" 終了 ... end") | |
| 374 step_start = print_time(step_start) | |
| 375 } | |
| 376 | |
| 377 func getBiko_fromCSV(file, date string) (bikohash map[string]string, err error) { | |
| 378 bikohash = make(map[string]string) | |
| 379 | |
| 380 data, err := ioutil.ReadFile(file) | |
| 381 if err != nil { | |
| 382 return bikohash, err | |
| 383 } | |
| 384 | |
| 385 r := csv.NewReader(strings.NewReader(string(data))) | |
| 386 records, err := r.ReadAll() | |
| 387 if err != nil { | |
| 388 return bikohash, err | |
| 389 } | |
| 390 | |
| 391 for _, record := range records { | |
| 392 hno := strings.TrimSpace(record[0]) | |
| 393 iraiymd := strings.TrimSpace(record[5]) | |
| 394 if iraiymd != date { | |
| 395 continue | |
| 396 } | |
| 397 bikohash[hno] = record[3] | |
| 398 } | |
| 399 | |
| 400 return bikohash, nil | |
| 401 } | |
| 402 | |
| 403 func getKubun_fromCSV(file string, hhshash map[string]string) (kubunhash map[string]string, err error) { | |
| 404 kubunhash = make(map[string]string) | |
| 405 ymdhash := make(map[string]string) | |
| 406 | |
| 407 data, err := ioutil.ReadFile(file) | |
| 408 if err != nil { | |
| 409 return kubunhash, err | |
| 410 } | |
| 411 | |
| 412 r := csv.NewReader(strings.NewReader(string(data))) | |
| 413 records, err := r.ReadAll() | |
| 414 if err != nil { | |
| 415 return kubunhash, err | |
| 416 } | |
| 417 | |
| 418 for _, record := range records { | |
| 419 hno := strings.TrimSpace(record[0]) | |
| 420 if _, ok := hhshash[hno]; !ok { | |
| 421 continue | |
| 422 } | |
| 423 if ymd, ok := ymdhash[hno]; !ok || ymd < record[8] { | |
| 424 ymdhash[hno] = record[8] | |
| 425 } | |
| 426 var buf string | |
| 427 switch strings.TrimSpace(record[9]) { | |
| 428 case "01": | |
| 429 buf = "[新規]" | |
| 430 case "02": | |
| 431 buf = "[更新]" | |
| 432 case "10": | |
| 433 buf = "[支介]" | |
| 434 case "05": | |
| 435 buf = "[区変]" | |
| 436 case "03": | |
| 437 buf = "[転入]" | |
| 438 case "09": | |
| 439 buf = "[証交]" | |
| 440 } | |
| 441 kubun, _, _ := transform.String(japanese.ShiftJIS.NewEncoder(), buf) | |
| 442 kubunhash[hno] = kubun | |
| 443 } | |
| 444 | |
| 445 return kubunhash, nil | |
| 446 } | |
| 447 | |
| 448 | |
| 449 func copy_tmp(file string) error { | |
| 450 os.Remove(default_tmpxdw) | |
| 451 b, err := ioutil.ReadFile(file) | |
| 452 if err != nil { | |
| 453 return err | |
| 454 } | |
| 455 if err := ioutil.WriteFile(default_tmpxdw, b, 0644); err != nil { | |
| 456 return err | |
| 457 } | |
| 458 return nil | |
| 459 } | |
| 460 | |
| 461 func xdw2txt(file string) (txt []string) { | |
| 462 s := C.GoString(C.xdw2txt(C.CString(file))) | |
| 463 r := strings.NewReader(s) | |
| 464 tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) | |
| 465 buf := bufio.NewScanner(tr) | |
| 466 for buf.Scan() { | |
| 467 txt = append(txt, buf.Text()) | |
| 468 } | |
| 469 return | |
| 470 } | |
| 471 | |
| 472 func print_time(t time.Time) time.Time { | |
| 473 now := time.Now() | |
| 474 if !flg_time { | |
| 475 return now | |
| 476 } | |
| 477 elapsed := now.Sub(t) | |
| 478 total := now.Sub(start) | |
| 479 s := fmt.Sprintf("---- Elapsed: %v (total = %v) @ %02d:%02d\n", elapsed, total, now.Hour(), now.Minute()) | |
| 480 fmt.Print(s) | |
| 481 return now | |
| 482 } | |
| 483 |
