/
1800medicare.go
193 lines (163 loc) · 6.24 KB
/
1800medicare.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* #nosec G404 */
package main
import (
"bufio"
"fmt"
"golang.org/x/text/language"
"math/rand"
"os"
"path/filepath"
"time"
"golang.org/x/text/cases"
)
type field struct {
l int
v string
}
type record struct {
hicn, blk field
firstName, middleName, lastName field
dob field
addr1, addr2, addr3, city, state, zip5, zip4 field
gender field
encDate field
effDate, srcCode, mechCode, prefInd field
saEffDate, saSrcCode, saMechCode, saPrefInd field
acoID, acoName field
}
func main() {
rand.Seed(time.Now().UTC().UnixNano())
now := time.Now()
// 1-800-MEDICARE filename format: (T|P)#EFT.ON.ACO.NGD1800.DPRF.Dyymmdd.Thhmmsst
fileName := fmt.Sprintf("T#EFT.ON.ACO.NGD1800.DPRF.%s", now.Format("D060102.T1504050"))
outf, err := os.Create(filepath.Clean(fileName))
if err != nil {
panic(err)
}
_, err = outf.WriteString(fmt.Sprintf("HDR_BENEDATASHR%s\n", now.Format("20060102")))
if err != nil {
panic(err)
}
recCount := 0
for _, acoID := range []string{"A9990", "A9991", "A9992", "A9993", "A9994"} {
inf, err := os.Open(fmt.Sprintf("%s-HICNs", acoID))
if err != nil {
panic(err)
}
s := bufio.NewScanner(inf)
for s.Scan() {
// Randomly select HICNs from ACO for suppression records
if rand.Intn(2) == 0 {
continue
}
hicn := string(s.Bytes())
p := profile(hicn, acoID)
recs := records(p)
for _, r := range recs {
for _, f := range []field{r.hicn, r.blk, r.firstName, r.middleName, r.lastName, r.dob, r.addr1, r.addr2, r.addr3, r.city, r.state, r.zip5, r.zip4, r.gender, r.encDate, r.effDate, r.srcCode, r.mechCode, r.prefInd, r.saEffDate, r.saSrcCode, r.saMechCode, r.saPrefInd, r.acoID, r.acoName} {
_, err = outf.WriteString(fmt.Sprintf("%-"+fmt.Sprint(f.l)+"s", f.v))
if err != nil {
panic(err)
}
}
_, err = outf.WriteString("\n")
if err != nil {
panic(err)
}
}
recCount += len(recs)
}
_, err = outf.WriteString(fmt.Sprintf("TRL_BENEDATASHR%s%-10d", now.Format("20060102"), recCount))
if err != nil {
panic(err)
}
err = inf.Close()
if err != nil {
panic(err)
}
}
err = outf.Close()
if err != nil {
panic(err)
}
}
func profile(hicn string, acoID string) record {
dobMin, _ := time.Parse("2006-01-02", "1900-01-01")
dobMax := time.Now().Add(-65 * 365 * 24 * time.Hour)
p := record{
hicn: field{l: 11, v: hicn}, // HICN
blk: field{l: 10}, // Beneficiary link key
firstName: field{l: 30, v: randWord(1, 30)}, // Beneficiary first name
middleName: field{l: 30}, // Beneficiary middle name
lastName: field{l: 40, v: randWord(1, 30)}, // Beneficiary last name
dob: field{l: 8, v: ccyymmdd(dobMin, dobMax)}, // Beneficiary date of birth
addr1: field{l: 55, v: addr1()}, // Beneficiary address line 1
addr2: field{l: 55}, // Beneficiary address line 2
addr3: field{l: 55}, // Beneficiary address line 3
city: field{l: 40, v: randWord(1, 40)}, // Beneficiary city
state: field{l: 2, v: "ST"}, // Beneficiary state
zip5: field{l: 5, v: "00000"}, // Beneficiary first five digits of ZIP code
zip4: field{l: 4}, // Beneficiary last four digits of ZIP code
gender: field{l: 1, v: oneOfStr("M", "F", "U")}, // Beneficiary gender
acoID: field{l: 5, v: acoID}, // ACO identifier
acoName: field{l: 70, v: randWord(1, 66) + " ACO"}, // ACO legal name
}
return p
}
func records(profile record) []record {
// Create 0-3 suppression records for this profile
ct := rand.Intn(4)
encDtMin, encDtMax := time.Now().Add(-7*24*time.Hour), time.Now()
effDtMin, effDtMax := time.Now().Add(-7*24*time.Hour), time.Now().Add(3*24*time.Hour)
records := []record{}
for i := 0; i < ct; i++ {
r := profile
r.srcCode = field{l: 5, v: oneOfStr("1800", "")} // Beneficiary data sharing source code
r.saSrcCode = field{l: 5, v: oneOfStr("1-800", "")} // Beneficiary substance abuse data sharing source code
if r.srcCode.v == "" && r.saSrcCode.v == "" {
// One or both types of data sharing should have values
continue
}
r.encDate = field{l: 8, v: ccyymmdd(encDtMin, encDtMax)} // Encounter date
r.effDate = field{l: 8, v: ""} // Beneficiary data sharing effective date
r.mechCode = field{l: 1, v: ""} // Beneficiary option data sharing decision mechanism code
r.prefInd = field{l: 1, v: ""} // Beneficiary data sharing preference indicator
// If beneficiary data sharing source code is populated, also populate its associated fields (ICD v9.1 p.11)
if r.srcCode.v != "" {
r.effDate.v = ccyymmdd(effDtMin, effDtMax)
r.mechCode.v = "T"
r.prefInd.v = oneOfStr("Y", "N")
}
r.saEffDate = field{l: 8, v: ""} // Beneficiary substance abuse data sharing effective date
r.saMechCode = field{l: 1, v: ""} // Beneficiary option substance abuse decision mechanism code
r.saPrefInd = field{l: 1, v: ""} // Beneficiary substance abuse data sharing preference indicator
// If beneficiary substance abuse data sharing source code is populated, also populate its associated fields (ICD v9.1 p.11)
if r.saSrcCode.v != "" {
r.saEffDate.v = ccyymmdd(effDtMin, effDtMax)
r.saMechCode.v = "T"
r.saPrefInd.v = "N"
}
records = append(records, r)
}
return records
}
func ccyymmdd(min, max time.Time) string {
diffHrs := max.Sub(min).Hours()
dt := min.Add(time.Duration(rand.Float64()*diffHrs) * time.Hour)
return dt.Format("20060102")
}
func oneOfStr(strs ...string) string {
return strs[rand.Intn(len(strs))]
}
func randWord(minLen, maxLen int) string {
const letters = "abcdefghijklmnopqrstuvwxyz"
l := rand.Intn(maxLen-minLen) + minLen
w := ""
for i := 0; i < l; i++ {
w = w + string(letters[rand.Intn(len(letters))])
}
return cases.Title(language.Und).String(w)
}
func addr1() string {
return fmt.Sprintf("%d %s %s", rand.Intn(50000), randWord(1, 44), oneOfStr("St", "Ave", "Dr", "Blvd", "Way"))
}