Skip to content

Commit d368f79

Browse files
authored
initial commit
initial commit
1 parent 55a8b18 commit d368f79

File tree

1 file changed

+310
-0
lines changed

1 file changed

+310
-0
lines changed

sequence.go

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"encoding/csv"
6+
"fmt"
7+
"io/ioutil"
8+
"log"
9+
"math"
10+
"os"
11+
"strconv"
12+
"strings"
13+
//"sync"
14+
"time"
15+
)
16+
17+
var skillMap = map[string]string{
18+
"NMAAHC": "Main Menu",
19+
"NMAAHC 10": "Advance Passes",
20+
"NMAAHC 11": "Same Day/Walk Up Passes",
21+
"NMAAHC 12": "Cancel/Exchange Passes",
22+
"NMAAHC TICKET": "Obtain Passes Over Phone",
23+
"NMAAHC XFER VALID": "Valid Transfer",
24+
"NMAAHC SHOP": "Museum Shop",
25+
"NMAAHC CAFE": "Sweet Home Cafe",
26+
"NMAAHC 14": "New Group Reservation",
27+
"NMAAHC BusyNoAnswer": "Network Error/Busy",
28+
"NMAAHC NetInvalidNum": "Network Error/Busy",
29+
"NMAAHC 18": "Cancel Group Reservation",
30+
"NMAAHC MEM RENEW": "Donations, Gifts, New/Renew Membership",
31+
"NMAAHC MEM QUESTION": "Questions About Membership",
32+
"NMAAHC 17": "Donate Object or Collection",
33+
"NMAAHC 2": "Timed Entry Passes",
34+
"NMAAHC 3": "Group Reservations",
35+
"NMAAHC 4": "Membership & Donations",
36+
"NMAAHC 5": "Location & Hours",
37+
"NMAAHC 6": "Transportation & Parking",
38+
"NMAAHC 7": "Tours",
39+
"NMAAHC 8": "Accessibility",
40+
"NMAAHC 9": "Sweet Home Cafe and the Museum Shop",
41+
}
42+
43+
var TICKET string = "Wednesday"
44+
45+
var iID, iMID, iTIME, iCAMP, iCONTACT, iSKILL, iDATE int
46+
47+
type entry struct {
48+
assigned int
49+
values []string
50+
}
51+
52+
type sequence struct {
53+
seqID int
54+
entries map[int]entry
55+
}
56+
57+
type sequenceList struct {
58+
index int
59+
sequences map[int]sequence
60+
}
61+
62+
func (seqList *sequenceList) addSequence(seq *sequence) {
63+
seqList.sequences[seqList.index] = *seq
64+
seq.seqID = seqList.index
65+
seqList.index++
66+
67+
}
68+
69+
func (seq *sequence) addEntry(id int, ent *entry) {
70+
ent.assigned = seq.seqID
71+
seq.entries[id] = *ent
72+
73+
}
74+
75+
func (seq *sequence) merge(seq2 *sequence) {
76+
for id, ent := range seq2.entries {
77+
if _, ok := seq.entries[id]; !ok {
78+
seq.addEntry(id, &ent)
79+
80+
}
81+
82+
}
83+
84+
}
85+
86+
func (ent *entry) forTrace(entries map[int]*entry) (*sequence, error) {
87+
// if it is the beginning of a sequence, then add start the sequence with ent and delete it from entries
88+
if id, err := strconv.Atoi(ent.values[iID]); err != nil {
89+
return &sequence{}, err
90+
91+
} else {
92+
seq := &sequence{}
93+
seq.entries = make(map[int]entry)
94+
seq.addEntry(id, ent)
95+
defer delete(entries, id)
96+
for _, spawn := range entries {
97+
if spawn.assigned == -1 {
98+
if bytes.Equal([]byte(ent.values[iID]), []byte(spawn.values[iMID])) {
99+
if seq2, err := spawn.forTrace(entries); err != nil {
100+
return seq, err
101+
102+
} else {
103+
seq.merge(seq2)
104+
105+
}
106+
107+
}
108+
109+
}
110+
111+
}
112+
return seq, nil
113+
114+
}
115+
116+
}
117+
118+
func (seq *sequence) xferReason() string {
119+
for _, ent := range seq.entries {
120+
if ent.values[iSKILL] == "NMAAHC TICKET" {
121+
return "TICKETING"
122+
123+
} else if ent.values[iSKILL] == "NMAAHC MEM RENEW" ||
124+
ent.values[iSKILL] == "NMAAHC MEM QUESTION" {
125+
return "MEMBERSHIP"
126+
127+
}
128+
129+
}
130+
return ""
131+
132+
}
133+
134+
func isTDay(start_date time.Time) bool {
135+
start_year, start_month, _ := start_date.Date()
136+
month_start := time.Date(start_year, start_month, 1, 1, 1, 1, 1, time.UTC)
137+
for {
138+
if month_start.Weekday().String() == TICKET {
139+
break
140+
141+
} else {
142+
month_start = month_start.Add(time.Hour * 24)
143+
144+
}
145+
146+
}
147+
return start_date.Day() == month_start.Day()
148+
149+
}
150+
151+
func main() {
152+
sFile := "Data.csv"
153+
fileStr, err := ioutil.ReadFile(sFile)
154+
if err != nil {
155+
fmt.Println(err)
156+
157+
}
158+
str := string(fileStr)
159+
entries := make(map[int]*entry)
160+
seqList := sequenceList{0, make(map[int]sequence)}
161+
r := csv.NewReader(strings.NewReader(str))
162+
headers, err := r.Read()
163+
headers = append(headers, "S_ID", "TIME_30", "TIME_15", "CALL_SUM", "AREA", "WEEKDAY", "T_DAY")
164+
if err != nil {
165+
fmt.Println(err)
166+
}
167+
for i, sHeader := range headers {
168+
if sHeader == "contact_id" {
169+
iID = i
170+
171+
} else if sHeader == "master_contact_id" {
172+
iMID = i
173+
174+
} else if sHeader == "start_time" {
175+
iTIME = i
176+
177+
} else if sHeader == "campaign_name" {
178+
iCAMP = i
179+
180+
} else if sHeader == "skill_name" {
181+
iSKILL = i
182+
183+
} else if sHeader == "contact_name" {
184+
iCONTACT = i
185+
186+
} else if sHeader == "start_date" {
187+
iDATE = i
188+
189+
}
190+
191+
}
192+
for {
193+
record, err := r.Read()
194+
if err != nil {
195+
break
196+
197+
}
198+
// make each entry have an initial assigned = -1
199+
if record[iCAMP] == "NMAAHC" {
200+
if id, err := strconv.Atoi(record[iID]); err != nil {
201+
fmt.Println(err)
202+
203+
} else {
204+
entries[id] = &entry{-1, record}
205+
206+
}
207+
208+
}
209+
210+
}
211+
//var waitGroup sync.WaitGroup
212+
for _, ent := range entries {
213+
if ent.assigned == -1 {
214+
if bytes.Equal([]byte(ent.values[iID]), []byte(ent.values[iMID])) {
215+
if seq, err := ent.forTrace(entries); err != nil {
216+
fmt.Println(err)
217+
218+
} else {
219+
seqList.addSequence(seq)
220+
221+
}
222+
223+
}
224+
}
225+
226+
}
227+
//waitGroup.Wait()
228+
file, err := os.Create("callSequence.csv")
229+
w := csv.NewWriter(file)
230+
if err := w.Write(headers); err != nil {
231+
log.Fatalln(err)
232+
233+
}
234+
for sID, seq := range seqList.sequences {
235+
var index int = 1
236+
for _, ent := range seq.entries {
237+
timeStamp, err := time.Parse("15:04:05", ent.values[iTIME])
238+
if err != nil {
239+
fmt.Println(err)
240+
241+
}
242+
var intervals [2]string
243+
var iMin [2]int = [2]int{int(math.Floor(float64(timeStamp.Minute())/30.0) * 30),
244+
int(math.Floor(float64(timeStamp.Minute())/15.0) * 15)}
245+
for i := range intervals {
246+
if timeStamp.Hour() < 10 {
247+
intervals[i] += "0" + strconv.Itoa(timeStamp.Hour())
248+
249+
} else {
250+
intervals[i] += strconv.Itoa(timeStamp.Hour())
251+
252+
}
253+
if iMin[i] < 10 {
254+
intervals[i] += ":0" + strconv.Itoa(iMin[i])
255+
256+
} else {
257+
intervals[i] += ":" + strconv.Itoa(iMin[i])
258+
259+
}
260+
intervals[i] += ":00"
261+
262+
}
263+
if ent.values[iCONTACT] == "Outbound" {
264+
ent.values[iCONTACT] = func(s *sequence) string {
265+
for _, e := range s.entries {
266+
if e.values[iCONTACT] != "Outbound" {
267+
return e.values[iCONTACT]
268+
269+
}
270+
271+
}
272+
return ""
273+
274+
}(&seq)
275+
276+
}
277+
startDate, err := time.Parse("01/02/2006", ent.values[iDATE])
278+
if err != nil {
279+
fmt.Println(err)
280+
281+
}
282+
var AREA string
283+
if ent.values[iSKILL] == "NMAAHC XFER VALID" ||
284+
ent.values[iSKILL] == "NMAAHC BusyNoAnswer" ||
285+
ent.values[iSKILL] == "NMAAHC NetInvalidNum" {
286+
AREA = seq.xferReason() + " " + skillMap[ent.values[iSKILL]]
287+
288+
} else {
289+
AREA = skillMap[ent.values[iSKILL]]
290+
291+
}
292+
ent.values = append(ent.values, // Array being appended to
293+
strconv.Itoa(sID), intervals[0], intervals[1], strconv.Itoa(index), // Sequence ID, TIME_30, TIME_15
294+
AREA, startDate.Weekday().String(), strconv.FormatBool(isTDay(startDate))) // Call sum, AREA, WEEKDAY, T_DAY
295+
if err := w.Write(ent.values); err != nil {
296+
log.Fatalln(err)
297+
298+
}
299+
index = 0
300+
301+
}
302+
303+
}
304+
w.Flush()
305+
if err := w.Error(); err != nil {
306+
log.Fatal(err)
307+
308+
}
309+
310+
}

0 commit comments

Comments
 (0)